From bbe1d73c29d3377fa5fb88624b91fb014b1a84d5 Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Tue, 4 Mar 2025 22:48:41 +0100 Subject: [PATCH 1/3] fix: correctly set `is_updating` before flushing root effects --- .changeset/proud-poems-brake.md | 5 +++ .../svelte/src/internal/client/runtime.js | 3 ++ packages/svelte/tests/signals/test.ts | 41 +++++++++++++++++++ 3 files changed, 49 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 000000000000..3f4e076e2269 --- /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 486c819f3671..8f4be922b045 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -644,8 +644,10 @@ function infinite_loop_guard() { } function flush_queued_root_effects() { + let prev_updating = is_updating_effect; try { var flush_count = 0; + is_updating_effect = true; while (queued_root_effects.length > 0) { if (flush_count++ > 1000) { @@ -670,6 +672,7 @@ function flush_queued_root_effects() { } } finally { is_flushing = false; + is_updating_effect = prev_updating; last_scheduled_effect = null; if (DEV) { diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts index 046f833e0ed7..ef4cf16d3b6c 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(); + }; + }); }); From 37ab5f9f57c5e23f5bf5ee74c40dadd489b6f97d Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 4 Mar 2025 18:19:41 -0500 Subject: [PATCH 2/3] rename for consistency with update_effect --- packages/svelte/src/internal/client/runtime.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 8f4be922b045..9be7f0163370 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -644,7 +644,8 @@ function infinite_loop_guard() { } function flush_queued_root_effects() { - let prev_updating = is_updating_effect; + let was_updating_effect = is_updating_effect; + try { var flush_count = 0; is_updating_effect = true; @@ -672,7 +673,7 @@ function flush_queued_root_effects() { } } finally { is_flushing = false; - is_updating_effect = prev_updating; + is_updating_effect = was_updating_effect; last_scheduled_effect = null; if (DEV) { From a4d5f2592eaeb86ffb9faafb6d4f4ca1643e5407 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 4 Mar 2025 18:19:53 -0500 Subject: [PATCH 3/3] use var --- packages/svelte/src/internal/client/runtime.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 9be7f0163370..9f721f9ec4d6 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -644,7 +644,7 @@ function infinite_loop_guard() { } function flush_queued_root_effects() { - let was_updating_effect = is_updating_effect; + var was_updating_effect = is_updating_effect; try { var flush_count = 0;