mirror of https://github.com/sveltejs/svelte
fix: reject pending async deriveds on discard (#18308)
The rejects all async deriveds of a batch as `OBSOLETE`, so they don't hang around and bail early without triggering the batch. If we don't do this, an async derived can trigger the already done batch, which schedules an effect that is never flushed. Because it is never flushed the branches it touched on its way up are never cleared, and so anything else in that subtree is now unreactive.rolldown
parent
3ef761b87b
commit
a81f96549d
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: reject pending async deriveds on discard
|
||||
@ -0,0 +1,39 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target, logs }) {
|
||||
await tick();
|
||||
const [fork, real, resolve] = target.querySelectorAll('button');
|
||||
|
||||
fork.click();
|
||||
await tick();
|
||||
resolve.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
0
|
||||
<button>fork</button>
|
||||
<button>real</button>
|
||||
<button>resolve</button>
|
||||
`
|
||||
);
|
||||
assert.deepEqual(logs, [0]);
|
||||
|
||||
real.click();
|
||||
await tick();
|
||||
resolve.click();
|
||||
await tick();
|
||||
assert.htmlEqual(
|
||||
target.innerHTML,
|
||||
`
|
||||
1
|
||||
<button>fork</button>
|
||||
<button>real</button>
|
||||
<button>resolve</button>
|
||||
`
|
||||
);
|
||||
assert.deepEqual(logs, [0, 1]);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,23 @@
|
||||
<script>
|
||||
import { fork } from "svelte";
|
||||
|
||||
let count = $state(0);
|
||||
let queued = [];
|
||||
|
||||
function push(v) {
|
||||
if (!v) return v;
|
||||
|
||||
return new Promise((resolve) => {
|
||||
queued.push(() => resolve(v));
|
||||
});
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
console.log(count);
|
||||
})
|
||||
</script>
|
||||
|
||||
{await push(count)}
|
||||
<button onclick={() => fork(() => count++).discard()}>fork</button>
|
||||
<button onclick={() => count++}>real</button>
|
||||
<button onclick={() => queued.shift()?.()}>resolve</button>
|
||||
Loading…
Reference in new issue