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 @@ + + + + + +even
+ {:else} +odd
+ {/if} + + {#key count} +{await push(count)}
+ + {#snippet pending()} +loading...
+ {/snippet} +loading...
+ {/snippet} +