From 35783c3767d8aa4d2719f686a098bf7782c8f710 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 11 Jun 2025 15:25:40 -0400 Subject: [PATCH] complete revert --- .../svelte/src/internal/client/dev/tracing.js | 17 +++++++++++ .../src/internal/client/dom/blocks/each.js | 10 +++++++ .../src/internal/client/reactivity/sources.js | 1 + .../src/internal/client/reactivity/types.d.ts | 2 ++ .../svelte/src/internal/client/runtime.js | 29 +++++++++++-------- 5 files changed, 47 insertions(+), 12 deletions(-) diff --git a/packages/svelte/src/internal/client/dev/tracing.js b/packages/svelte/src/internal/client/dev/tracing.js index 05a4ac3806..65c6379625 100644 --- a/packages/svelte/src/internal/client/dev/tracing.js +++ b/packages/svelte/src/internal/client/dev/tracing.js @@ -26,6 +26,23 @@ function log_entry(signal, entry) { return; } + if (signal.trace) { + var previous_captured_signals = captured_signals; + var captured = new Set(); + set_captured_signals(captured); + + try { + untrack(signal.trace); + } finally { + set_captured_signals(previous_captured_signals); + } + + if (captured.size > 0) { + for (const dep of captured) log_entry(dep); + return; + } + } + const type = (signal.f & DERIVED) !== 0 ? '$derived' : '$state'; const current_reaction = /** @type {Reaction} */ (active_reaction); const dirty = signal.wv > current_reaction.wv || current_reaction.wv === 0; diff --git a/packages/svelte/src/internal/client/dom/blocks/each.js b/packages/svelte/src/internal/client/dom/blocks/each.js index e8f00546d0..954dcb2214 100644 --- a/packages/svelte/src/internal/client/dom/blocks/each.js +++ b/packages/svelte/src/internal/client/dom/blocks/each.js @@ -524,6 +524,16 @@ function create_item( var v = reactive ? (mutable ? mutable_source(value) : source(value)) : value; var i = (flags & EACH_INDEX_REACTIVE) === 0 ? index : source(index); + if (DEV && reactive) { + // For tracing purposes, we need to link the source signal we create with the + // collection + index so that tracing works as intended + /** @type {Value} */ (v).trace = () => { + var collection_index = typeof i === 'number' ? index : i.v; + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + get_collection()[collection_index]; + }; + } + /** @type {EachItem} */ var item = { i, diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js index 4c04c37a67..40a3e4e77f 100644 --- a/packages/svelte/src/internal/client/reactivity/sources.js +++ b/packages/svelte/src/internal/client/reactivity/sources.js @@ -70,6 +70,7 @@ export function source(v, stack) { signal.created = stack ?? get_stack('CreatedAt'); signal.updated = null; signal.set_during_effect = false; + signal.trace = null; } return signal; diff --git a/packages/svelte/src/internal/client/reactivity/types.d.ts b/packages/svelte/src/internal/client/reactivity/types.d.ts index f2e7576720..756bb98f09 100644 --- a/packages/svelte/src/internal/client/reactivity/types.d.ts +++ b/packages/svelte/src/internal/client/reactivity/types.d.ts @@ -29,6 +29,8 @@ export interface Value extends Signal { * increment the write version so that it shows up as dirty when the effect re-runs */ set_during_effect?: boolean; + /** A function that retrieves the underlying source, used for each block item signals */ + trace?: null | (() => void); } export interface Reaction extends Signal { diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index b7a2fc09a5..c06705ce24 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -773,22 +773,27 @@ export function get(signal) { active_reaction !== null && tracing_expressions.reaction === active_reaction ) { - var trace = get_stack('TracedAt'); + // Used when mapping state between special blocks like `each` + if (signal.trace) { + signal.trace(); + } else { + var trace = get_stack('TracedAt'); - if (trace) { - var entry = tracing_expressions.entries.get(signal); + if (trace) { + var entry = tracing_expressions.entries.get(signal); - if (entry === undefined) { - entry = { traces: [] }; - tracing_expressions.entries.set(signal, entry); - } + if (entry === undefined) { + entry = { traces: [] }; + tracing_expressions.entries.set(signal, entry); + } - var last = entry.traces[entry.traces.length - 1]; + var last = entry.traces[entry.traces.length - 1]; - // traces can be duplicated, e.g. by `snapshot` invoking both - // both `getOwnPropertyDescriptor` and `get` traps at once - if (trace.stack !== last?.stack) { - entry.traces.push(trace); + // traces can be duplicated, e.g. by `snapshot` invoking both + // both `getOwnPropertyDescriptor` and `get` traps at once + if (trace.stack !== last?.stack) { + entry.traces.push(trace); + } } } }