diff --git a/.changeset/sad-forks-go.md b/.changeset/sad-forks-go.md new file mode 100644 index 0000000000..da27e11642 --- /dev/null +++ b/.changeset/sad-forks-go.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: keep deriveds reactive after their original parent effect was destroyed diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js index 7e6f3c6f60..070230a461 100644 --- a/packages/svelte/src/internal/client/reactivity/deriveds.js +++ b/packages/svelte/src/internal/client/reactivity/deriveds.js @@ -11,7 +11,8 @@ import { STALE_REACTION, ASYNC, WAS_MARKED, - CONNECTED + CONNECTED, + DESTROYED } from '#client/constants'; import { active_reaction, @@ -296,7 +297,9 @@ function get_derived_parent_effect(derived) { var parent = derived.parent; while (parent !== null) { if ((parent.f & DERIVED) === 0) { - return /** @type {Effect} */ (parent); + // The original parent effect might've been destroyed but the derived + // is used elsewhere now - do not return the destroyed effect in that case + return (parent.f & DESTROYED) === 0 ? /** @type {Effect} */ (parent) : null; } parent = parent.parent; } diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts index eff6d6166a..13430609a8 100644 --- a/packages/svelte/tests/signals/test.ts +++ b/packages/svelte/tests/signals/test.ts @@ -1391,6 +1391,33 @@ describe('signals', () => { }; }); + test('derived whose original parent effect has been destroyed keeps updating', () => { + return () => { + let count: Source; + let double: Derived; + const destroy = effect_root(() => { + render_effect(() => { + count = state(0); + double = derived(() => $.get(count) * 2); + }); + }); + + flushSync(); + assert.equal($.get(double!), 0); + + destroy(); + flushSync(); + + set(count!, 1); + flushSync(); + assert.equal($.get(double!), 2); + + set(count!, 2); + flushSync(); + assert.equal($.get(double!), 4); + }; + }); + test('$effect.root inside deriveds stay alive independently', () => { const log: any[] = []; const c = state(0);