diff --git a/packages/svelte/src/internal/client/dom/blocks/await.js b/packages/svelte/src/internal/client/dom/blocks/await.js index 8605812f1ee7..e7917fbd9e45 100644 --- a/packages/svelte/src/internal/client/dom/blocks/await.js +++ b/packages/svelte/src/internal/client/dom/blocks/await.js @@ -22,7 +22,7 @@ import { set_dev_current_component_function, set_dev_stack } from '../../context.js'; -import { flushSync } from '../../reactivity/batch.js'; +import { flushSync, is_flushing_sync } from '../../reactivity/batch.js'; const PENDING = 0; const THEN = 1; @@ -126,7 +126,7 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) { // without this, the DOM does not update until two ticks after the promise // resolves, which is unexpected behaviour (and somewhat irksome to test) - flushSync(); + if (!is_flushing_sync) flushSync(); } } } diff --git a/packages/svelte/src/internal/client/dom/task.js b/packages/svelte/src/internal/client/dom/task.js index 1a47eee6cfb1..8c513614672b 100644 --- a/packages/svelte/src/internal/client/dom/task.js +++ b/packages/svelte/src/internal/client/dom/task.js @@ -10,10 +10,6 @@ function run_micro_tasks() { run_all(tasks); } -export function has_pending_tasks() { - return micro_tasks.length > 0; -} - /** * @param {() => void} fn */ @@ -40,7 +36,7 @@ export function queue_micro_task(fn) { * Synchronously run any queued tasks. */ export function flush_tasks() { - if (micro_tasks.length > 0) { + while (micro_tasks.length > 0) { run_micro_tasks(); } } diff --git a/packages/svelte/src/internal/client/reactivity/batch.js b/packages/svelte/src/internal/client/reactivity/batch.js index 10d4ef4435ed..8cf0e4bd9db1 100644 --- a/packages/svelte/src/internal/client/reactivity/batch.js +++ b/packages/svelte/src/internal/client/reactivity/batch.js @@ -23,7 +23,7 @@ import { update_effect } from '../runtime.js'; import * as e from '../errors.js'; -import { flush_tasks, has_pending_tasks, queue_micro_task } from '../dom/task.js'; +import { flush_tasks, queue_micro_task } from '../dom/task.js'; import { DEV } from 'esm-env'; import { invoke_error_boundary } from '../error-handling.js'; import { old_values } from './sources.js'; @@ -355,20 +355,18 @@ export class Batch { } flush() { - this.activate(); - if (queued_root_effects.length > 0) { + this.activate(); flush_effects(); + + if (current_batch !== null && current_batch !== this) { + // this can happen if a new batch was created during `flush_effects()` + return; + } } else if (this.#pending === 0) { this.#commit(); } - if (current_batch !== null && current_batch !== this) { - // this can happen if a `flushSync` occurred during `flush_effects()`, - // which is permitted in legacy mode despite being a terrible idea - return; - } - this.deactivate(); } @@ -468,14 +466,17 @@ export function flushSync(fn) { var result; if (fn) { - flush_effects(); + if (current_batch !== null) { + flush_effects(); + } + result = fn(); } while (true) { flush_tasks(); - if (queued_root_effects.length === 0 && !has_pending_tasks()) { + if (queued_root_effects.length === 0) { current_batch?.flush(); // we need to check again, in case we just updated an `$effect.pending()`