From 0dc84ab2a21a98818053f6d885578c76bd5c5a25 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 3 Feb 2025 12:06:52 -0500 Subject: [PATCH] only suspend in top-level async deriveds --- .../src/internal/client/reactivity/deriveds.js | 6 +++++- .../samples/async-nested-derived/Child.svelte | 11 +++++++++++ .../samples/async-nested-derived/_config.js | 14 ++++++++++++++ .../samples/async-nested-derived/main.svelte | 17 +++++++++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 packages/svelte/tests/runtime-runes/samples/async-nested-derived/Child.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/async-nested-derived/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/async-nested-derived/main.svelte diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js index f1d63bd1fa..0735b7296c 100644 --- a/packages/svelte/src/internal/client/reactivity/deriveds.js +++ b/packages/svelte/src/internal/client/reactivity/deriveds.js @@ -29,6 +29,7 @@ import { get_stack } from '../dev/tracing.js'; import { tracing_mode_flag } from '../../flags/index.js'; import { capture, suspend } from '../dom/blocks/boundary.js'; import { component_context } from '../context.js'; +import { noop } from '../../shared/utils.js'; /** @type {Effect | null} */ export let from_async_derived = null; @@ -100,6 +101,9 @@ export function async_derived(fn, detect_waterfall = true) { var promise = /** @type {Promise} */ (/** @type {unknown} */ (undefined)); var value = source(/** @type {V} */ (undefined)); + // only suspend in async deriveds created on initialisation + var should_suspend = !active_reaction; + // TODO this isn't a block block(async () => { if (DEV) from_async_derived = active_effect; @@ -107,7 +111,7 @@ export function async_derived(fn, detect_waterfall = true) { if (DEV) from_async_derived = null; var restore = capture(); - var unsuspend = suspend(); + var unsuspend = should_suspend ? suspend() : noop; try { var v = await promise; diff --git a/packages/svelte/tests/runtime-runes/samples/async-nested-derived/Child.svelte b/packages/svelte/tests/runtime-runes/samples/async-nested-derived/Child.svelte new file mode 100644 index 0000000000..546494f4c3 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-nested-derived/Child.svelte @@ -0,0 +1,11 @@ + + +

{indirect}

diff --git a/packages/svelte/tests/runtime-runes/samples/async-nested-derived/_config.js b/packages/svelte/tests/runtime-runes/samples/async-nested-derived/_config.js new file mode 100644 index 0000000000..172b44e6e3 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-nested-derived/_config.js @@ -0,0 +1,14 @@ +import { flushSync, tick } from 'svelte'; +import { test } from '../../test'; + +export default test({ + async test({ assert, target }) { + await tick(); + assert.htmlEqual(target.innerHTML, '

0

'); + + const button = target.querySelector('button'); + + flushSync(() => button?.click()); + assert.htmlEqual(target.innerHTML, '

1

'); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/async-nested-derived/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-nested-derived/main.svelte new file mode 100644 index 0000000000..e5306f1925 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-nested-derived/main.svelte @@ -0,0 +1,17 @@ + + + + + + + + {#snippet pending()} +

pending

+ {/snippet} +
+ +{console.log(`outside boundary ${count}`)}