From d2f453f8b099ee46eb5835fc2af2952bda0e2fe6 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Tue, 28 Oct 2025 02:40:13 +0100 Subject: [PATCH] fix: don't restore batch in `#await` (#17051) #16977 had one slight regression which might contribute to #16990: The batch from earlier was restored, but that doesn't make sense in this situations since this has nothing to do with our new async logic of batches suspending until pending work is done. As a result you could end up with a batch being created, and then the restore then instead reverting to an earlier batch that was already done, which means a ghost-batch ends up in the set of batches, subsequently triggering time traveling when it shouldn't. This may help with #16990 No test because basically impossible to do so --- .changeset/shaky-jars-cut.md | 5 +++++ packages/svelte/src/internal/client/dom/blocks/await.js | 8 ++++++-- packages/svelte/src/internal/client/reactivity/async.js | 5 ++--- 3 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 .changeset/shaky-jars-cut.md diff --git a/.changeset/shaky-jars-cut.md b/.changeset/shaky-jars-cut.md new file mode 100644 index 0000000000..b74b00fa1c --- /dev/null +++ b/.changeset/shaky-jars-cut.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: don't restore batch in `#await` diff --git a/packages/svelte/src/internal/client/dom/blocks/await.js b/packages/svelte/src/internal/client/dom/blocks/await.js index bac01e4c33..87d64df23e 100644 --- a/packages/svelte/src/internal/client/dom/blocks/await.js +++ b/packages/svelte/src/internal/client/dom/blocks/await.js @@ -12,7 +12,7 @@ import { import { queue_micro_task } from '../task.js'; import { HYDRATION_START_ELSE, UNINITIALIZED } from '../../../../constants.js'; import { is_runes } from '../../context.js'; -import { flushSync, is_flushing_sync } from '../../reactivity/batch.js'; +import { Batch, flushSync, is_flushing_sync } from '../../reactivity/batch.js'; import { BranchManager } from './branches.js'; import { capture, unset_context } from '../../reactivity/async.js'; @@ -69,7 +69,11 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) { if (destroyed) return; resolved = true; - restore(); + // We don't want to restore the previous batch here; {#await} blocks don't follow the async logic + // we have elsewhere, instead pending/resolve/fail states are each their own batch so to speak. + restore(false); + // Make sure we have a batch, since the branch manager expects one to exist + Batch.ensure(); if (hydrating) { // `restore()` could set `hydrating` to `true`, which we very much diff --git a/packages/svelte/src/internal/client/reactivity/async.js b/packages/svelte/src/internal/client/reactivity/async.js index fb836df989..bdd7eed940 100644 --- a/packages/svelte/src/internal/client/reactivity/async.js +++ b/packages/svelte/src/internal/client/reactivity/async.js @@ -33,7 +33,6 @@ import { set_hydrating, skip_nodes } from '../dom/hydration.js'; -import { create_text } from '../dom/operations.js'; /** * @@ -102,11 +101,11 @@ export function capture() { var previous_dev_stack = dev_stack; } - return function restore() { + return function restore(activate_batch = true) { set_active_effect(previous_effect); set_active_reaction(previous_reaction); set_component_context(previous_component_context); - previous_batch?.activate(); + if (activate_batch) previous_batch?.activate(); if (was_hydrating) { set_hydrating(true);