From 181fb2ad496dcd7e1915032b553115c805034bbf Mon Sep 17 00:00:00 2001 From: Paolo Ricciuti Date: Wed, 5 Mar 2025 00:36:26 +0100 Subject: [PATCH] fix: correctly set `is_updating` before flushing root effects (#15442) * fix: correctly set `is_updating` before flushing root effects * rename for consistency with update_effect * use var --------- Co-authored-by: Rich Harris --- .changeset/proud-poems-brake.md | 5 +++ .../svelte/src/internal/client/runtime.js | 4 ++ packages/svelte/tests/signals/test.ts | 41 +++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 .changeset/proud-poems-brake.md diff --git a/.changeset/proud-poems-brake.md b/.changeset/proud-poems-brake.md new file mode 100644 index 0000000000..3f4e076e22 --- /dev/null +++ b/.changeset/proud-poems-brake.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: correctly set `is_updating` before flushing root effects diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 486c819f36..9f721f9ec4 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -644,8 +644,11 @@ function infinite_loop_guard() { } function flush_queued_root_effects() { + var was_updating_effect = is_updating_effect; + try { var flush_count = 0; + is_updating_effect = true; while (queued_root_effects.length > 0) { if (flush_count++ > 1000) { @@ -670,6 +673,7 @@ function flush_queued_root_effects() { } } finally { is_flushing = false; + is_updating_effect = was_updating_effect; last_scheduled_effect = null; if (DEV) { diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts index 046f833e0e..ef4cf16d3b 100644 --- a/packages/svelte/tests/signals/test.ts +++ b/packages/svelte/tests/signals/test.ts @@ -1135,4 +1135,45 @@ describe('signals', () => { destroy(); }; }); + + test('unowned deriveds correctly update', () => { + const log: any[] = []; + + return () => { + const a = state(0); + const b = state(0); + const c = derived(() => { + return $.get(a); + }); + const d = derived(() => { + return $.get(b); + }); + + const destroy = effect_root(() => { + const e = derived(() => { + return $.get(c) === 1 && $.get(d) === 1; + }); + render_effect(() => { + log.push($.get(e)); + }); + }); + + assert.deepEqual(log, [false]); + + set(a, 1); + set(b, 1); + + flushSync(); + + assert.deepEqual(log, [false, true]); + + set(b, 9); + + flushSync(); + + assert.deepEqual(log, [false, true, false]); + + destroy(); + }; + }); });