From 925dbebdd64467cf677c86594b4764c609349f89 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 21 Oct 2025 12:23:17 -0700 Subject: [PATCH] add test, fix block resolution --- .../src/internal/client/reactivity/batch.js | 28 ++++----- .../samples/async-block-resolve/_config.js | 63 +++++++++++++++++++ .../samples/async-block-resolve/main.svelte | 36 +++++++++++ 3 files changed, 112 insertions(+), 15 deletions(-) create mode 100644 packages/svelte/tests/runtime-runes/samples/async-block-resolve/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/async-block-resolve/main.svelte diff --git a/packages/svelte/src/internal/client/reactivity/batch.js b/packages/svelte/src/internal/client/reactivity/batch.js index 215b992cc4..f35003db10 100644 --- a/packages/svelte/src/internal/client/reactivity/batch.js +++ b/packages/svelte/src/internal/client/reactivity/batch.js @@ -157,12 +157,7 @@ export class Batch { this.#traverse_effect_tree(root, target); } - // if there is no outstanding async work, commit - if (this.#pending === 0) { - // commit before flushing effects, since that may result in - // another batch being created - this.#commit(); - } + this.#resolve(); if (this.#blocking_pending > 0) { this.#defer_effects(target.effects); @@ -300,8 +295,8 @@ export class Batch { // this can happen if a new batch was created during `flush_effects()` return; } - } else if (this.#pending === 0) { - this.#commit(); + } else { + this.#resolve(); } this.deactivate(); @@ -317,16 +312,19 @@ export class Batch { } } - /** - * Append and remove branches to/from the DOM - */ - #commit() { - for (const fn of this.#callbacks) { - fn(); + #resolve() { + if (this.#blocking_pending === 0) { + // append/remove branches + for (const fn of this.#callbacks) fn(); + this.#callbacks.clear(); } - this.#callbacks.clear(); + if (this.#pending === 0) { + this.#commit(); + } + } + #commit() { // If there are other pending batches, they now need to be 'rebased' — // in other words, we re-run block/async effects with the newly // committed state, unless the batch in question has a more diff --git a/packages/svelte/tests/runtime-runes/samples/async-block-resolve/_config.js b/packages/svelte/tests/runtime-runes/samples/async-block-resolve/_config.js new file mode 100644 index 0000000000..ee403290bc --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-block-resolve/_config.js @@ -0,0 +1,63 @@ +import { tick } from 'svelte'; +import { test } from '../../test'; + +export default test({ + async test({ assert, target }) { + const [increment, shift] = target.querySelectorAll('button'); + + shift.click(); + await tick(); + + shift.click(); + await tick(); + + assert.htmlEqual( + target.innerHTML, + ` + + +

even

+

0

+ ` + ); + + increment.click(); + await tick(); + + assert.htmlEqual( + target.innerHTML, + ` + + +

even

+

0

+ ` + ); + + shift.click(); + await tick(); + + assert.htmlEqual( + target.innerHTML, + ` + + +

odd

+

loading...

+ ` + ); + + shift.click(); + await tick(); + + assert.htmlEqual( + target.innerHTML, + ` + + +

odd

+

1

+ ` + ); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/async-block-resolve/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-block-resolve/main.svelte new file mode 100644 index 0000000000..73fe83889a --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-block-resolve/main.svelte @@ -0,0 +1,36 @@ + + + + + + + {#if await push(count) % 2 === 0} +

even

+ {:else} +

odd

+ {/if} + + {#key count} + +

{await push(count)}

+ + {#snippet pending()} +

loading...

+ {/snippet} +
+ {/key} + + {#snippet pending()} +

loading...

+ {/snippet} +