Convert src/runtime/internal/dev.ts to JavaScript

pull/8569/head
S. Elliott Johnson 3 years ago
parent c7fd1c69d2
commit ea4e7931e4

@ -1,206 +1,224 @@
import { import { custom_event, append, append_hydration, insert, insert_hydration, detach, listen, attr } from './dom';
custom_event,
append,
append_hydration,
insert,
insert_hydration,
detach,
listen,
attr
} from './dom';
import { SvelteComponent } from './Component'; import { SvelteComponent } from './Component';
import { is_void } from '../../shared/utils/names'; import { is_void } from '../../shared/utils/names';
import { contenteditable_truthy_values } from './utils'; import { contenteditable_truthy_values } from './utils';
/** @param {string} type
export function dispatch_dev<T = any>(type: string, detail?: T) { * @param {T} detail
document.dispatchEvent( * @returns {void}
custom_event(type, { version: '__VERSION__', ...detail }, { bubbles: true }) */
); export function dispatch_dev(type, detail) {
document.dispatchEvent(custom_event(type, { version: '__VERSION__', ...detail }, { bubbles: true }));
} }
/** @param {Node} target
export function append_dev(target: Node, node: Node) { * @param {Node} node
dispatch_dev('SvelteDOMInsert', { target, node }); * @returns {void}
append(target, node); */
export function append_dev(target, node) {
dispatch_dev('SvelteDOMInsert', { target, node });
append(target, node);
} }
/** @param {Node} target
export function append_hydration_dev(target: Node, node: Node) { * @param {Node} node
dispatch_dev('SvelteDOMInsert', { target, node }); * @returns {void}
append_hydration(target, node); */
export function append_hydration_dev(target, node) {
dispatch_dev('SvelteDOMInsert', { target, node });
append_hydration(target, node);
} }
/** @param {Node} target
export function insert_dev(target: Node, node: Node, anchor?: Node) { * @param {Node} node
dispatch_dev('SvelteDOMInsert', { target, node, anchor }); * @param {Node} anchor
insert(target, node, anchor); * @returns {void}
*/
export function insert_dev(target, node, anchor) {
dispatch_dev('SvelteDOMInsert', { target, node, anchor });
insert(target, node, anchor);
} }
/** @param {Node} target
export function insert_hydration_dev(target: Node, node: Node, anchor?: Node) { * @param {Node} node
dispatch_dev('SvelteDOMInsert', { target, node, anchor }); * @param {Node} anchor
insert_hydration(target, node, anchor); * @returns {void}
*/
export function insert_hydration_dev(target, node, anchor) {
dispatch_dev('SvelteDOMInsert', { target, node, anchor });
insert_hydration(target, node, anchor);
} }
/** @param {Node} node
export function detach_dev(node: Node) { * @returns {void}
dispatch_dev('SvelteDOMRemove', { node }); */
detach(node); export function detach_dev(node) {
dispatch_dev('SvelteDOMRemove', { node });
detach(node);
} }
/** @param {Node} before
export function detach_between_dev(before: Node, after: Node) { * @param {Node} after
while (before.nextSibling && before.nextSibling !== after) { * @returns {void}
detach_dev(before.nextSibling); */
} export function detach_between_dev(before, after) {
while (before.nextSibling && before.nextSibling !== after) {
detach_dev(before.nextSibling);
}
} }
/** @param {Node} after
export function detach_before_dev(after: Node) { * @returns {void}
while (after.previousSibling) { */
detach_dev(after.previousSibling); export function detach_before_dev(after) {
} while (after.previousSibling) {
detach_dev(after.previousSibling);
}
} }
/** @param {Node} before
export function detach_after_dev(before: Node) { * @returns {void}
while (before.nextSibling) { */
detach_dev(before.nextSibling); export function detach_after_dev(before) {
} while (before.nextSibling) {
detach_dev(before.nextSibling);
}
} }
/** @param {Node} node
export function listen_dev( * @param {string} event
node: Node, * @param {EventListenerOrEventListenerObject} handler
event: string, * @param {boolean | AddEventListenerOptions | EventListenerOptions} options
handler: EventListenerOrEventListenerObject, * @param {boolean} has_prevent_default
options?: boolean | AddEventListenerOptions | EventListenerOptions, * @param {boolean} has_stop_propagation
has_prevent_default?: boolean, * @param {boolean} has_stop_immediate_propagation
has_stop_propagation?: boolean, * @returns {() => void}
has_stop_immediate_propagation?: boolean */
) { export function listen_dev(node, event, handler, options, has_prevent_default, has_stop_propagation, has_stop_immediate_propagation) {
const modifiers = const modifiers = options === true ? ['capture'] : options ? Array.from(Object.keys(options)) : [];
options === true ? ['capture'] : options ? Array.from(Object.keys(options)) : []; if (has_prevent_default)
if (has_prevent_default) modifiers.push('preventDefault'); modifiers.push('preventDefault');
if (has_stop_propagation) modifiers.push('stopPropagation'); if (has_stop_propagation)
if (has_stop_immediate_propagation) modifiers.push('stopImmediatePropagation'); modifiers.push('stopPropagation');
if (has_stop_immediate_propagation)
dispatch_dev('SvelteDOMAddEventListener', { node, event, handler, modifiers }); modifiers.push('stopImmediatePropagation');
dispatch_dev('SvelteDOMAddEventListener', { node, event, handler, modifiers });
const dispose = listen(node, event, handler, options); const dispose = listen(node, event, handler, options);
return () => { return () => {
dispatch_dev('SvelteDOMRemoveEventListener', { node, event, handler, modifiers }); dispatch_dev('SvelteDOMRemoveEventListener', { node, event, handler, modifiers });
dispose(); dispose();
}; };
} }
/** @param {Element} node
export function attr_dev(node: Element, attribute: string, value?: string) { * @param {string} attribute
attr(node, attribute, value); * @param {string} value
* @returns {void}
if (value == null) dispatch_dev('SvelteDOMRemoveAttribute', { node, attribute }); */
else dispatch_dev('SvelteDOMSetAttribute', { node, attribute, value }); export function attr_dev(node, attribute, value) {
attr(node, attribute, value);
if (value == null)
dispatch_dev('SvelteDOMRemoveAttribute', { node, attribute });
else
dispatch_dev('SvelteDOMSetAttribute', { node, attribute, value });
} }
/** @param {Element} node
export function prop_dev(node: Element, property: string, value?: any) { * @param {string} property
node[property] = value; * @param {any} value
* @returns {void}
dispatch_dev('SvelteDOMSetProperty', { node, property, value }); */
export function prop_dev(node, property, value) {
node[property] = value;
dispatch_dev('SvelteDOMSetProperty', { node, property, value });
} }
/** @param {HTMLElement} node
export function dataset_dev(node: HTMLElement, property: string, value?: any) { * @param {string} property
node.dataset[property] = value; * @param {any} value
* @returns {void}
dispatch_dev('SvelteDOMSetDataset', { node, property, value }); */
export function dataset_dev(node, property, value) {
node.dataset[property] = value;
dispatch_dev('SvelteDOMSetDataset', { node, property, value });
} }
/** @param {Text} text
export function set_data_dev(text: Text, data: unknown) { * @param {unknown} data
data = '' + data; * @returns {void}
if (text.data === data) return; */
dispatch_dev('SvelteDOMSetData', { node: text, data }); export function set_data_dev(text, data) {
text.data = data as string; data = '' + data;
if (text.data === data)
return;
dispatch_dev('SvelteDOMSetData', { node: text, data });
text.data = data;
} }
/** @param {Text} text
export function set_data_contenteditable_dev(text: Text, data: unknown) { * @param {unknown} data
data = '' + data; * @returns {void}
if (text.wholeText === data) return; */
dispatch_dev('SvelteDOMSetData', { node: text, data }); export function set_data_contenteditable_dev(text, data) {
text.data = data as string; data = '' + data;
if (text.wholeText === data)
return;
dispatch_dev('SvelteDOMSetData', { node: text, data });
text.data = data;
} }
/** @param {Text} text
export function set_data_maybe_contenteditable_dev(text: Text, data: unknown, attr_value: string) { * @param {unknown} data
if (~contenteditable_truthy_values.indexOf(attr_value)) { * @param {string} attr_value
set_data_contenteditable_dev(text, data); * @returns {void}
} else { */
set_data_dev(text, data); export function set_data_maybe_contenteditable_dev(text, data, attr_value) {
} if (~contenteditable_truthy_values.indexOf(attr_value)) {
set_data_contenteditable_dev(text, data);
}
else {
set_data_dev(text, data);
}
} }
/** @returns {void} */
export function validate_each_argument(arg) { export function validate_each_argument(arg) {
if (typeof arg !== 'string' && !(arg && typeof arg === 'object' && 'length' in arg)) { if (typeof arg !== 'string' && !(arg && typeof arg === 'object' && 'length' in arg)) {
let msg = '{#each} only iterates over array-like objects.'; let msg = '{#each} only iterates over array-like objects.';
if (typeof Symbol === 'function' && arg && Symbol.iterator in arg) { if (typeof Symbol === 'function' && arg && Symbol.iterator in arg) {
msg += ' You can use a spread to convert this iterable into an array.'; msg += ' You can use a spread to convert this iterable into an array.';
} }
throw new Error(msg); throw new Error(msg);
} }
} }
/** @returns {void} */
export function validate_slots(name, slot, keys) { export function validate_slots(name, slot, keys) {
for (const slot_key of Object.keys(slot)) { for (const slot_key of Object.keys(slot)) {
if (!~keys.indexOf(slot_key)) { if (!~keys.indexOf(slot_key)) {
console.warn(`<${name}> received an unexpected slot "${slot_key}".`); console.warn(`<${name}> received an unexpected slot "${slot_key}".`);
} }
} }
} }
/** @param {unknown} tag
export function validate_dynamic_element(tag: unknown) { * @returns {void}
const is_string = typeof tag === 'string'; */
if (tag && !is_string) { export function validate_dynamic_element(tag) {
throw new Error('<svelte:element> expects "this" attribute to be a string.'); const is_string = typeof tag === 'string';
} if (tag && !is_string) {
throw new Error('<svelte:element> expects "this" attribute to be a string.');
}
} }
/** @param {undefined | string} tag
export function validate_void_dynamic_element(tag: undefined | string) { * @returns {void}
if (tag && is_void(tag)) { */
console.warn(`<svelte:element this="${tag}"> is self-closing and cannot have content.`); export function validate_void_dynamic_element(tag) {
} if (tag && is_void(tag)) {
console.warn(`<svelte:element this="${tag}"> is self-closing and cannot have content.`);
}
} }
/** @returns {any} */
export function construct_svelte_component_dev(component, props) { export function construct_svelte_component_dev(component, props) {
const error_message = 'this={...} of <svelte:component> should specify a Svelte component.'; const error_message = 'this={...} of <svelte:component> should specify a Svelte component.';
try { try {
const instance = new component(props); const instance = new component(props);
if (!instance.$$ || !instance.$set || !instance.$on || !instance.$destroy) { if (!instance.$$ || !instance.$set || !instance.$on || !instance.$destroy) {
throw new Error(error_message); throw new Error(error_message);
} }
return instance; return instance;
} catch (err) { }
const { message } = err; catch (err) {
if (typeof message === 'string' && message.indexOf('is not a constructor') !== -1) { const { message } = err;
throw new Error(error_message); if (typeof message === 'string' && message.indexOf('is not a constructor') !== -1) {
} else { throw new Error(error_message);
throw err; }
} else {
} throw err;
} }
}
export interface SvelteComponentDev<
Props extends Record<string, any> = any,
Events extends Record<string, any> = any,
Slots extends Record<string, any> = any // eslint-disable-line @typescript-eslint/no-unused-vars
> {
$set(props?: Partial<Props>): void;
$on<K extends Extract<keyof Events, string>>(
type: K,
callback: ((e: Events[K]) => void) | null | undefined
): () => void;
$destroy(): void;
[accessor: string]: any;
}
export interface ComponentConstructorOptions<
Props extends Record<string, any> = Record<string, any>
> {
target: Element | Document | ShadowRoot;
anchor?: Element;
props?: Props;
context?: Map<any, any>;
hydrate?: boolean;
intro?: boolean;
$$inline?: boolean;
} }
/** /**
* Base class for Svelte components with some minor dev-enhancements. Used when dev=true. * Base class for Svelte components with some minor dev-enhancements. Used when dev=true.
* *
@ -224,135 +242,86 @@ export interface ComponentConstructorOptions<
* </script> * </script>
* <MyComponent foo={'bar'} /> * <MyComponent foo={'bar'} />
* ``` * ```
* @extends SvelteComponent
*/ */
export class SvelteComponentDev< export class SvelteComponentDev extends SvelteComponent {
Props extends Record<string, any> = any, /**
Events extends Record<string, any> = any, * @private
Slots extends Record<string, any> = any * For type checking capabilities only.
> extends SvelteComponent { * Does not exist at runtime.
/** * ### DO NOT USE!
* @private */
* For type checking capabilities only. $$prop_def = undefined;
* Does not exist at runtime. /**
* ### DO NOT USE! * @private
*/ * For type checking capabilities only.
$$prop_def: Props; * Does not exist at runtime.
/** * ### DO NOT USE!
* @private */
* For type checking capabilities only. $$events_def = undefined;
* Does not exist at runtime. /**
* ### DO NOT USE! * @private
*/ * For type checking capabilities only.
$$events_def: Events; * Does not exist at runtime.
/** * ### DO NOT USE!
* @private */
* For type checking capabilities only. $$slot_def = undefined;
* Does not exist at runtime. constructor(options) {
* ### DO NOT USE! if (!options || (!options.target && !options.$$inline)) {
*/ throw new Error("'target' is a required option");
$$slot_def: Slots; }
super();
constructor(options: ComponentConstructorOptions<Props>) { }
if (!options || (!options.target && !options.$$inline)) { /** @returns {void} */
throw new Error("'target' is a required option"); $destroy() {
} super.$destroy();
this.$destroy = () => {
super(); console.warn('Component was already destroyed'); // eslint-disable-line no-console
} };
}
$destroy() { /** @returns {void} */
super.$destroy(); $capture_state() { }
this.$destroy = () => { /** @returns {void} */
console.warn('Component was already destroyed'); // eslint-disable-line no-console $inject_state() { }
};
}
$capture_state() {}
$inject_state() {}
} }
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface SvelteComponentTyped<
Props extends Record<string, any> = any,
Events extends Record<string, any> = any,
Slots extends Record<string, any> = any
> extends SvelteComponentDev<Props, Events, Slots> {}
/** /**
* @deprecated Use `SvelteComponent` instead. See PR for more information: https://github.com/sveltejs/svelte/pull/8512 * @deprecated Use `SvelteComponent` instead. See PR for more information: https://github.com/sveltejs/svelte/pull/8512
* @extends SvelteComponentDev<Props, Events, Slots>
*/ */
export class SvelteComponentTyped< export class SvelteComponentTyped extends SvelteComponentDev {
Props extends Record<string, any> = any, }
Events extends Record<string, any> = any, /** @returns {() => void} */
Slots extends Record<string, any> = any export function loop_guard(timeout) {
> extends SvelteComponentDev<Props, Events, Slots> {} const start = Date.now();
return () => {
if (Date.now() - start > timeout) {
throw new Error('Infinite loop detected');
}
};
}
/** /**
* Convenience type to get the type of a Svelte component. Useful for example in combination with * @typedef {Class<HTMLElement>} ComponentType
* dynamic components using `<svelte:component>`. * @template {SvelteComponentDev} [Component=SvelteComponentDev]
*
* Example:
* ```html
* <script lang="ts">
* import type { ComponentType, SvelteComponent } from 'svelte';
* import Component1 from './Component1.svelte';
* import Component2 from './Component2.svelte';
*
* const component: ComponentType = someLogic() ? Component1 : Component2;
* const componentOfCertainSubType: ComponentType<SvelteComponent<{ needsThisProp: string }>> = someLogic() ? Component1 : Component2;
* </script>
*
* <svelte:component this={component} />
* <svelte:component this={componentOfCertainSubType} needsThisProp="hello" />
* ```
*/ */
export type ComponentType<Component extends SvelteComponentDev = SvelteComponentDev> = (new (
options: ComponentConstructorOptions<
Component extends SvelteComponentDev<infer Props> ? Props : Record<string, any>
>
) => Component) & {
/** The custom element version of the component. Only present if compiled with the `customElement` compiler option */
element?: typeof HTMLElement;
};
/** /**
* Convenience type to get the props the given component expects. Example: * @typedef {Component extends SvelteComponentDev<infer Props> ? Props : never} ComponentProps
* ```html * @template {SvelteComponent} Component
* <script lang="ts">
* import type { ComponentProps } from 'svelte';
* import Component from './Component.svelte';
*
* const props: ComponentProps<Component> = { foo: 'bar' }; // Errors if these aren't the correct props
* </script>
* ```
*/ */
export type ComponentProps<Component extends SvelteComponent> =
Component extends SvelteComponentDev<infer Props> ? Props : never;
/** /**
* Convenience type to get the events the given component expects. Example: * @typedef {Component extends SvelteComponentDev<any, infer Events> ? Events : never} ComponentEvents
* ```html * @template {SvelteComponent} Component
* <script lang="ts">
* import type { ComponentEvents } from 'svelte';
* import Component from './Component.svelte';
*
* function handleCloseEvent(event: ComponentEvents<Component>['close']) {
* console.log(event.detail);
* }
* </script>
*
* <Component on:close={handleCloseEvent} />
* ```
*/ */
export type ComponentEvents<Component extends SvelteComponent> =
Component extends SvelteComponentDev<any, infer Events> ? Events : never;
export function loop_guard(timeout) { /** @typedef {Object} SvelteComponentDev */
const start = Date.now(); /** @typedef {Object} ComponentConstructorOptions
return () => { * @property {Element|Document|ShadowRoot} target
if (Date.now() - start > timeout) { * @property {Element} [anchor]
throw new Error('Infinite loop detected'); * @property {Props} [props]
} * @property {Map<any,any>} [context]
}; * @property {boolean} [hydrate]
} * @property {boolean} [intro]
* @property {boolean} [$$inline]
*/
/** @typedef {Object} SvelteComponentTyped */
Loading…
Cancel
Save