mirror of https://github.com/sveltejs/svelte
We shouldn't continue executing async work where we know the surrounding branch is destroyed already, it can leave to noisy "derived inter" warnings or even runtime errors ("cannot stringify symbol" when running a template effect with an uninitialized source). Neither should we warn about waterfalls on an already-destroyed async effect.
Fixes #18097 (though strictly speaking that particular instance is also fixed by #18117 which fixes the underlying cause for the reruns; this one is necessary in itself though, as shown by the new test)
async-obsolete-branch-fix
parent
7fddfbdbbd
commit
a2bbfb9173
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: abort running obsolete async branches
|
||||
@ -0,0 +1,6 @@
|
||||
<script>
|
||||
let { count } = $props();
|
||||
let double = $derived(count * 2);
|
||||
|
||||
$effect.pre(() => console.log(count, double));
|
||||
</script>
|
||||
@ -0,0 +1,27 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target, logs, warnings }) {
|
||||
const [increment, resolve] = target.querySelectorAll('button');
|
||||
|
||||
increment.click();
|
||||
await tick();
|
||||
assert.deepEqual(logs, []);
|
||||
|
||||
resolve.click();
|
||||
await tick();
|
||||
assert.deepEqual(logs, []);
|
||||
|
||||
resolve.click();
|
||||
await tick();
|
||||
assert.deepEqual(logs, []);
|
||||
|
||||
resolve.click();
|
||||
await tick();
|
||||
assert.deepEqual(logs, [1, 2]);
|
||||
|
||||
// no await waterfall / inert derived warnings
|
||||
assert.deepEqual(warnings, []);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,31 @@
|
||||
<script>
|
||||
import Child from "./Child.svelte";
|
||||
let count = $state(0);
|
||||
|
||||
let deferreds = [];
|
||||
|
||||
function push(v) {
|
||||
return new Promise((resolve, reject) => {
|
||||
deferreds.push({ resolve: () => resolve(v), reject });
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<button onclick={() => count += 1}>increment</button>
|
||||
<button onclick={() => deferreds.shift()?.resolve()}>resolve</button>
|
||||
|
||||
<svelte:boundary>
|
||||
{#if count % 2 === 0}
|
||||
{@const double = count * 2}
|
||||
<p>true</p>
|
||||
{await push(count)} {double}
|
||||
<Child count={await push(count)} />
|
||||
{:else}
|
||||
<p>false</p>
|
||||
<Child count={await push(count)} />
|
||||
{/if}
|
||||
|
||||
{#snippet pending()}
|
||||
<p>loading...</p>
|
||||
{/snippet}
|
||||
</svelte:boundary>
|
||||
Loading…
Reference in new issue