diff --git a/.changeset/olive-forks-grin.md b/.changeset/olive-forks-grin.md new file mode 100644 index 0000000000..6b66827c86 --- /dev/null +++ b/.changeset/olive-forks-grin.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure unowned deriveds correctly update diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 779548a65c..d04d66ba8a 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -162,9 +162,9 @@ export function check_dirtiness(reaction) { if ((flags & MAYBE_DIRTY) !== 0) { var dependencies = reaction.deps; + var is_unowned = (flags & UNOWNED) !== 0; if (dependencies !== null) { - var is_unowned = (flags & UNOWNED) !== 0; var i; if ((flags & DISCONNECTED) !== 0) { @@ -198,7 +198,10 @@ export function check_dirtiness(reaction) { } } - set_signal_status(reaction, CLEAN); + // Unowned signals should never be marked as clean. + if (!is_unowned) { + set_signal_status(reaction, CLEAN); + } } return false; diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts index 9e537b7659..d14d5fe964 100644 --- a/packages/svelte/tests/signals/test.ts +++ b/packages/svelte/tests/signals/test.ts @@ -676,4 +676,21 @@ describe('signals', () => { assert.equal(d.deps?.length, 1); }; }); + + test('unowned deriveds correctly update', () => { + return () => { + const arr1 = proxy<{ a: number }[]>([]); + const arr2 = proxy([]); + const combined = derived(() => [...arr1, ...arr2]); + const derived_length = derived(() => $.get(combined).length); + + assert.deepEqual($.get(combined), []); + assert.equal($.get(derived_length), 0); + + arr1.push({ a: 1 }); + + assert.deepEqual($.get(combined), [{ a: 1 }]); + assert.equal($.get(derived_length), 1); + }; + }); });