diff --git a/packages/svelte/src/internal/client/dom/blocks/async.js b/packages/svelte/src/internal/client/dom/blocks/async.js index c3283081ab..18b0088d2f 100644 --- a/packages/svelte/src/internal/client/dom/blocks/async.js +++ b/packages/svelte/src/internal/client/dom/blocks/async.js @@ -22,14 +22,15 @@ export function async(node, expressions, fn) { boundary.increment(); Promise.all(expressions.map((fn) => async_derived(fn))).then((result) => { - batch.run(() => { - restore(); - fn(node, ...result); + batch?.restore(); - // TODO is this necessary? - schedule_effect(effect); - }); + restore(); + fn(node, ...result); + // TODO is this necessary? + schedule_effect(effect); + + batch?.flush(); boundary.decrement(); }); } diff --git a/packages/svelte/src/internal/client/reactivity/batch.js b/packages/svelte/src/internal/client/reactivity/batch.js index 8f36e9e693..d3b8933ab8 100644 --- a/packages/svelte/src/internal/client/reactivity/batch.js +++ b/packages/svelte/src/internal/client/reactivity/batch.js @@ -2,6 +2,7 @@ import { CLEAN, DIRTY } from '#client/constants'; import { flush_queued_effects, + flush_queued_root_effects, process_effects, schedule_effect, set_queued_root_effects, @@ -17,10 +18,6 @@ const batches = new Set(); /** @type {Batch | null} */ export let current_batch = null; -export function remove_current_batch() { - current_batch = null; -} - /** Update `$effect.pending()` */ function update_pending() { internal_set(pending, batches.size > 0); @@ -149,12 +146,21 @@ export class Batch { } } - /** - * @param {() => void} fn - */ - run(fn) { + restore() { current_batch = this; - fn(); + } + + flush() { + flush_queued_root_effects(); + + // TODO can this happen? + if (current_batch !== this) return; + + if (this.settled()) { + this.remove(); + } + + current_batch = null; } commit() { @@ -210,6 +216,15 @@ export class Batch { current_batch = new Batch(); batches.add(current_batch); + + queueMicrotask(() => { + if (current_batch === null) { + // a flushSync happened in the meantime + return; + } + + current_batch.flush(); + }); } return current_batch; diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js index 9c1390a0bf..03624b55a6 100644 --- a/packages/svelte/src/internal/client/reactivity/deriveds.js +++ b/packages/svelte/src/internal/client/reactivity/deriveds.js @@ -162,9 +162,9 @@ export function async_derived(fn, location) { } } - batch.run(() => { - internal_set(signal, v); - }); + batch?.restore(); + internal_set(signal, v); + batch?.flush(); if (DEV && location !== undefined) { recent_async_deriveds.add(signal); diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index 051b3f741f..e2ffcd41dd 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -357,9 +357,9 @@ export function template_effect(fn, sync = [], async = [], d = derived) { var effect = create_template_effect(fn, [...sync.map(d), ...result]); - batch.run(() => { - schedule_effect(effect); - }); + batch?.restore(); + schedule_effect(effect); + batch?.flush(); }); } else { create_template_effect(fn, sync.map(d)); diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 4accdb0ce6..085c1fa850 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -51,7 +51,7 @@ import { import { Boundary } from './dom/blocks/boundary.js'; import * as w from './warnings.js'; import { is_firefox } from './dom/operations.js'; -import { current_batch, Batch, remove_current_batch } from './reactivity/batch.js'; +import { current_batch, Batch } from './reactivity/batch.js'; import { log_effect_tree, root } from './dev/debug.js'; // Used for DEV time error handling @@ -693,7 +693,7 @@ function infinite_loop_guard() { } } -function flush_queued_root_effects() { +export function flush_queued_root_effects() { var was_updating_effect = is_updating_effect; var batch = /** @type {Batch} */ (current_batch); @@ -764,24 +764,6 @@ export function flush_queued_effects(effects) { * @returns {void} */ export function schedule_effect(signal) { - if (!is_flushing) { - is_flushing = true; - queueMicrotask(() => { - if (current_batch === null) { - // a flushSync happened in the meantime - return; - } - - flush_queued_root_effects(); - - if (current_batch?.settled()) { - current_batch.remove(); - } - - remove_current_batch(); - }); - } - var effect = (last_scheduled_effect = signal); while (effect.parent !== null) { @@ -868,7 +850,7 @@ export function process_effects(batch, root) { export function flushSync(fn) { var result; - Batch.ensure(); + const batch = Batch.ensure(); if (fn) { is_flushing = true; @@ -884,12 +866,10 @@ export function flushSync(fn) { flush_tasks(); } - if (current_batch?.settled()) { - current_batch.remove(); + if (batch === current_batch) { + batch.flush(); } - remove_current_batch(); - return /** @type {T} */ (result); }