restore removal of batch_values.delete(derived) in mark_reactions

A derived's batch-local value can be a later batch's previous value; deleting it makes the next
read fall back to the real (later batch's) value.
async-another-try-pt-1-prune
Rich Harris 2 days ago
parent 70bb7f4295
commit 737de2e4f3
No known key found for this signature in database

@ -411,7 +411,6 @@ function mark_reactions(signal, status, updated_during_traversal) {
} else if ((flags & DERIVED) !== 0) {
var derived = /** @type {Derived} */ (reaction);
batch_values?.delete(derived);
mark_reactions(derived, MAYBE_DIRTY, updated_during_traversal);
} else if (not_dirty) {
var effect = /** @type {Effect} */ (reaction);

@ -0,0 +1,33 @@
import { tick } from 'svelte';
import { test } from '../../test';
const buttons = '<button>x</button><button>t</button><button>shift</button>';
// While batch A (x) commits, a pre effect writes to `s`. That marks `label` (via `big`) as
// maybe dirty, but it doesn't actually change. `label` must still show the value from A's
// point of view, not the one from the later, still-pending batch B (t).
export default test({
async test({ assert, target }) {
await tick();
const [x, t, shift] = target.querySelectorAll('button');
// A
x.click();
await tick();
// B
t.click();
await tick();
assert.htmlEqual(target.innerHTML, `${buttons}<p>0</p><p>0</p><p>0 false-0</p>`);
// A commits, B is still pending
shift.click();
await tick();
assert.htmlEqual(target.innerHTML, `${buttons}<p>1</p><p>0</p><p>1 false-0</p>`);
// B commits
shift.click();
await tick();
assert.htmlEqual(target.innerHTML, `${buttons}<p>1</p><p>1</p><p>1 false-1</p>`);
}
});

@ -0,0 +1,32 @@
<script>
import { untrack } from 'svelte';
let x = $state(0);
let t = $state(0);
let s = $state(0);
// `s` changes, but `big` doesn't
let big = $derived(s > 100);
let label = $derived(`${big}-${t}`);
const queue = [];
function push(v) {
if (!v) return v;
return new Promise((r) => queue.push(() => r(v)));
}
$effect.pre(() => {
if (x) untrack(() => s++);
});
</script>
<button onclick={() => x++}>x</button>
<button onclick={() => t++}>t</button>
<button onclick={() => queue.shift()()}>shift</button>
<p>{await push(x)}</p>
<p>{await push(t)}</p>
<!-- evaluates `label` during traversal of B -->
{#key label}{/key}
<p>{x} {label}</p>
Loading…
Cancel
Save