add more types

pull/7324/head
Ivan Hofer 5 years ago
parent 49b869b1dd
commit 4c48f95bce

@ -1,4 +1,4 @@
import './ambient'; import './ambient.d.ts';
export { export {
onMount, onMount,

@ -1,5 +1,31 @@
import { has_prop } from './utils'; import { has_prop } from './utils';
// marks a part in the code where types
// 1. should be improved or
// 2. where casting is needed in order to satisfy TypeScript
// a deeper look at these parts is needed to check if they can be replaced with a normal cast or if they currently contain a potential bug
type TODO<T = any> = T
type NodeEx = Node & {
claim_order?: number,
hydrate_init?: true,
actual_end_child?: NodeEx,
childNodes: NodeListOf<NodeEx>,
}
type HTMLInputElementEx = HTMLInputElement & {
__value: string
}
type HTMLSelectElementEx = HTMLSelectElement & {
__value: string
options: HTMLOptionElementEx[]
}
type HTMLOptionElementEx = HTMLOptionElement & {
__value: string
}
// Track which nodes are claimed during hydration. Unclaimed nodes can then be removed from the DOM // Track which nodes are claimed during hydration. Unclaimed nodes can then be removed from the DOM
// at the end of hydration without touching the remaining nodes. // at the end of hydration without touching the remaining nodes.
let is_hydrating = false; let is_hydrating = false;
@ -11,13 +37,6 @@ export function end_hydrating() {
is_hydrating = false; is_hydrating = false;
} }
type NodeEx = Node & {
claim_order?: number,
hydrate_init? : true,
actual_end_child?: NodeEx,
childNodes: NodeListOf<NodeEx>,
};
function upper_bound(low: number, high: number, key: (index: number) => number, value: number) { function upper_bound(low: number, high: number, key: (index: number) => number, value: number) {
// Return first index of value larger than input value in the range [low, high) // Return first index of value larger than input value in the range [low, high)
while (low < high) { while (low < high) {
@ -151,7 +170,7 @@ export function get_root_for_style(node: Node): ShadowRoot | Document {
if (root && (root as ShadowRoot).host) { if (root && (root as ShadowRoot).host) {
return root as ShadowRoot; return root as ShadowRoot;
} }
return node.ownerDocument; return node.ownerDocument as TODO<Document>;
} }
export function append_empty_stylesheet(node: Node) { export function append_empty_stylesheet(node: Node) {
@ -169,12 +188,12 @@ export function append_hydration(target: NodeEx, node: NodeEx) {
init_hydrate(target); init_hydrate(target);
if ((target.actual_end_child === undefined) || ((target.actual_end_child !== null) && (target.actual_end_child.parentElement !== target))) { if ((target.actual_end_child === undefined) || ((target.actual_end_child !== null) && (target.actual_end_child.parentElement !== target))) {
target.actual_end_child = target.firstChild; target.actual_end_child = target.firstChild as TODO<NodeEx>;
} }
// Skip nodes of undefined ordering // Skip nodes of undefined ordering
while ((target.actual_end_child !== null) && (target.actual_end_child.claim_order === undefined)) { while ((target.actual_end_child !== null) && ((target.actual_end_child as NodeEx).claim_order === undefined)) {
target.actual_end_child = target.actual_end_child.nextSibling; target.actual_end_child = (target.actual_end_child as NodeEx).nextSibling as TODO<ChildNode>;
} }
if (node !== target.actual_end_child) { if (node !== target.actual_end_child) {
@ -183,7 +202,7 @@ export function append_hydration(target: NodeEx, node: NodeEx) {
target.insertBefore(node, target.actual_end_child); target.insertBefore(node, target.actual_end_child);
} }
} else { } else {
target.actual_end_child = node.nextSibling; target.actual_end_child = node.nextSibling as ChildNode | undefined;
} }
} else if (node.parentNode !== target || node.nextSibling !== null) { } else if (node.parentNode !== target || node.nextSibling !== null) {
target.appendChild(node); target.appendChild(node);
@ -203,10 +222,27 @@ export function insert_hydration(target: NodeEx, node: NodeEx, anchor?: NodeEx)
} }
export function detach(node: Node) { export function detach(node: Node) {
node.parentNode.removeChild(node); (node.parentNode as TODO<Node>).removeChild(node);
} }
export function destroy_each(iterations, detaching) { // TODO: import this interface from /src/runtime/internal/Component.ts
interface Fragment {
key: string | null;
first: null;
/* create */ c: () => void;
/* claim */ l: (nodes: any) => void;
/* hydrate */ h: () => void;
/* mount */ m: (target: HTMLElement, anchor: any) => void;
/* update */ p: (ctx: any, dirty: any) => void;
/* measure */ r: () => void;
/* fix */ f: () => void;
/* animate */ a: () => void;
/* intro */ i: (local: any) => void;
/* outro */ o: (local: any) => void;
/* destroy */ d: (detaching: 0 | 1) => void;
}
export function destroy_each(iterations: Fragment[], detaching: 0 | 1) {
for (let i = 0; i < iterations.length; i += 1) { for (let i = 0; i < iterations.length; i += 1) {
if (iterations[i]) iterations[i].d(detaching); if (iterations[i]) iterations[i].d(detaching);
} }
@ -256,32 +292,28 @@ export function listen(node: EventTarget, event: string, handler: EventListenerO
return () => node.removeEventListener(event, handler, options); return () => node.removeEventListener(event, handler, options);
} }
export function prevent_default(fn) { export function prevent_default<E extends Event>(fn: (event: E) => void) {
return function(event) { return function (this: unknown, event: E) {
event.preventDefault(); event.preventDefault();
// @ts-ignore
return fn.call(this, event); return fn.call(this, event);
}; };
} }
export function stop_propagation(fn) { export function stop_propagation<E extends Event>(fn: (event: E) => void) {
return function(event) { return function (this: unknown, event: E) {
event.stopPropagation(); event.stopPropagation();
// @ts-ignore
return fn.call(this, event); return fn.call(this, event);
}; };
} }
export function self(fn) { export function self<E extends Event>(fn: (event: E) => void) {
return function(event) { return function (this: unknown, event: E) {
// @ts-ignore
if (event.target === this) fn.call(this, event); if (event.target === this) fn.call(this, event);
}; };
} }
export function trusted(fn) { export function trusted<E extends Event>(fn: (event: E) => void) {
return function(event) { return function (this: unknown, event: E) {
// @ts-ignore
if (event.isTrusted) fn.call(this, event); if (event.isTrusted) fn.call(this, event);
}; };
} }
@ -291,20 +323,20 @@ export function attr(node: Element, attribute: string, value?: string) {
else if (node.getAttribute(attribute) !== value) node.setAttribute(attribute, value); else if (node.getAttribute(attribute) !== value) node.setAttribute(attribute, value);
} }
export function set_attributes(node: Element & ElementCSSInlineStyle, attributes: { [x: string]: string }) { export function set_attributes<N extends Element & ElementCSSInlineStyle>(node: N, attributes: { [K in keyof N]: N[K] }) {
// @ts-ignore // @ts-ignore
const descriptors = Object.getOwnPropertyDescriptors(node.__proto__); const descriptors = Object.getOwnPropertyDescriptors(node.__proto__);
for (const key in attributes) { for (const key in attributes) {
if (attributes[key] == null) { if (attributes[key] == null) {
node.removeAttribute(key); node.removeAttribute(key);
} else if (key === 'style') { } else if (key === 'style') {
node.style.cssText = attributes[key]; node.style.cssText = attributes[key] as unknown as TODO<string>;
} else if (key === '__value') { } else if (key === '__value') {
(node as any).value = node[key] = attributes[key]; (node as any).value = node[key] = attributes[key];
} else if (descriptors[key] && descriptors[key].set) { } else if (descriptors[key] && descriptors[key].set) {
node[key] = attributes[key]; node[key] = attributes[key];
} else { } else {
attr(node, key, attributes[key]); attr(node, key, attributes[key] as unknown as TODO<string>);
} }
} }
} }
@ -315,19 +347,20 @@ export function set_svg_attributes(node: Element & ElementCSSInlineStyle, attrib
} }
} }
export function set_custom_element_data(node, prop, value) { export function set_custom_element_data(node: Element, prop: string, value: string) {
if (prop in node) { if (prop in node) {
node[prop] = typeof node[prop] === 'boolean' && value === '' ? true : value; //@ts-ignore
node[prop] = typeof node[(prop as keyof typeof node)] === 'boolean' && value === '' ? true : value;
} else { } else {
attr(node, prop, value); attr(node, prop, value);
} }
} }
export function xlink_attr(node, attribute, value) { export function xlink_attr(node: Element, attribute: string, value: string) {
node.setAttributeNS('http://www.w3.org/1999/xlink', attribute, value); node.setAttributeNS('http://www.w3.org/1999/xlink', attribute, value);
} }
export function get_binding_group_value(group, __value, checked) { export function get_binding_group_value(group: HTMLInputElementEx[], __value: string, checked: boolean) {
const value = new Set(); const value = new Set();
for (let i = 0; i < group.length; i += 1) { for (let i = 0; i < group.length; i += 1) {
if (group[i].checked) value.add(group[i].__value); if (group[i].checked) value.add(group[i].__value);
@ -338,11 +371,11 @@ export function get_binding_group_value(group, __value, checked) {
return Array.from(value); return Array.from(value);
} }
export function to_number(value) { export function to_number(value: TODO) {
return value === '' ? null : +value; return value === '' ? null : +value;
} }
export function time_ranges_to_array(ranges) { export function time_ranges_to_array(ranges: TimeRanges) {
const array = []; const array = [];
for (let i = 0; i < ranges.length; i += 1) { for (let i = 0; i < ranges.length; i += 1) {
array.push({ start: ranges.start(i), end: ranges.end(i) }); array.push({ start: ranges.start(i), end: ranges.end(i) });
@ -353,7 +386,10 @@ export function time_ranges_to_array(ranges) {
type ChildNodeEx = ChildNode & NodeEx; type ChildNodeEx = ChildNode & NodeEx;
type ChildNodeArray = ChildNodeEx[] & { type ChildNodeArray = ChildNodeEx[] & {
claim_info?: { claim_info?: ClaimInfo
}
type ClaimInfo = {
/** /**
* The index of the last claimed element * The index of the last claimed element
*/ */
@ -363,7 +399,6 @@ type ChildNodeArray = ChildNodeEx[] & {
*/ */
total_claimed: number; total_claimed: number;
} }
};
export function children(element: Element) { export function children(element: Element) {
return Array.from(element.childNodes); return Array.from(element.childNodes);
@ -375,13 +410,13 @@ function init_claim_info(nodes: ChildNodeArray) {
} }
} }
function claim_node<R extends ChildNodeEx>(nodes: ChildNodeArray, predicate: (node: ChildNodeEx) => node is R, processNode: (node: ChildNodeEx) => ChildNodeEx | undefined, createNode: () => R, dontUpdateLastIndex: boolean = false) { function claim_node<R extends ChildNodeEx>(nodes: ChildNodeArray, predicate: (node: ChildNodeEx) => node is R, processNode: (node: R) => R | undefined, createNode: () => R, dontUpdateLastIndex: boolean = false) {
// Try to find nodes in an order such that we lengthen the longest increasing subsequence // Try to find nodes in an order such that we lengthen the longest increasing subsequence
init_claim_info(nodes); init_claim_info(nodes);
const resultNode = (() => { const resultNode = (() => {
// We first try to find an element after the previous one // We first try to find an element after the previous one
for (let i = nodes.claim_info.last_index; i < nodes.length; i++) { for (let i = (nodes.claim_info as TODO<ClaimInfo>).last_index; i < nodes.length; i++) {
const node = nodes[i]; const node = nodes[i];
if (predicate(node)) { if (predicate(node)) {
@ -393,7 +428,7 @@ function claim_node<R extends ChildNodeEx>(nodes: ChildNodeArray, predicate: (no
nodes[i] = replacement; nodes[i] = replacement;
} }
if (!dontUpdateLastIndex) { if (!dontUpdateLastIndex) {
nodes.claim_info.last_index = i; (nodes.claim_info as TODO<ClaimInfo>).last_index = i;
} }
return node; return node;
} }
@ -402,7 +437,7 @@ function claim_node<R extends ChildNodeEx>(nodes: ChildNodeArray, predicate: (no
// Otherwise, we try to find one before // Otherwise, we try to find one before
// We iterate in reverse so that we don't go too far back // We iterate in reverse so that we don't go too far back
for (let i = nodes.claim_info.last_index - 1; i >= 0; i--) { for (let i = (nodes.claim_info as TODO<ClaimInfo>).last_index - 1; i >= 0; i--) {
const node = nodes[i]; const node = nodes[i];
if (predicate(node)) { if (predicate(node)) {
@ -414,10 +449,10 @@ function claim_node<R extends ChildNodeEx>(nodes: ChildNodeArray, predicate: (no
nodes[i] = replacement; nodes[i] = replacement;
} }
if (!dontUpdateLastIndex) { if (!dontUpdateLastIndex) {
nodes.claim_info.last_index = i; (nodes.claim_info as TODO<ClaimInfo>).last_index = i;
} else if (replacement === undefined) { } else if (replacement === undefined) {
// Since we spliced before the last_index, we decrease it // Since we spliced before the last_index, we decrease it
nodes.claim_info.last_index--; (nodes.claim_info as TODO<ClaimInfo>).last_index--;
} }
return node; return node;
} }
@ -427,16 +462,16 @@ function claim_node<R extends ChildNodeEx>(nodes: ChildNodeArray, predicate: (no
return createNode(); return createNode();
})(); })();
resultNode.claim_order = nodes.claim_info.total_claimed; resultNode.claim_order = (nodes.claim_info as TODO<ClaimInfo>).total_claimed;
nodes.claim_info.total_claimed += 1; (nodes.claim_info as TODO<ClaimInfo>).total_claimed += 1;
return resultNode; return resultNode;
} }
function claim_element_base(nodes: ChildNodeArray, name: string, attributes: { [key: string]: boolean }, create_element: (name: string) => Element | SVGElement) { function claim_element_base(nodes: ChildNodeArray, name: string, attributes: { [key: string]: boolean }, create_element: (name: string) => Element | SVGElement) {
return claim_node<Element | SVGElement>( return claim_node<Element | SVGElement>(
nodes, nodes,
(node: ChildNode): node is Element | SVGElement => node.nodeName === name, (node): node is Element | SVGElement => node.nodeName === name,
(node: Element) => { (node) => {
const remove = []; const remove = [];
for (let j = 0; j < node.attributes.length; j++) { for (let j = 0; j < node.attributes.length; j++) {
const attribute = node.attributes[j]; const attribute = node.attributes[j];
@ -459,11 +494,11 @@ export function claim_svg_element(nodes: ChildNodeArray, name: string, attribute
return claim_element_base(nodes, name, attributes, svg_element); return claim_element_base(nodes, name, attributes, svg_element);
} }
export function claim_text(nodes: ChildNodeArray, data) { export function claim_text(nodes: ChildNodeArray, data: string) {
return claim_node<Text>( return claim_node<Text>(
nodes, nodes,
(node: ChildNode): node is Text => node.nodeType === 3, (node): node is Text => node.nodeType === 3,
(node: Text) => { (node) => {
const dataStr = '' + data; const dataStr = '' + data;
if (node.data.startsWith(dataStr)) { if (node.data.startsWith(dataStr)) {
if (node.data.length !== dataStr.length) { if (node.data.length !== dataStr.length) {
@ -478,21 +513,21 @@ export function claim_text(nodes: ChildNodeArray, data) {
); );
} }
export function claim_space(nodes) { export function claim_space(nodes: ChildNodeArray) {
return claim_text(nodes, ' '); return claim_text(nodes, ' ');
} }
function find_comment(nodes, text, start) { function find_comment(nodes: ChildNodeArray, text: string, start: number) {
for (let i = start; i < nodes.length; i += 1) { for (let i = start; i < nodes.length; i += 1) {
const node = nodes[i]; const node = nodes[i];
if (node.nodeType === 8 /* comment node */ && node.textContent.trim() === text) { if (node.nodeType === 8 /* comment node */ && (node.textContent as TODO<string>).trim() === text) {
return i; return i;
} }
} }
return nodes.length; return nodes.length;
} }
export function claim_html_tag(nodes) { export function claim_html_tag(nodes: ChildNodeArray) {
// find html opening tag // find html opening tag
const start_index = find_comment(nodes, 'HTML_TAG_START', 0); const start_index = find_comment(nodes, 'HTML_TAG_START', 0);
const end_index = find_comment(nodes, 'HTML_TAG_END', start_index); const end_index = find_comment(nodes, 'HTML_TAG_END', start_index);
@ -506,22 +541,22 @@ export function claim_html_tag(nodes) {
detach(html_tag_nodes[html_tag_nodes.length - 1]); detach(html_tag_nodes[html_tag_nodes.length - 1]);
const claimed_nodes = html_tag_nodes.slice(1, html_tag_nodes.length - 1); const claimed_nodes = html_tag_nodes.slice(1, html_tag_nodes.length - 1);
for (const n of claimed_nodes) { for (const n of claimed_nodes) {
n.claim_order = nodes.claim_info.total_claimed; n.claim_order = (nodes.claim_info as TODO<ClaimInfo>).total_claimed;
nodes.claim_info.total_claimed += 1; (nodes.claim_info as TODO<ClaimInfo>).total_claimed += 1;
} }
return new HtmlTagHydration(claimed_nodes); return new HtmlTagHydration(claimed_nodes);
} }
export function set_data(text, data) { export function set_data(text: Text, data: string) {
data = '' + data; data = '' + data;
if (text.wholeText !== data) text.data = data; if (text.wholeText !== data) text.data = data;
} }
export function set_input_value(input, value) { export function set_input_value(input: HTMLInputElement, value: string | null) {
input.value = value == null ? '' : value; input.value = value == null ? '' : value;
} }
export function set_input_type(input, type) { export function set_input_type(input: HTMLInputElement, type: string) {
try { try {
input.type = type; input.type = type;
} catch (e) { } catch (e) {
@ -529,7 +564,7 @@ export function set_input_type(input, type) {
} }
} }
export function set_style(node, key, value, important) { export function set_style(node: HTMLElement, key: string, value: string, important: boolean) {
if (value === null) { if (value === null) {
node.style.removeProperty(key); node.style.removeProperty(key);
} else { } else {
@ -537,7 +572,7 @@ export function set_style(node, key, value, important) {
} }
} }
export function select_option(select, value) { export function select_option(select: HTMLSelectElementEx, value: string) {
for (let i = 0; i < select.options.length; i += 1) { for (let i = 0; i < select.options.length; i += 1) {
const option = select.options[i]; const option = select.options[i];
@ -550,20 +585,20 @@ export function select_option(select, value) {
select.selectedIndex = -1; // no option should be selected select.selectedIndex = -1; // no option should be selected
} }
export function select_options(select, value) { export function select_options(select: HTMLSelectElementEx, value: string) {
for (let i = 0; i < select.options.length; i += 1) { for (let i = 0; i < select.options.length; i += 1) {
const option = select.options[i]; const option = select.options[i];
option.selected = ~value.indexOf(option.__value); option.selected = ~value.indexOf(option.__value) as unknown as TODO<boolean>;
} }
} }
export function select_value(select) { export function select_value(select: HTMLSelectElementEx) {
const selected_option = select.querySelector(':checked') || select.options[0]; const selected_option = (select.querySelector(':checked') || select.options[0]) as HTMLOptionElementEx;
return selected_option && selected_option.__value; return selected_option && selected_option.__value;
} }
export function select_multiple_value(select) { export function select_multiple_value(select: HTMLSelectElement) {
return [].map.call(select.querySelectorAll(':checked'), option => option.__value); return [].map.call(select.querySelectorAll(':checked'), (option: HTMLOptionElementEx) => option.__value);
} }
// unfortunately this can't be a constant as that wouldn't be tree-shakeable // unfortunately this can't be a constant as that wouldn't be tree-shakeable
@ -607,13 +642,13 @@ export function add_resize_listener(node: HTMLElement, fn: () => void) {
if (crossorigin) { if (crossorigin) {
iframe.src = "data:text/html,<script>onresize=function(){parent.postMessage(0,'*')}</script>"; iframe.src = "data:text/html,<script>onresize=function(){parent.postMessage(0,'*')}</script>";
unsubscribe = listen(window, 'message', (event: MessageEvent) => { unsubscribe = listen(window, 'message', ((event: MessageEvent) => {
if (event.source === iframe.contentWindow) fn(); if (event.source === iframe.contentWindow) fn();
}); }) as TODO<EventListener>);
} else { } else {
iframe.src = 'about:blank'; iframe.src = 'about:blank';
iframe.onload = () => { iframe.onload = () => {
unsubscribe = listen(iframe.contentWindow, 'resize', fn); unsubscribe = listen(iframe.contentWindow as TODO<Window>, 'resize', fn);
}; };
} }
@ -630,13 +665,14 @@ export function add_resize_listener(node: HTMLElement, fn: () => void) {
}; };
} }
export function toggle_class(element, name, toggle) { export function toggle_class(element: HTMLElement, name: string, toggle: true) {
// TODO: why not use `element.classList.toggle` ?
element.classList[toggle ? 'add' : 'remove'](name); element.classList[toggle ? 'add' : 'remove'](name);
} }
export function custom_event<T = any>(type: string, detail?: T, bubbles: boolean = false) { export function custom_event<T = any>(type: string, detail?: T, bubbles: boolean = false) {
const e: CustomEvent<T> = document.createEvent('CustomEvent'); const e: CustomEvent<T> = document.createEvent('CustomEvent');
e.initCustomEvent(type, bubbles, false, detail); e.initCustomEvent(type, bubbles, false, detail as TODO<T>);
return e; return e;
} }
@ -650,11 +686,14 @@ export class HtmlTag {
// html tag nodes // html tag nodes
n: ChildNode[]; n: ChildNode[];
// target // target
//@ts-ignore
t: HTMLElement; t: HTMLElement;
// anchor // anchor
//@ts-ignore
a: HTMLElement; a: HTMLElement;
constructor() { constructor() {
//@ts-ignore
this.e = this.n = null; this.e = this.n = null;
} }
@ -662,13 +701,14 @@ export class HtmlTag {
this.h(html); this.h(html);
} }
m(html: string, target: HTMLElement, anchor: HTMLElement = null) { m(html: string, target: HTMLElement, anchor: HTMLElement | null = null) {
if (!this.e) { if (!this.e) {
this.e = element(target.nodeName as keyof HTMLElementTagNameMap); this.e = element(target.nodeName as keyof HTMLElementTagNameMap);
this.t = target; this.t = target;
this.c(html); this.c(html);
} }
//@ts-ignore
this.i(anchor); this.i(anchor);
} }
@ -677,7 +717,7 @@ export class HtmlTag {
this.n = Array.from(this.e.childNodes); this.n = Array.from(this.e.childNodes);
} }
i(anchor) { i(anchor: Node) {
for (let i = 0; i < this.n.length; i += 1) { for (let i = 0; i < this.n.length; i += 1) {
insert(this.t, this.n[i], anchor); insert(this.t, this.n[i], anchor);
} }
@ -700,6 +740,7 @@ export class HtmlTagHydration extends HtmlTag {
constructor(claimed_nodes?: ChildNode[]) { constructor(claimed_nodes?: ChildNode[]) {
super(); super();
//@ts-ignore
this.e = this.n = null; this.e = this.n = null;
this.l = claimed_nodes; this.l = claimed_nodes;
} }
@ -710,7 +751,7 @@ export class HtmlTagHydration extends HtmlTag {
super.c(html); super.c(html);
} }
} }
i(anchor) { i(anchor: NodeEx) {
for (let i = 0; i < this.n.length; i += 1) { for (let i = 0; i < this.n.length; i += 1) {
insert_hydration(this.t, this.n[i], anchor); insert_hydration(this.t, this.n[i], anchor);
} }
@ -718,17 +759,17 @@ export class HtmlTagHydration extends HtmlTag {
} }
export function attribute_to_object(attributes: NamedNodeMap) { export function attribute_to_object(attributes: NamedNodeMap) {
const result = {}; const result: Record<string, string> = {};
for (const attribute of attributes) { for (const attribute of attributes as unknown as Iterable<Attr>) {
result[attribute.name] = attribute.value; result[attribute.name] = attribute.value;
} }
return result; return result;
} }
export function get_custom_elements_slots(element: HTMLElement) { export function get_custom_elements_slots(element: HTMLElement) {
const result = {}; const result: Record<string, true> = {};
element.childNodes.forEach((node: Element) => { element.childNodes.forEach((node) => {
result[node.slot || 'default'] = true; result[(node as TODO<Element>).slot || 'default'] = true;
}); });
return result; return result;
} }

@ -27,13 +27,11 @@ export function blank_object(): {} {
return Object.create(null); return Object.create(null);
} }
type FunctionWithoutArguments = () => unknown export function run(fn: Function) {
export function run(fn: FunctionWithoutArguments) {
return fn(); return fn();
} }
export function run_all(fns: FunctionWithoutArguments[]) { export function run_all(fns: Function[]) {
fns.forEach(run); fns.forEach(run);
} }
@ -59,7 +57,7 @@ export function not_equal(a: unknown, b: unknown) {
return a != a ? b == b : a !== b; return a != a ? b == b : a !== b;
} }
export function is_empty(obj: Record<string | number | symbol, unknown>) { export function is_empty(obj: Record<PropertyKey, unknown>) {
return Object.keys(obj).length === 0; return Object.keys(obj).length === 0;
} }
@ -147,21 +145,21 @@ export function get_all_dirty_from_scope($$scope) {
return -1; return -1;
} }
export function exclude_internal_props(props) { export function exclude_internal_props<P extends Record<PropertyKey, unknown>>(props: P) {
const result = {}; const result: Partial<P> = {};
for (const k in props) if (k[0] !== '$') result[k] = props[k]; for (const k in props) if (k[0] !== '$') result[k] = props[k];
return result; return result;
} }
export function compute_rest_props(props, keys) { export function compute_rest_props<P extends Record<PropertyKey, unknown>>(props: P, keys: string[] | Set<string>) {
const rest = {}; const rest: Partial<P> = {};
keys = new Set(keys); keys = new Set(keys);
for (const k in props) if (!keys.has(k) && k[0] !== '$') rest[k] = props[k]; for (const k in props) if (!keys.has(k) && k[0] !== '$') rest[k] = props[k];
return rest; return rest;
} }
export function compute_slots(slots) { export function compute_slots<S extends Map<string, unknown>>(slots: S) {
const result = {}; const result = {} as Record<keyof S, true>;
for (const key in slots) { for (const key in slots) {
result[key] = true; result[key] = true;
} }

@ -1,17 +1,7 @@
{ {
"extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"moduleResolution": "node",
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"target": "ESNext",
"isolatedModules": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": "../../", "baseUrl": "../../",
"allowJs": true,
"checkJs": true,
"paths": { "paths": {
"$runtime/*": ["src/runtime/*"] "$runtime/*": ["src/runtime/*"]
}, },

@ -6,7 +6,7 @@
// target node v8+ (https://node.green/) // target node v8+ (https://node.green/)
// the only missing feature is Array.prototype.values // the only missing feature is Array.prototype.values
"lib": ["es2017"], "lib": ["es2017", "DOM"],
"target": "es2017", "target": "es2017",
"declaration": true, "declaration": true,

Loading…
Cancel
Save