From 15883654f38bec87b2db3c7a7fe56ed73c48682b Mon Sep 17 00:00:00 2001 From: Matei Trandafir Date: Thu, 12 Jun 2025 14:48:30 +0000 Subject: [PATCH 01/12] thing --- .../src/internal/client/reactivity/props.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index f3111361c051..e102441055f8 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -17,6 +17,8 @@ import { LEGACY_DERIVED_PROP, LEGACY_PROPS, STATE_SYMBOL } from '#client/constan import { proxy } from '../proxy.js'; import { capture_store_binding } from './store.js'; import { legacy_mode_flag } from '../../flags/index.js'; +import { component_context } from '../context.js'; +import { teardown } from './effects.js'; /** * @param {((value?: number) => number)} fn @@ -159,16 +161,17 @@ export function legacy_rest_props(props, exclude) { * The proxy handler for spread props. Handles the incoming array of props * that looks like `() => { dynamic: props }, { static: prop }, ..` and wraps * them so that the whole thing is passed to the component as the `$$props` argument. - * @template {Record} T - * @type {ProxyHandler<{ props: Array T)> }>}} + * @typedef {Record} T + * @type {ProxyHandler<{ props: Array T)>, oldProps: T, destroyed: boolean }>}} */ const spread_props_handler = { get(target, key) { + if (target.destroyed && key in target.oldProps) return target.oldProps[key] let i = target.props.length; while (i--) { let p = target.props[i]; if (is_function(p)) p = p(); - if (typeof p === 'object' && p !== null && key in p) return p[key]; + if (typeof p === 'object' && p !== null && key in p) return (target.oldProps[key] = p[key]); } }, set(target, key, value) { @@ -178,7 +181,7 @@ const spread_props_handler = { if (is_function(p)) p = p(); const desc = get_descriptor(p, key); if (desc && desc.set) { - desc.set(value); + desc.set(target.oldProps[key] = value); return true; } } @@ -238,7 +241,9 @@ const spread_props_handler = { * @returns {any} */ export function spread_props(...props) { - return new Proxy({ props }, spread_props_handler); + let destroyed = false + teardown(() => { destroyed = true }) + return new Proxy({ props, oldProps: {}, get destroyed() { return destroyed } }, spread_props_handler); } /** From 144d3ccf63fe4dbe9efb84754acb4198e8f09e7f Mon Sep 17 00:00:00 2001 From: Matei Trandafir Date: Thu, 12 Jun 2025 15:00:01 +0000 Subject: [PATCH 02/12] format --- .../src/internal/client/reactivity/props.js | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index e102441055f8..dd9a17c0e36a 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -166,7 +166,7 @@ export function legacy_rest_props(props, exclude) { */ const spread_props_handler = { get(target, key) { - if (target.destroyed && key in target.oldProps) return target.oldProps[key] + if (target.destroyed && key in target.oldProps) return target.oldProps[key]; let i = target.props.length; while (i--) { let p = target.props[i]; @@ -181,7 +181,7 @@ const spread_props_handler = { if (is_function(p)) p = p(); const desc = get_descriptor(p, key); if (desc && desc.set) { - desc.set(target.oldProps[key] = value); + desc.set((target.oldProps[key] = value)); return true; } } @@ -241,9 +241,20 @@ const spread_props_handler = { * @returns {any} */ export function spread_props(...props) { - let destroyed = false - teardown(() => { destroyed = true }) - return new Proxy({ props, oldProps: {}, get destroyed() { return destroyed } }, spread_props_handler); + let destroyed = false; + teardown(() => { + destroyed = true; + }); + return new Proxy( + { + props, + oldProps: {}, + get destroyed() { + return destroyed; + } + }, + spread_props_handler + ); } /** From 3b9fdf982ec95c1a121ef6dd453020c5f1d3d34d Mon Sep 17 00:00:00 2001 From: Matei-Paul Trandafir Date: Thu, 12 Jun 2025 20:50:26 +0300 Subject: [PATCH 03/12] Correctly initialize oldProps so it's not null even if it's never read --- .../src/internal/client/reactivity/props.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index dd9a17c0e36a..525fb955d0bf 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -17,7 +17,6 @@ import { LEGACY_DERIVED_PROP, LEGACY_PROPS, STATE_SYMBOL } from '#client/constan import { proxy } from '../proxy.js'; import { capture_store_binding } from './store.js'; import { legacy_mode_flag } from '../../flags/index.js'; -import { component_context } from '../context.js'; import { teardown } from './effects.js'; /** @@ -161,8 +160,8 @@ export function legacy_rest_props(props, exclude) { * The proxy handler for spread props. Handles the incoming array of props * that looks like `() => { dynamic: props }, { static: prop }, ..` and wraps * them so that the whole thing is passed to the component as the `$$props` argument. - * @typedef {Record} T - * @type {ProxyHandler<{ props: Array T)>, oldProps: T, destroyed: boolean }>}} + * @typedef {Record} AnyProps + * @type {ProxyHandler<{ props: Array AnyProps)>, oldProps: AnyProps, destroyed: boolean }>}} */ const spread_props_handler = { get(target, key) { @@ -242,13 +241,18 @@ const spread_props_handler = { */ export function spread_props(...props) { let destroyed = false; - teardown(() => { - destroyed = true; - }); + teardown(() => (destroyed = true)); return new Proxy( { props, - oldProps: {}, + oldProps: untrack(() => { + const oldProps = {}; + for (let p of props) { + if (typeof p === 'function') p = p(); + Object.assign(oldProps, p); + } + return oldProps; + }), get destroyed() { return destroyed; } From d546f1967d3c78dd9164ba0ec9a02494ec6875bd Mon Sep 17 00:00:00 2001 From: Matei-Paul Trandafir Date: Thu, 12 Jun 2025 21:08:09 +0300 Subject: [PATCH 04/12] Make it work even if no spread props are used --- .../3-transform/client/visitors/SlotElement.js | 3 +-- .../client/visitors/shared/component.js | 16 ++++++---------- packages/svelte/src/internal/client/index.js | 2 +- .../src/internal/client/reactivity/props.js | 2 +- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SlotElement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SlotElement.js index 401cfde42832..43393e5bdc5a 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/SlotElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/SlotElement.js @@ -54,8 +54,7 @@ export function SlotElement(node, context) { // Let bindings first, they can be used on attributes context.state.init.push(...lets); - const props_expression = - spreads.length === 0 ? b.object(props) : b.call('$.spread_props', b.object(props), ...spreads); + const props_expression = b.call('$.props', b.object(props), ...spreads); const fallback = node.fragment.nodes.length === 0 diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js index a1c4025d6023..1d52e4ac7c82 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/component.js @@ -4,8 +4,8 @@ import { dev, is_ignored } from '../../../../../state.js'; import { get_attribute_chunks, object } from '../../../../../utils/ast.js'; import * as b from '#compiler/builders'; -import { build_bind_this, memoize_expression, validate_binding } from '../shared/utils.js'; -import { build_attribute_value } from '../shared/element.js'; +import { build_bind_this, memoize_expression, validate_binding } from './utils.js'; +import { build_attribute_value } from './element.js'; import { build_event_handler } from './events.js'; import { determine_slot } from '../../../../../utils/slot.js'; @@ -399,14 +399,10 @@ export function build_component(node, component_name, context) { push_prop(b.init('$$legacy', b.true)); } - const props_expression = - props_and_spreads.length === 0 || - (props_and_spreads.length === 1 && Array.isArray(props_and_spreads[0])) - ? b.object(/** @type {Property[]} */ (props_and_spreads[0]) || []) - : b.call( - '$.spread_props', - ...props_and_spreads.map((p) => (Array.isArray(p) ? b.object(p) : p)) - ); + const props_expression = b.call( + '$.props', + ...props_and_spreads.map((p) => (Array.isArray(p) ? b.object(p) : p)) + ); /** @param {Expression} node_id */ let fn = (node_id) => { diff --git a/packages/svelte/src/internal/client/index.js b/packages/svelte/src/internal/client/index.js index 60f9af912060..7a4b045f52d6 100644 --- a/packages/svelte/src/internal/client/index.js +++ b/packages/svelte/src/internal/client/index.js @@ -114,7 +114,7 @@ export { prop, rest_props, legacy_rest_props, - spread_props, + props, update_pre_prop, update_prop } from './reactivity/props.js'; diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index 525fb955d0bf..b61a9bf4300e 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -239,7 +239,7 @@ const spread_props_handler = { * @param {Array | (() => Record)>} props * @returns {any} */ -export function spread_props(...props) { +export function props(...props) { let destroyed = false; teardown(() => (destroyed = true)); return new Proxy( From 642105f6efd2df45c1b470113e7d9d1181c6daed Mon Sep 17 00:00:00 2001 From: Matei-Paul Trandafir Date: Thu, 12 Jun 2025 21:30:03 +0300 Subject: [PATCH 05/12] Make it work with out transitions --- .../src/internal/client/reactivity/props.js | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index b61a9bf4300e..14c91017c15f 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -10,14 +10,14 @@ import { import { get_descriptor, is_function } from '../../shared/utils.js'; import { mutable_source, set, source, update } from './sources.js'; import { derived, derived_safe_equal } from './deriveds.js'; -import { get, captured_signals, untrack } from '../runtime.js'; +import { get, captured_signals, untrack, active_effect } from '../runtime.js'; import { safe_equals } from './equality.js'; import * as e from '../errors.js'; import { LEGACY_DERIVED_PROP, LEGACY_PROPS, STATE_SYMBOL } from '#client/constants'; import { proxy } from '../proxy.js'; import { capture_store_binding } from './store.js'; import { legacy_mode_flag } from '../../flags/index.js'; -import { teardown } from './effects.js'; +import { component_context } from '../context.js'; /** * @param {((value?: number) => number)} fn @@ -240,8 +240,23 @@ const spread_props_handler = { * @returns {any} */ export function props(...props) { - let destroyed = false; - teardown(() => (destroyed = true)); + let paused = false; + const context = component_context; + if (active_effect) { + (active_effect.transitions ??= []).push({ + is_global: true, + in() { + paused = false; + }, + out(callback) { + paused = true; + callback?.(); + }, + stop() { + paused = true; + } + }); + } return new Proxy( { props, @@ -254,7 +269,7 @@ export function props(...props) { return oldProps; }), get destroyed() { - return destroyed; + return (context?.d ?? false) || paused; } }, spread_props_handler From bb239fb965e6f6ce45f8a25db105a6a3f2a5dbcd Mon Sep 17 00:00:00 2001 From: Matei-Paul Trandafir Date: Thu, 12 Jun 2025 21:50:08 +0300 Subject: [PATCH 06/12] Revert #15469 --- .../svelte/src/internal/client/context.js | 9 ++---- .../src/internal/client/reactivity/props.js | 32 +++---------------- .../src/internal/client/reactivity/sources.js | 12 ------- .../svelte/src/internal/client/runtime.js | 7 +--- .../svelte/src/internal/client/types.d.ts | 2 -- 5 files changed, 8 insertions(+), 54 deletions(-) diff --git a/packages/svelte/src/internal/client/context.js b/packages/svelte/src/internal/client/context.js index 7c7213b7a2de..f381c62d3a1f 100644 --- a/packages/svelte/src/internal/client/context.js +++ b/packages/svelte/src/internal/client/context.js @@ -101,16 +101,15 @@ export function getAllContexts() { * @returns {void} */ export function push(props, runes = false, fn) { - var ctx = (component_context = { + component_context = { p: component_context, c: null, - d: false, e: null, m: false, s: props, x: null, l: null - }); + }; if (legacy_mode_flag && !runes) { component_context.l = { @@ -121,10 +120,6 @@ export function push(props, runes = false, fn) { }; } - teardown(() => { - /** @type {ComponentContext} */ (ctx).d = true; - }); - if (DEV) { // component function component_context.function = fn; diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index 14c91017c15f..125647c44b24 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -240,20 +240,19 @@ const spread_props_handler = { * @returns {any} */ export function props(...props) { - let paused = false; - const context = component_context; + let destroyed = false; if (active_effect) { (active_effect.transitions ??= []).push({ is_global: true, in() { - paused = false; + destroyed = false; }, out(callback) { - paused = true; + destroyed = true; callback?.(); }, stop() { - paused = true; + destroyed = true; } }); } @@ -269,21 +268,13 @@ export function props(...props) { return oldProps; }), get destroyed() { - return (context?.d ?? false) || paused; + return destroyed; } }, spread_props_handler ); } -/** - * @param {Derived} current_value - * @returns {boolean} - */ -function has_destroyed_component_ctx(current_value) { - return current_value.ctx?.d ?? false; -} - /** * This function is responsible for synchronizing a possibly bound prop with the inner component state. * It is used whenever the compiler sees that the component writes to the prop, or when it has a default prop_value. @@ -417,11 +408,6 @@ export function prop(props, key, flags, fallback) { return (inner_current_value.v = parent_value); }); - // Ensure we eagerly capture the initial value if it's bindable - if (bindable) { - get(current_value); - } - if (!immutable) current_value.equals = safe_equals; return function (/** @type {any} */ value, /** @type {boolean} */ mutation) { @@ -449,20 +435,12 @@ export function prop(props, key, flags, fallback) { fallback_value = new_value; } - if (has_destroyed_component_ctx(current_value)) { - return value; - } - untrack(() => get(current_value)); // force a synchronisation immediately } return value; } - if (has_destroyed_component_ctx(current_value)) { - return current_value.v; - } - return get(current_value); }; } diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js index 40a3e4e77f14..111e8ca7a21d 100644 --- a/packages/svelte/src/internal/client/reactivity/sources.js +++ b/packages/svelte/src/internal/client/reactivity/sources.js @@ -14,7 +14,6 @@ import { reaction_sources, check_dirtiness, untracking, - is_destroying_effect, push_reaction_value } from '../runtime.js'; import { equals, safe_equals } from './equality.js'; @@ -38,9 +37,6 @@ import { execute_derived } from './deriveds.js'; export let inspect_effects = new Set(); -/** @type {Map} */ -export const old_values = new Map(); - /** * @param {Set} v */ @@ -160,14 +156,6 @@ export function set(source, value, should_proxy = false) { */ export function internal_set(source, value) { if (!source.equals(value)) { - var old_value = source.v; - - if (is_destroying_effect) { - old_values.set(source, value); - } else { - old_values.set(source, old_value); - } - source.v = value; if (DEV && tracing_mode_flag) { diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 954406095904..237a7a3c994e 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -25,7 +25,7 @@ import { EFFECT_IS_UPDATING } from './constants.js'; import { flush_tasks } from './dom/task.js'; -import { internal_set, old_values } from './reactivity/sources.js'; +import { internal_set } from './reactivity/sources.js'; import { destroy_derived_effects, update_derived } from './reactivity/deriveds.js'; import * as e from './errors.js'; @@ -535,7 +535,6 @@ function flush_queued_root_effects() { var collected_effects = process_effects(root_effects[i]); flush_queued_effects(collected_effects); } - old_values.clear(); } } finally { is_flushing = false; @@ -800,10 +799,6 @@ export function get(signal) { } } - if (is_destroying_effect && old_values.has(signal)) { - return old_values.get(signal); - } - return signal.v; } diff --git a/packages/svelte/src/internal/client/types.d.ts b/packages/svelte/src/internal/client/types.d.ts index 9703c2aac198..a3156b14dd45 100644 --- a/packages/svelte/src/internal/client/types.d.ts +++ b/packages/svelte/src/internal/client/types.d.ts @@ -14,8 +14,6 @@ export type ComponentContext = { p: null | ComponentContext; /** context */ c: null | Map; - /** destroyed */ - d: boolean; /** deferred effects */ e: null | Array<{ fn: () => void | (() => void); From 8072ab5b44a2f9916ca5b786986ff571a0219bf8 Mon Sep 17 00:00:00 2001 From: Matei-Paul Trandafir Date: Thu, 12 Jun 2025 21:53:19 +0300 Subject: [PATCH 07/12] Lint & format --- .../src/internal/client/reactivity/props.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index 125647c44b24..c3a8b3c2fc04 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -161,16 +161,16 @@ export function legacy_rest_props(props, exclude) { * that looks like `() => { dynamic: props }, { static: prop }, ..` and wraps * them so that the whole thing is passed to the component as the `$$props` argument. * @typedef {Record} AnyProps - * @type {ProxyHandler<{ props: Array AnyProps)>, oldProps: AnyProps, destroyed: boolean }>}} + * @type {ProxyHandler<{ props: Array AnyProps)>, old_props: AnyProps, destroyed: boolean }>}} */ const spread_props_handler = { get(target, key) { - if (target.destroyed && key in target.oldProps) return target.oldProps[key]; + if (target.destroyed && key in target.old_props) return target.old_props[key]; let i = target.props.length; while (i--) { let p = target.props[i]; if (is_function(p)) p = p(); - if (typeof p === 'object' && p !== null && key in p) return (target.oldProps[key] = p[key]); + if (typeof p === 'object' && p !== null && key in p) return (target.old_props[key] = p[key]); } }, set(target, key, value) { @@ -180,7 +180,7 @@ const spread_props_handler = { if (is_function(p)) p = p(); const desc = get_descriptor(p, key); if (desc && desc.set) { - desc.set((target.oldProps[key] = value)); + desc.set((target.old_props[key] = value)); return true; } } @@ -259,13 +259,13 @@ export function props(...props) { return new Proxy( { props, - oldProps: untrack(() => { - const oldProps = {}; + old_props: untrack(() => { + const old_props = {}; for (let p of props) { if (typeof p === 'function') p = p(); - Object.assign(oldProps, p); + Object.assign(old_props, p); } - return oldProps; + return old_props; }), get destroyed() { return destroyed; From 587c385724ffe8163fdc3e6ce4951367d189e252 Mon Sep 17 00:00:00 2001 From: Matei-Paul Trandafir Date: Thu, 12 Jun 2025 23:45:53 +0300 Subject: [PATCH 08/12] Much better implementation --- .../src/internal/client/reactivity/props.js | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index c3a8b3c2fc04..6fa79af20bd0 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -13,7 +13,13 @@ import { derived, derived_safe_equal } from './deriveds.js'; import { get, captured_signals, untrack, active_effect } from '../runtime.js'; import { safe_equals } from './equality.js'; import * as e from '../errors.js'; -import { LEGACY_DERIVED_PROP, LEGACY_PROPS, STATE_SYMBOL } from '#client/constants'; +import { + DESTROYED, + INERT, + LEGACY_DERIVED_PROP, + LEGACY_PROPS, + STATE_SYMBOL +} from '#client/constants'; import { proxy } from '../proxy.js'; import { capture_store_binding } from './store.js'; import { legacy_mode_flag } from '../../flags/index.js'; @@ -240,22 +246,7 @@ const spread_props_handler = { * @returns {any} */ export function props(...props) { - let destroyed = false; - if (active_effect) { - (active_effect.transitions ??= []).push({ - is_global: true, - in() { - destroyed = false; - }, - out(callback) { - destroyed = true; - callback?.(); - }, - stop() { - destroyed = true; - } - }); - } + const effect = active_effect; return new Proxy( { props, @@ -268,7 +259,7 @@ export function props(...props) { return old_props; }), get destroyed() { - return destroyed; + return effect ? (effect.f & (DESTROYED | INERT)) !== 0 : false; } }, spread_props_handler From 3ee6b6204ab7b09e46864fefdd3f39f8ddf29214 Mon Sep 17 00:00:00 2001 From: Matei-Paul Trandafir Date: Fri, 13 Jun 2025 00:12:36 +0300 Subject: [PATCH 09/12] Restore some stuff from #15469, but differently --- .../src/internal/client/reactivity/props.js | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index 6fa79af20bd0..d52772250c57 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -266,6 +266,13 @@ export function props(...props) { ); } +/** + * @param {Derived} derived + */ +function is_paused_or_destroyed(derived) { + return (derived.f & (DESTROYED | INERT)) !== 0; +} + /** * This function is responsible for synchronizing a possibly bound prop with the inner component state. * It is used whenever the compiler sees that the component writes to the prop, or when it has a default prop_value. @@ -399,6 +406,11 @@ export function prop(props, key, flags, fallback) { return (inner_current_value.v = parent_value); }); + // Ensure we eagerly capture the initial value if it's bindable + if (bindable) { + get(current_value); + } + if (!immutable) current_value.equals = safe_equals; return function (/** @type {any} */ value, /** @type {boolean} */ mutation) { @@ -426,12 +438,20 @@ export function prop(props, key, flags, fallback) { fallback_value = new_value; } + if (is_paused_or_destroyed(current_value)) { + return value; + } + untrack(() => get(current_value)); // force a synchronisation immediately } return value; } + if (is_paused_or_destroyed(current_value)) { + return value; + } + return get(current_value); }; } From d04e4bb14a787c7e34aecf2dc8ed781c0ac6449b Mon Sep 17 00:00:00 2001 From: Matei-Paul Trandafir Date: Fri, 13 Jun 2025 01:30:27 +0300 Subject: [PATCH 10/12] Update test snapshots --- .../bind-component-snippet/_expected/client/index.svelte.js | 6 +++--- .../samples/bind-this/_expected/client/index.svelte.js | 4 ++-- .../_expected/client/index.svelte.js | 6 +++--- .../samples/purity/_expected/client/index.svelte.js | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/client/index.svelte.js index ba3f4b155a31..a407c84a8ad2 100644 --- a/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/client/index.svelte.js @@ -18,17 +18,17 @@ export default function Bind_component_snippet($$anchor) { var fragment = root(); var node = $.first_child(fragment); - TextInput(node, { + TextInput(node, $.props({ get value() { return $.get(value); }, set value($$value) { $.set(value, $$value, true); } - }); + })); var text_1 = $.sibling(node); $.template_effect(() => $.set_text(text_1, ` value: ${$.get(value) ?? ''}`)); $.append($$anchor, fragment); -} \ No newline at end of file +} diff --git a/packages/svelte/tests/snapshot/samples/bind-this/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/bind-this/_expected/client/index.svelte.js index dfd32a04e51d..7b9f6d0abfb0 100644 --- a/packages/svelte/tests/snapshot/samples/bind-this/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/bind-this/_expected/client/index.svelte.js @@ -3,5 +3,5 @@ import 'svelte/internal/flags/legacy'; import * as $ from 'svelte/internal/client'; export default function Bind_this($$anchor) { - $.bind_this(Foo($$anchor, { $$legacy: true }), ($$value) => foo = $$value, () => foo); -} \ No newline at end of file + $.bind_this(Foo($$anchor, $.props({ $$legacy: true })), ($$value) => foo = $$value, () => foo); +} diff --git a/packages/svelte/tests/snapshot/samples/function-prop-no-getter/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/function-prop-no-getter/_expected/client/index.svelte.js index 762a23754c9b..4bf75eea50c0 100644 --- a/packages/svelte/tests/snapshot/samples/function-prop-no-getter/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/function-prop-no-getter/_expected/client/index.svelte.js @@ -10,7 +10,7 @@ export default function Function_prop_no_getter($$anchor) { const plusOne = (num) => num + 1; - Button($$anchor, { + Button($$anchor, $.props({ onmousedown: () => $.set(count, $.get(count) + 1), onmouseup, onmouseenter: () => $.set(count, plusOne($.get(count)), true), @@ -23,5 +23,5 @@ export default function Function_prop_no_getter($$anchor) { $.append($$anchor, text); }, $$slots: { default: true } - }); -} \ No newline at end of file + })); +} diff --git a/packages/svelte/tests/snapshot/samples/purity/_expected/client/index.svelte.js b/packages/svelte/tests/snapshot/samples/purity/_expected/client/index.svelte.js index a351851875ed..de315b019662 100644 --- a/packages/svelte/tests/snapshot/samples/purity/_expected/client/index.svelte.js +++ b/packages/svelte/tests/snapshot/samples/purity/_expected/client/index.svelte.js @@ -16,6 +16,6 @@ export default function Purity($$anchor) { var node = $.sibling(p_1, 2); - Child(node, { prop: encodeURIComponent('hello') }); + Child(node, $.props({ prop: encodeURIComponent('hello') })); $.append($$anchor, fragment); -} \ No newline at end of file +} From bd1fb74729f699b2a4585a6cb5e09afe9f752bab Mon Sep 17 00:00:00 2001 From: Matei-Paul Trandafir Date: Fri, 13 Jun 2025 01:30:40 +0300 Subject: [PATCH 11/12] Fix derived pause logic --- .../svelte/src/internal/client/reactivity/deriveds.js | 2 +- .../svelte/src/internal/client/reactivity/props.js | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js index e9cea0df3e64..5fa3ffe1c041 100644 --- a/packages/svelte/src/internal/client/reactivity/deriveds.js +++ b/packages/svelte/src/internal/client/reactivity/deriveds.js @@ -116,7 +116,7 @@ let stack = []; * @param {Derived} derived * @returns {Effect | null} */ -function get_derived_parent_effect(derived) { +export function get_derived_parent_effect(derived) { var parent = derived.parent; while (parent !== null) { if ((parent.f & DERIVED) === 0) { diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index d52772250c57..937f60bf843b 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -9,8 +9,8 @@ import { } from '../../../constants.js'; import { get_descriptor, is_function } from '../../shared/utils.js'; import { mutable_source, set, source, update } from './sources.js'; -import { derived, derived_safe_equal } from './deriveds.js'; -import { get, captured_signals, untrack, active_effect } from '../runtime.js'; +import { derived, derived_safe_equal, get_derived_parent_effect } from './deriveds.js'; +import { active_effect, captured_signals, get, untrack } from '../runtime.js'; import { safe_equals } from './equality.js'; import * as e from '../errors.js'; import { @@ -23,7 +23,6 @@ import { import { proxy } from '../proxy.js'; import { capture_store_binding } from './store.js'; import { legacy_mode_flag } from '../../flags/index.js'; -import { component_context } from '../context.js'; /** * @param {((value?: number) => number)} fn @@ -270,7 +269,9 @@ export function props(...props) { * @param {Derived} derived */ function is_paused_or_destroyed(derived) { - return (derived.f & (DESTROYED | INERT)) !== 0; + const parent = get_derived_parent_effect(derived); + if (!parent) return false; + return (parent.f & (DESTROYED | INERT)) !== 0; } /** @@ -449,7 +450,7 @@ export function prop(props, key, flags, fallback) { } if (is_paused_or_destroyed(current_value)) { - return value; + return current_value.v; } return get(current_value); From e2290b59e997663ac0241c1ebfc6746c23714145 Mon Sep 17 00:00:00 2001 From: Matei-Paul Trandafir Date: Fri, 13 Jun 2025 01:55:05 +0300 Subject: [PATCH 12/12] Fix more tests --- .../samples/effect-teardown-stale-value/_config.js | 3 ++- .../samples/nested-effect-conflict/_config.js | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/svelte/tests/runtime-runes/samples/effect-teardown-stale-value/_config.js b/packages/svelte/tests/runtime-runes/samples/effect-teardown-stale-value/_config.js index 1016ffb43e7e..349487883bf6 100644 --- a/packages/svelte/tests/runtime-runes/samples/effect-teardown-stale-value/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/effect-teardown-stale-value/_config.js @@ -14,7 +14,8 @@ export default test({ 'up', { foo: false, bar: false }, 'down', - { foo: false, bar: false }, + // TODO the test should be deleted as there's no more concept of "teardown stale value" + { foo: true, bar: true }, 'up', { foo: true, bar: true } ]); diff --git a/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/_config.js b/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/_config.js index eb631bc9f4bc..a8c16b7008c9 100644 --- a/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/nested-effect-conflict/_config.js @@ -10,6 +10,14 @@ export default test({ }); await Promise.resolve(); - assert.deepEqual(logs, ['top level', 'inner', 0, 'destroy inner', 0, 'destroy outer', 0]); + assert.deepEqual(logs, [ + 'top level', + 'inner', + 0, + 'destroy inner', + undefined, + 'destroy outer', + undefined + ]); } });