Skip to content

Commit 925dbeb

Browse files
committed
add test, fix block resolution
1 parent cfa87a9 commit 925dbeb

File tree

3 files changed

+112
-15
lines changed

3 files changed

+112
-15
lines changed

packages/svelte/src/internal/client/reactivity/batch.js

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,7 @@ export class Batch {
157157
this.#traverse_effect_tree(root, target);
158158
}
159159

160-
// if there is no outstanding async work, commit
161-
if (this.#pending === 0) {
162-
// commit before flushing effects, since that may result in
163-
// another batch being created
164-
this.#commit();
165-
}
160+
this.#resolve();
166161

167162
if (this.#blocking_pending > 0) {
168163
this.#defer_effects(target.effects);
@@ -300,8 +295,8 @@ export class Batch {
300295
// this can happen if a new batch was created during `flush_effects()`
301296
return;
302297
}
303-
} else if (this.#pending === 0) {
304-
this.#commit();
298+
} else {
299+
this.#resolve();
305300
}
306301

307302
this.deactivate();
@@ -317,16 +312,19 @@ export class Batch {
317312
}
318313
}
319314

320-
/**
321-
* Append and remove branches to/from the DOM
322-
*/
323-
#commit() {
324-
for (const fn of this.#callbacks) {
325-
fn();
315+
#resolve() {
316+
if (this.#blocking_pending === 0) {
317+
// append/remove branches
318+
for (const fn of this.#callbacks) fn();
319+
this.#callbacks.clear();
326320
}
327321

328-
this.#callbacks.clear();
322+
if (this.#pending === 0) {
323+
this.#commit();
324+
}
325+
}
329326

327+
#commit() {
330328
// If there are other pending batches, they now need to be 'rebased' —
331329
// in other words, we re-run block/async effects with the newly
332330
// committed state, unless the batch in question has a more
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { tick } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
async test({ assert, target }) {
6+
const [increment, shift] = target.querySelectorAll('button');
7+
8+
shift.click();
9+
await tick();
10+
11+
shift.click();
12+
await tick();
13+
14+
assert.htmlEqual(
15+
target.innerHTML,
16+
`
17+
<button>0</button>
18+
<button>shift</button>
19+
<p>even</p>
20+
<p>0</p>
21+
`
22+
);
23+
24+
increment.click();
25+
await tick();
26+
27+
assert.htmlEqual(
28+
target.innerHTML,
29+
`
30+
<button>1</button>
31+
<button>shift</button>
32+
<p>even</p>
33+
<p>0</p>
34+
`
35+
);
36+
37+
shift.click();
38+
await tick();
39+
40+
assert.htmlEqual(
41+
target.innerHTML,
42+
`
43+
<button>1</button>
44+
<button>shift</button>
45+
<p>odd</p>
46+
<p>loading...</p>
47+
`
48+
);
49+
50+
shift.click();
51+
await tick();
52+
53+
assert.htmlEqual(
54+
target.innerHTML,
55+
`
56+
<button>1</button>
57+
<button>shift</button>
58+
<p>odd</p>
59+
<p>1</p>
60+
`
61+
);
62+
}
63+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<script>
2+
let resolvers = [];
3+
4+
function push(value) {
5+
const { promise, resolve } = Promise.withResolvers();
6+
resolvers.push(() => resolve(value));
7+
return promise;
8+
}
9+
10+
let count = $state(0);
11+
</script>
12+
13+
<button onclick={() => count += 1}>{$state.eager(count)}</button>
14+
<button onclick={() => resolvers.shift()?.()}>shift</button>
15+
16+
<svelte:boundary>
17+
{#if await push(count) % 2 === 0}
18+
<p>even</p>
19+
{:else}
20+
<p>odd</p>
21+
{/if}
22+
23+
{#key count}
24+
<svelte:boundary>
25+
<p>{await push(count)}</p>
26+
27+
{#snippet pending()}
28+
<p>loading...</p>
29+
{/snippet}
30+
</svelte:boundary>
31+
{/key}
32+
33+
{#snippet pending()}
34+
<p>loading...</p>
35+
{/snippet}
36+
</svelte:boundary>

0 commit comments

Comments
 (0)