Skip to content

Commit 2071160

Browse files
committed
keep order
1 parent 7e83cda commit 2071160

File tree

3 files changed

+126
-26
lines changed

3 files changed

+126
-26
lines changed

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

Lines changed: 69 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,61 @@ export class Batch {
8686
}
8787

8888
if (this.async_effects.length === 0 && this.settled()) {
89-
var render_effects = this.render_effects;
90-
var effects = this.effects;
89+
var merged = false;
90+
91+
// if there are older batches with overlapping
92+
// state, we can't commit this batch. instead,
93+
// we merge it into the older batches
94+
for (const batch of batches) {
95+
if (batch === this) break;
96+
97+
for (const [source] of batch.#current) {
98+
if (this.#current.has(source)) {
99+
merged = true;
100+
101+
for (const [source, value] of this.#current) {
102+
batch.#current.set(source, value);
103+
// TODO what about batch.#previous?
104+
}
105+
106+
for (const e of this.render_effects) {
107+
set_signal_status(e, CLEAN);
108+
// TODO use sets instead of arrays
109+
if (!batch.render_effects.includes(e)) {
110+
batch.render_effects.push(e);
111+
}
112+
}
113+
114+
for (const e of this.effects) {
115+
set_signal_status(e, CLEAN);
116+
// TODO use sets instead of arrays
117+
if (!batch.effects.includes(e)) {
118+
batch.effects.push(e);
119+
}
120+
}
121+
122+
this.remove();
123+
break;
124+
}
125+
}
126+
}
91127

92-
this.render_effects = [];
93-
this.effects = [];
128+
if (merged) {
129+
this.remove();
130+
} else {
131+
var render_effects = this.render_effects;
132+
var effects = this.effects;
94133

95-
this.commit();
134+
this.render_effects = [];
135+
this.effects = [];
136+
137+
this.commit();
96138

97-
flush_queued_effects(render_effects);
98-
flush_queued_effects(effects);
139+
flush_queued_effects(render_effects);
140+
flush_queued_effects(effects);
99141

100-
this.deferred?.resolve();
142+
this.deferred?.resolve();
143+
}
101144
} else {
102145
for (const e of this.render_effects) set_signal_status(e, CLEAN);
103146
for (const e of this.effects) set_signal_status(e, CLEAN);
@@ -133,24 +176,24 @@ export class Batch {
133176
remove() {
134177
batches.delete(this);
135178

136-
for (var batch of batches) {
137-
/** @type {Source} */
138-
var source;
139-
140-
if (batch.#id < this.#id) {
141-
// other batch is older than this
142-
for (source of this.#previous.keys()) {
143-
batch.#previous.delete(source);
144-
}
145-
} else {
146-
// other batch is newer than this
147-
for (source of batch.#previous.keys()) {
148-
if (this.#previous.has(source)) {
149-
batch.#previous.set(source, source.v);
150-
}
151-
}
152-
}
153-
}
179+
// for (var batch of batches) {
180+
// /** @type {Source} */
181+
// var source;
182+
183+
// if (batch.#id < this.#id) {
184+
// // other batch is older than this
185+
// for (source of this.#previous.keys()) {
186+
// batch.#previous.delete(source);
187+
// }
188+
// } else {
189+
// // other batch is newer than this
190+
// for (source of batch.#previous.keys()) {
191+
// if (this.#previous.has(source)) {
192+
// batch.#previous.set(source, source.v);
193+
// }
194+
// }
195+
// }
196+
// }
154197
}
155198

156199
restore() {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { flushSync, settled, tick } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
html: `<button>both</button><button>a</button><button>b</button><p>loading...</p>`,
6+
7+
async test({ assert, target }) {
8+
const [both, a, b] = target.querySelectorAll('button');
9+
10+
await Promise.resolve();
11+
await Promise.resolve();
12+
await Promise.resolve();
13+
await Promise.resolve();
14+
15+
assert.htmlEqual(
16+
target.innerHTML,
17+
`
18+
<button>both</button><button>a</button><button>b</button>
19+
<p>1 * 2 = 2</p>
20+
<p>2 * 2 = 4</p>
21+
`
22+
);
23+
24+
flushSync(() => both.click());
25+
flushSync(() => b.click());
26+
27+
await Promise.resolve();
28+
await Promise.resolve();
29+
await Promise.resolve();
30+
31+
assert.htmlEqual(
32+
target.innerHTML,
33+
`
34+
<button>both</button><button>a</button><button>b</button>
35+
<p>2 * 2 = 4</p>
36+
<p>4 * 2 = 8</p>
37+
`
38+
);
39+
}
40+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<script>
2+
let a = $state(1);
3+
let b = $state(2);
4+
</script>
5+
6+
<button onclick={() => {a += 1; b += 1;}}>both</button>
7+
<button onclick={() => {a += 1;}}>a</button>
8+
<button onclick={() => {b += 1;}}>b</button>
9+
10+
<svelte:boundary>
11+
<p>{a} * 2 = {await (a * 2)}</p>
12+
<p>{b} * 2 = {b * 2}</p>
13+
14+
{#snippet pending()}
15+
<p>loading...</p>
16+
{/snippet}
17+
</svelte:boundary>

0 commit comments

Comments
 (0)