fix: don't create async deriveds for a component destroyed while waiting for its top-level `await` (#18931)

Fixes #18930

---------

Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
pull/18847/merge
jarrednorris 14 hours ago committed by GitHub
parent 79a0c0d4d8
commit 179f66b297
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: don't create async deriveds for a component destroyed while waiting for its top-level `await`

@ -103,6 +103,11 @@ export function flatten(blockers, sync, async, fn) {
if (blocker_promise) {
blocker_promise.then(() => {
if ((parent.f & DESTROYED) !== 0) {
decrement_pending();
return;
}
restore();
run();
unset_context();

@ -0,0 +1,7 @@
<script>
let { promise } = $props();
const value = await promise;
</script>
<p>{await Promise.resolve(value)}</p>

@ -0,0 +1,31 @@
import { tick } from 'svelte';
import { test } from '../../test';
export default test({
async test({ assert, target }) {
const [hide, resolve] = target.querySelectorAll('button');
assert.htmlEqual(
target.innerHTML,
`
<button>hide</button>
<button>resolve</button>
<p>loading...</p>
`
);
hide.click();
await tick();
resolve.click();
await tick();
assert.htmlEqual(
target.innerHTML,
`
<button>hide</button>
<button>resolve</button>
`
);
}
});

@ -0,0 +1,20 @@
<script>
import Child from './Child.svelte';
const deferred = Promise.withResolvers();
let show = $state(true);
</script>
<button onclick={() => (show = false)}>hide</button>
<button onclick={() => deferred.resolve(1)}>resolve</button>
<svelte:boundary>
{#if show}
<Child promise={deferred.promise} />
{/if}
{#snippet pending()}
<p>loading...</p>
{/snippet}
</svelte:boundary>
Loading…
Cancel
Save