From 4f41e816baa007fb6a4e31164da49576e87e342e Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 4 Feb 2026 13:07:46 -0500 Subject: [PATCH] fix: ensure infinite effect loops are cleared after flushing (#17601) * failing effect-loop-infinite test * fix --- .changeset/chatty-mammals-find.md | 5 +++++ .../svelte/src/internal/client/reactivity/batch.js | 3 ++- packages/svelte/tests/runtime-legacy/shared.ts | 2 ++ .../samples/effect-loop-infinite/_config.js | 11 ++++++----- 4 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 .changeset/chatty-mammals-find.md diff --git a/.changeset/chatty-mammals-find.md b/.changeset/chatty-mammals-find.md new file mode 100644 index 0000000000..373dc0059a --- /dev/null +++ b/.changeset/chatty-mammals-find.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure infinite effect loops are cleared after flushing diff --git a/packages/svelte/src/internal/client/reactivity/batch.js b/packages/svelte/src/internal/client/reactivity/batch.js index cef2df4716..9bf93c873f 100644 --- a/packages/svelte/src/internal/client/reactivity/batch.js +++ b/packages/svelte/src/internal/client/reactivity/batch.js @@ -647,8 +647,9 @@ function flush_effects() { } } } finally { - is_flushing = false; + queued_root_effects = []; + is_flushing = false; last_scheduled_effect = null; if (DEV) { diff --git a/packages/svelte/tests/runtime-legacy/shared.ts b/packages/svelte/tests/runtime-legacy/shared.ts index 8c29a6ada2..c5317f822e 100644 --- a/packages/svelte/tests/runtime-legacy/shared.ts +++ b/packages/svelte/tests/runtime-legacy/shared.ts @@ -521,6 +521,8 @@ async function run_test_variant( errors, hydrate: hydrate_fn }); + + flushSync(); } if (config.runtime_error && !unhandled_rejection) { diff --git a/packages/svelte/tests/runtime-runes/samples/effect-loop-infinite/_config.js b/packages/svelte/tests/runtime-runes/samples/effect-loop-infinite/_config.js index 57f60c2b44..44cf5b09e2 100644 --- a/packages/svelte/tests/runtime-runes/samples/effect-loop-infinite/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/effect-loop-infinite/_config.js @@ -11,11 +11,12 @@ export default test({ test({ assert, errors }) { const [button] = document.querySelectorAll('button'); - try { + assert.throws(() => { flushSync(() => button.click()); - } catch (e) { - assert.equal(errors.length, 1); // for whatever reason we can't get the name which should be 'updated at' - assert.ok(/** @type {Error} */ (e).message.startsWith('effect_update_depth_exceeded')); - } + }, /effect_update_depth_exceeded/); + + assert.equal(errors.length, 1); + + assert.doesNotThrow(flushSync); } });