From ea97fe22daec39e3dced47018f31ff7c8ec10be0 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 12 Mar 2024 13:40:02 -0400 Subject: [PATCH] chore: move legacy code (#10775) * move event modifier code * move more legacy code * oops --------- Co-authored-by: Rich Harris --- .../client/dom/legacy/event-modifiers.js | 83 +++++++ .../internal/client/dom/legacy/lifecycle.js | 54 +++++ .../src/internal/client/dom/legacy/misc.js | 68 ++++++ packages/svelte/src/internal/client/render.js | 208 +----------------- packages/svelte/src/internal/index.js | 3 + 5 files changed, 209 insertions(+), 207 deletions(-) create mode 100644 packages/svelte/src/internal/client/dom/legacy/event-modifiers.js create mode 100644 packages/svelte/src/internal/client/dom/legacy/lifecycle.js create mode 100644 packages/svelte/src/internal/client/dom/legacy/misc.js diff --git a/packages/svelte/src/internal/client/dom/legacy/event-modifiers.js b/packages/svelte/src/internal/client/dom/legacy/event-modifiers.js new file mode 100644 index 0000000000..f41a740903 --- /dev/null +++ b/packages/svelte/src/internal/client/dom/legacy/event-modifiers.js @@ -0,0 +1,83 @@ +/** + * @param {(event: Event, ...args: Array) => void} fn + * @returns {(event: Event, ...args: unknown[]) => void} + */ +export function trusted(fn) { + return function (...args) { + var event = /** @type {Event} */ (args[0]); + if (event.isTrusted) { + // @ts-ignore + fn.apply(this, args); + } + }; +} + +/** + * @param {(event: Event, ...args: Array) => void} fn + * @returns {(event: Event, ...args: unknown[]) => void} + */ +export function self(fn) { + return function (...args) { + var event = /** @type {Event} */ (args[0]); + // @ts-ignore + if (event.target === this) { + // @ts-ignore + fn.apply(this, args); + } + }; +} + +/** + * @param {(event: Event, ...args: Array) => void} fn + * @returns {(event: Event, ...args: unknown[]) => void} + */ +export function stopPropagation(fn) { + return function (...args) { + var event = /** @type {Event} */ (args[0]); + event.stopPropagation(); + // @ts-ignore + return fn.apply(this, args); + }; +} + +/** + * @param {(event: Event, ...args: Array) => void} fn + * @returns {(event: Event, ...args: unknown[]) => void} + */ +export function once(fn) { + var ran = false; + + return function (...args) { + if (ran) return; + ran = true; + + // @ts-ignore + return fn.apply(this, args); + }; +} + +/** + * @param {(event: Event, ...args: Array) => void} fn + * @returns {(event: Event, ...args: unknown[]) => void} + */ +export function stopImmediatePropagation(fn) { + return function (...args) { + var event = /** @type {Event} */ (args[0]); + event.stopImmediatePropagation(); + // @ts-ignore + return fn.apply(this, args); + }; +} + +/** + * @param {(event: Event, ...args: Array) => void} fn + * @returns {(event: Event, ...args: unknown[]) => void} + */ +export function preventDefault(fn) { + return function (...args) { + var event = /** @type {Event} */ (args[0]); + event.preventDefault(); + // @ts-ignore + return fn.apply(this, args); + }; +} diff --git a/packages/svelte/src/internal/client/dom/legacy/lifecycle.js b/packages/svelte/src/internal/client/dom/legacy/lifecycle.js new file mode 100644 index 0000000000..d7ec2efa08 --- /dev/null +++ b/packages/svelte/src/internal/client/dom/legacy/lifecycle.js @@ -0,0 +1,54 @@ +import { run } from '../../../common.js'; +import { pre_effect, user_effect } from '../../reactivity/effects.js'; +import { current_component_context, deep_read_state, get, untrack } from '../../runtime.js'; + +/** + * Legacy-mode only: Call `onMount` callbacks and set up `beforeUpdate`/`afterUpdate` effects + */ +export function init() { + const context = /** @type {import('#client').ComponentContext} */ (current_component_context); + const callbacks = context.u; + + if (!callbacks) return; + + // beforeUpdate + if (callbacks.b.length) { + pre_effect(() => { + observe_all(context); + callbacks.b.forEach(run); + }); + } + + // onMount (must run before afterUpdate) + user_effect(() => { + const fns = untrack(() => callbacks.m.map(run)); + return () => { + for (const fn of fns) { + if (typeof fn === 'function') { + fn(); + } + } + }; + }); + + // afterUpdate + if (callbacks.a.length) { + user_effect(() => { + observe_all(context); + callbacks.a.forEach(run); + }); + } +} + +/** + * Invoke the getter of all signals associated with a component + * so they can be registered to the effect this function is called in. + * @param {import('#client').ComponentContext} context + */ +function observe_all(context) { + if (context.d) { + for (const signal of context.d) get(signal); + } + + deep_read_state(context.s); +} diff --git a/packages/svelte/src/internal/client/dom/legacy/misc.js b/packages/svelte/src/internal/client/dom/legacy/misc.js new file mode 100644 index 0000000000..a4b52efe28 --- /dev/null +++ b/packages/svelte/src/internal/client/dom/legacy/misc.js @@ -0,0 +1,68 @@ +import { set, source } from '../../reactivity/sources.js'; +import { get } from '../../runtime.js'; +import { is_array } from '../../utils.js'; + +/** + * Under some circumstances, imports may be reactive in legacy mode. In that case, + * they should be using `reactive_import` as part of the transformation + * @param {() => any} fn + */ +export function reactive_import(fn) { + var s = source(0); + + return function () { + if (arguments.length === 1) { + set(s, get(s) + 1); + return arguments[0]; + } else { + get(s); + return fn(); + } + }; +} + +/** + * @this {any} + * @param {Record} $$props + * @param {Event} event + * @returns {void} + */ +export function bubble_event($$props, event) { + var events = /** @type {Record} */ ($$props.$$events)?.[ + event.type + ]; + + var callbacks = is_array(events) ? events.slice() : events == null ? [] : [events]; + + for (var fn of callbacks) { + // Preserve "this" context + fn.call(this, event); + } +} + +/** + * Used to simulate `$on` on a component instance when `legacy.componentApi` is `true` + * @param {Record} $$props + * @param {string} event_name + * @param {Function} event_callback + */ +export function add_legacy_event_listener($$props, event_name, event_callback) { + $$props.$$events ||= {}; + $$props.$$events[event_name] ||= []; + $$props.$$events[event_name].push(event_callback); +} + +/** + * Used to simulate `$set` on a component instance when `legacy.componentApi` is `true`. + * Needs component accessors so that it can call the setter of the prop. Therefore doesn't + * work for updating props in `$$props` or `$$restProps`. + * @this {Record} + * @param {Record} $$new_props + */ +export function update_legacy_props($$new_props) { + for (var key in $$new_props) { + if (key in this) { + this[key] = $$new_props[key]; + } + } +} diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index 75c37326ad..6b9f183ea3 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -22,16 +22,9 @@ import { push, pop, current_component_context, - get, deep_read_state } from './runtime.js'; -import { - render_effect, - effect, - pre_effect, - user_effect, - destroy_effect -} from './reactivity/effects.js'; +import { render_effect, effect, destroy_effect } from './reactivity/effects.js'; import { current_hydration_fragment, get_hydration_fragment, @@ -40,9 +33,7 @@ import { set_current_hydration_fragment } from './hydration.js'; import { array_from, define_property, get_descriptors, is_array, object_assign } from './utils.js'; -import { run } from '../common.js'; import { bind_transition } from './transitions.js'; -import { source, set } from './reactivity/sources.js'; import { ROOT_BLOCK } from './constants.js'; /** @type {Set} */ @@ -61,90 +52,6 @@ export function svg_replace(node) { return first_child; } -/** - * @param {(event: Event, ...args: Array) => void} fn - * @returns {(event: Event, ...args: unknown[]) => void} - */ -export function trusted(fn) { - return function (...args) { - const event = /** @type {Event} */ (args[0]); - if (event.isTrusted) { - // @ts-ignore - fn.apply(this, args); - } - }; -} - -/** - * @param {(event: Event, ...args: Array) => void} fn - * @returns {(event: Event, ...args: unknown[]) => void} - */ -export function self(fn) { - return function (...args) { - const event = /** @type {Event} */ (args[0]); - // @ts-ignore - if (event.target === this) { - // @ts-ignore - fn.apply(this, args); - } - }; -} - -/** - * @param {(event: Event, ...args: Array) => void} fn - * @returns {(event: Event, ...args: unknown[]) => void} - */ -export function stopPropagation(fn) { - return function (...args) { - const event = /** @type {Event} */ (args[0]); - event.stopPropagation(); - // @ts-ignore - return fn.apply(this, args); - }; -} - -/** - * @param {(event: Event, ...args: Array) => void} fn - * @returns {(event: Event, ...args: unknown[]) => void} - */ -export function once(fn) { - let ran = false; - return function (...args) { - if (ran) { - return; - } - ran = true; - // @ts-ignore - return fn.apply(this, args); - }; -} - -/** - * @param {(event: Event, ...args: Array) => void} fn - * @returns {(event: Event, ...args: unknown[]) => void} - */ -export function stopImmediatePropagation(fn) { - return function (...args) { - const event = /** @type {Event} */ (args[0]); - event.stopImmediatePropagation(); - // @ts-ignore - return fn.apply(this, args); - }; -} - -/** - * @param {(event: Event, ...args: Array) => void} fn - * @returns {(event: Event, ...args: unknown[]) => void} - */ -export function preventDefault(fn) { - return function (...args) { - const event = /** @type {Event} */ (args[0]); - event.preventDefault(); - // @ts-ignore - return fn.apply(this, args); - }; -} - /** * @param {string} event_name * @param {Element} dom @@ -1201,116 +1108,3 @@ function get_root_for_style(node) { } return /** @type {Document} */ (node.ownerDocument); } - -/** - * Legacy-mode only: Call `onMount` callbacks and set up `beforeUpdate`/`afterUpdate` effects - */ -export function init() { - const context = /** @type {import('./types.js').ComponentContext} */ (current_component_context); - const callbacks = context.u; - - if (!callbacks) return; - - // beforeUpdate - if (callbacks.b.length) { - pre_effect(() => { - observe_all(context); - callbacks.b.forEach(run); - }); - } - - // onMount (must run before afterUpdate) - user_effect(() => { - const fns = untrack(() => callbacks.m.map(run)); - return () => { - for (const fn of fns) { - if (typeof fn === 'function') { - fn(); - } - } - }; - }); - - // afterUpdate - if (callbacks.a.length) { - user_effect(() => { - observe_all(context); - callbacks.a.forEach(run); - }); - } -} - -/** - * Invoke the getter of all signals associated with a component - * so they can be registered to the effect this function is called in. - * @param {import('./types.js').ComponentContext} context - */ -function observe_all(context) { - if (context.d) { - for (const signal of context.d) get(signal); - } - - deep_read_state(context.s); -} - -/** - * Under some circumstances, imports may be reactive in legacy mode. In that case, - * they should be using `reactive_import` as part of the transformation - * @param {() => any} fn - */ -export function reactive_import(fn) { - const s = source(0); - return function () { - if (arguments.length === 1) { - set(s, get(s) + 1); - return arguments[0]; - } else { - get(s); - return fn(); - } - }; -} - -/** - * @this {any} - * @param {Record} $$props - * @param {Event} event - * @returns {void} - */ -export function bubble_event($$props, event) { - var events = /** @type {Record} */ ($$props.$$events)?.[ - event.type - ]; - var callbacks = is_array(events) ? events.slice() : events == null ? [] : [events]; - for (var fn of callbacks) { - // Preserve "this" context - fn.call(this, event); - } -} - -/** - * Used to simulate `$on` on a component instance when `legacy.componentApi` is `true` - * @param {Record} $$props - * @param {string} event_name - * @param {Function} event_callback - */ -export function add_legacy_event_listener($$props, event_name, event_callback) { - $$props.$$events ||= {}; - $$props.$$events[event_name] ||= []; - $$props.$$events[event_name].push(event_callback); -} - -/** - * Used to simulate `$set` on a component instance when `legacy.componentApi` is `true`. - * Needs component accessors so that it can call the setter of the prop. Therefore doesn't - * work for updating props in `$$props` or `$$restProps`. - * @this {Record} - * @param {Record} $$new_props - */ -export function update_legacy_props($$new_props) { - for (const key in $$new_props) { - if (key in this) { - this[key] = $$new_props[key]; - } - } -} diff --git a/packages/svelte/src/internal/index.js b/packages/svelte/src/internal/index.js index b3b4c27db2..2872a23f1e 100644 --- a/packages/svelte/src/internal/index.js +++ b/packages/svelte/src/internal/index.js @@ -40,6 +40,9 @@ export * from './client/dom/blocks/snippet.js'; export * from './client/dom/blocks/svelte-component.js'; export * from './client/dom/blocks/svelte-element.js'; export * from './client/dom/blocks/svelte-head.js'; +export * from './client/dom/legacy/event-modifiers.js'; +export * from './client/dom/legacy/lifecycle.js'; +export * from './client/dom/legacy/misc.js'; export * from './client/dom/template.js'; export * from './client/reactivity/deriveds.js'; export * from './client/reactivity/effects.js';