diff --git a/.changeset/smart-zoos-vanish.md b/.changeset/smart-zoos-vanish.md new file mode 100644 index 0000000000..b06583fd41 --- /dev/null +++ b/.changeset/smart-zoos-vanish.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: reconnected deep derived signals to graph diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index e699183d02..370e5e3d6d 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -171,8 +171,17 @@ export function check_dirtiness(reaction) { if (dependencies !== null) { var is_unowned = (flags & UNOWNED) !== 0; + var i; + + if ((flags & DISCONNECTED) !== 0) { + for (i = 0; i < dependencies.length; i++) { + (dependencies[i].reactions ??= []).push(reaction); + } - for (var i = 0; i < dependencies.length; i++) { + reaction.f ^= DISCONNECTED; + } + + for (i = 0; i < dependencies.length; i++) { var dependency = dependencies[i]; if (check_dirtiness(/** @type {import('#client').Derived} */ (dependency))) { @@ -771,25 +780,6 @@ export function get(signal) { if (check_dirtiness(derived)) { update_derived(derived); } - - if ((flags & DISCONNECTED) !== 0) { - // reconnect to the graph - deps = derived.deps; - - if (deps !== null) { - for (var i = 0; i < deps.length; i++) { - var dep = deps[i]; - var reactions = dep.reactions; - if (reactions === null) { - dep.reactions = [derived]; - } else if (!reactions.includes(derived)) { - reactions.push(derived); - } - } - } - - derived.f ^= DISCONNECTED; - } } return signal.v; diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts index 555beb0526..b66d25793f 100644 --- a/packages/svelte/tests/signals/test.ts +++ b/packages/svelte/tests/signals/test.ts @@ -550,6 +550,40 @@ describe('signals', () => { }; }); + test('deriveds update upon reconnection #3', () => { + let a = source(false); + let b = source(false); + + let c = derived(() => $.get(a) || $.get(b)); + let d = derived(() => $.get(c)); + let e = derived(() => $.get(d)); + + return () => { + const log: string[] = []; + let destroy = effect_root(() => { + render_effect(() => { + $.get(e); + log.push('init'); + }); + }); + destroy(); + + destroy = effect_root(() => { + render_effect(() => { + $.get(e); + log.push('update'); + }); + }); + + assert.deepEqual(log, ['init', 'update']); + + set(a, true); + flushSync(); + + assert.deepEqual(log, ['init', 'update', 'update']); + }; + }); + test('unowned deriveds are not added as reactions', () => { var count = source(0);