From 05ac10ea27ff963e9a255c68849350f91febc150 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 27 Oct 2025 23:48:14 +0100 Subject: [PATCH] fix: don't restore batch in `#await` #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 000000000000..b74b00fa1c34 --- /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 bac01e4c3393..87d64df23ed5 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 fb836df98914..bdd7eed94065 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);