diff --git a/.changeset/tough-meals-scream.md b/.changeset/tough-meals-scream.md new file mode 100644 index 000000000000..c11ba31b1d35 --- /dev/null +++ b/.changeset/tough-meals-scream.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +Restore flushSync optimizations from #15855 to replace the one from #15895 diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index d790c0ad145a..efc5b6a1d729 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -47,6 +47,7 @@ const handled_errors = new WeakSet(); let is_throwing_error = false; let is_flushing = false; +let is_flushing_sync = false; /** @type {Effect | null} */ let last_scheduled_effect = null; @@ -734,7 +735,9 @@ function flush_queued_effects(effects) { export function schedule_effect(signal) { if (!is_flushing) { is_flushing = true; - queueMicrotask(flush_queued_root_effects); + if (!is_flushing_sync) { + queueMicrotask(flush_queued_root_effects); + } } var effect = (last_scheduled_effect = signal); @@ -818,25 +821,33 @@ function process_effects(root) { * @returns {T} */ export function flushSync(fn) { - var result; + var previously_flushing_sync = is_flushing_sync; - if (fn) { - is_flushing = true; - flush_queued_root_effects(); + try { + var result; + is_flushing_sync = true; - is_flushing = true; - result = fn(); - } + if (fn) { + is_flushing = true; + flush_queued_root_effects(); + result = fn(); + } - while (true) { - flush_tasks(); + while (true) { + // is_flushing cannot be set to `true` before `flush_tasks` because it + // causes the regression at #16076, this can only be observed + // in browser and not in jsdom + flush_tasks(); - if (queued_root_effects.length === 0) { - return /** @type {T} */ (result); - } + if (queued_root_effects.length === 0) { + return /** @type {T} */ (result); + } - is_flushing = true; - flush_queued_root_effects(); + is_flushing = true; + flush_queued_root_effects(); + } + } finally { + is_flushing_sync = previously_flushing_sync; } } diff --git a/packages/svelte/tests/runtime-runes/samples/set-and-flushsync-conditionally-rendered-state/_config.js b/packages/svelte/tests/runtime-runes/samples/set-and-flushsync-conditionally-rendered-state/_config.js new file mode 100644 index 000000000000..66018e0b39a2 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/set-and-flushsync-conditionally-rendered-state/_config.js @@ -0,0 +1,33 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +// This test does not fail when the fix is removed, some jsdom/nodejs quirk, this requires browser mode to be tested +export default test({ + html: `