From 33450bc075df690c44ca5da4bcda7b9f01416670 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 25 Oct 2025 12:37:31 -0400 Subject: [PATCH] fix: ignore fork `discard()` after `commit()` --- .changeset/twenty-onions-attack.md | 5 +++++ .../src/internal/client/reactivity/batch.js | 22 +++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 .changeset/twenty-onions-attack.md diff --git a/.changeset/twenty-onions-attack.md b/.changeset/twenty-onions-attack.md new file mode 100644 index 0000000000..c23c8b590b --- /dev/null +++ b/.changeset/twenty-onions-attack.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ignore fork `discard()` after `commit()` diff --git a/packages/svelte/src/internal/client/reactivity/batch.js b/packages/svelte/src/internal/client/reactivity/batch.js index fdeb111a4d..ab83050cd0 100644 --- a/packages/svelte/src/internal/client/reactivity/batch.js +++ b/packages/svelte/src/internal/client/reactivity/batch.js @@ -913,28 +913,36 @@ export function fork(fn) { e.fork_timing(); } - const batch = Batch.ensure(); + var batch = Batch.ensure(); batch.is_fork = true; - const settled = batch.settled(); + var committed = false; + var settled = batch.settled(); flushSync(fn); // revert state changes - for (const [source, value] of batch.previous) { + for (var [source, value] of batch.previous) { source.v = value; } return { commit: async () => { + if (committed) { + await settled; + return; + } + if (!batches.has(batch)) { e.fork_discarded(); } + committed = true; + batch.is_fork = false; // apply changes - for (const [source, value] of batch.current) { + for (var [source, value] of batch.current) { source.v = value; } @@ -945,9 +953,9 @@ export function fork(fn) { // TODO maybe there's a better implementation? flushSync(() => { /** @type {Set} */ - const eager_effects = new Set(); + var eager_effects = new Set(); - for (const source of batch.current.keys()) { + for (var source of batch.current.keys()) { mark_eager_effects(source, eager_effects); } @@ -959,7 +967,7 @@ export function fork(fn) { await settled; }, discard: () => { - if (batches.has(batch)) { + if (!committed && batches.has(batch)) { batches.delete(batch); batch.discard(); }