restore updating content.wv on fork commit

apply() uses the batch's recorded write versions while other batches are pending, so they must
match the fresh versions given to the sources on commit.
async-another-try-pt-1-prune
Rich Harris 2 days ago
parent 3e92edfbf4
commit 498a696ac8
No known key found for this signature in database

@ -1431,7 +1431,7 @@ export function fork(fn) {
// apply changes and update write versions so deriveds see the change
for (var [source, content] of batch.current) {
source.v = content.v;
source.wv = increment_write_version();
content.wv = source.wv = increment_write_version();
}
// trigger any `$state.eager(...)` expressions with the new state.

@ -0,0 +1,35 @@
import { tick } from 'svelte';
import { test } from '../../test';
const buttons =
'<button>u</button><button>fork</button><button>cond</button><button>commit</button><button>shift</button>';
// The template effect is deferred by the fork (it depends on `s` via `big`), but before the
// fork is committed, it re-runs in the real world and starts reading `s` directly.
// Committing the fork (while another batch is pending) must still update it.
export default test({
async test({ assert, target }) {
await tick();
const [u, f, cond, commit, shift] = target.querySelectorAll('button');
// unrelated pending batch
u.click();
await tick();
f.click();
await tick();
assert.htmlEqual(target.innerHTML, `${buttons}<p>0</p><p>false</p>`);
cond.click();
await tick();
assert.htmlEqual(target.innerHTML, `${buttons}<p>0</p><p>0</p>`);
commit.click();
await tick();
assert.htmlEqual(target.innerHTML, `${buttons}<p>0</p><p>1</p>`);
shift.click();
await tick();
assert.htmlEqual(target.innerHTML, `${buttons}<p>1</p><p>1</p>`);
}
});

@ -0,0 +1,25 @@
<script>
import { fork } from 'svelte';
let s = $state(0);
let cond = $state(false);
let u = $state(0);
let big = $derived(s > 100);
const queue = [];
function push(v) {
if (!v) return v;
return new Promise((r) => queue.push(() => r(v)));
}
let f;
</script>
<button onclick={() => u++}>u</button>
<button onclick={() => (f = fork(() => s++))}>fork</button>
<button onclick={() => (cond = true)}>cond</button>
<button onclick={() => f.commit()}>commit</button>
<button onclick={() => queue.shift()()}>shift</button>
<p>{await push(u)}</p>
<p>{cond ? s : big}</p>
Loading…
Cancel
Save