diff --git a/.changeset/witty-tomatoes-care.md b/.changeset/witty-tomatoes-care.md new file mode 100644 index 0000000000..c544ad6315 --- /dev/null +++ b/.changeset/witty-tomatoes-care.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: better handling of derived signals that have no dependencies diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 429fd95d34..67891e84ce 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -824,7 +824,8 @@ function update_derived(signal, force_schedule) { destroy_references(signal); const value = execute_signal_fn(signal); updating_derived = previous_updating_derived; - const status = current_skip_consumer || (signal.f & UNOWNED) !== 0 ? DIRTY : CLEAN; + const status = + (current_skip_consumer || (signal.f & UNOWNED) !== 0) && signal.d !== null ? DIRTY : CLEAN; set_signal_status(signal, status); const equals = /** @type {import('./types.js').EqualsFunctions} */ (signal.e); if (!equals(value, signal.v)) { diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts index d34cd7f06c..0f8864ad6d 100644 --- a/packages/svelte/tests/signals/test.ts +++ b/packages/svelte/tests/signals/test.ts @@ -263,6 +263,27 @@ describe('signals', () => { }; }); + let no_deps = $.derived(() => { + return []; + }); + + test('two effects with an unowned derived that has no depedencies', () => { + const log: Array> = []; + + $.render_effect(() => { + log.push($.get(no_deps)); + }); + + $.render_effect(() => { + log.push($.get(no_deps)); + }); + + return () => { + $.flushSync(); + assert.deepEqual(log, [[], []]); + }; + }); + test('schedules rerun when writing to signal before reading it', (runes) => { if (!runes) return () => {};