diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/AwaitExpression.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/AwaitExpression.js index 5b2005fbe4..c176eec3f4 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/AwaitExpression.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/AwaitExpression.js @@ -14,7 +14,7 @@ export function AwaitExpression(node, context) { if (context.state.expression) { suspend = true; - // wrap the expression in `(await $.suspend(...)).exit()` if necessary, + // wrap the expression in `(await $.save(...)).restore()` if necessary, // i.e. whether anything could potentially be read _after_ the await let i = context.path.length; while (i--) { diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/AwaitExpression.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/AwaitExpression.js index 7e5e44eebb..1341d13ff4 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/AwaitExpression.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/AwaitExpression.js @@ -16,12 +16,9 @@ export function AwaitExpression(node, context) { return b.call( b.member( b.await( - b.call( - '$.suspend', - node.argument && /** @type {Expression} */ (context.visit(node.argument)) - ) + b.call('$.save', node.argument && /** @type {Expression} */ (context.visit(node.argument))) ), - 'exit' + 'restore' ) ); } diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js index 244e9011f3..9ea5d5be16 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js @@ -171,14 +171,14 @@ export function VariableDeclaration(node, context) { b.member( b.await( b.call( - '$.suspend', + '$.save', b.call( '$.async_derived', rune === '$derived.by' ? value : b.thunk(value, true) ) ) ), - 'exit' + 'restore' ) ) ) diff --git a/packages/svelte/src/internal/client/dom/blocks/async.js b/packages/svelte/src/internal/client/dom/blocks/async.js index 0ffeb0591b..4d2a624559 100644 --- a/packages/svelte/src/internal/client/dom/blocks/async.js +++ b/packages/svelte/src/internal/client/dom/blocks/async.js @@ -1,7 +1,7 @@ /** @import { TemplateNode, Value } from '#client' */ import { async_derived } from '../../reactivity/deriveds.js'; -import { suspend } from './boundary.js'; +import { save } from './boundary.js'; /** * @param {TemplateNode} node @@ -11,7 +11,7 @@ import { suspend } from './boundary.js'; export function async(node, expressions, fn) { // TODO handle hydration - suspend(Promise.all(expressions.map(async_derived))).then((result) => { - fn(node, ...result.exit()); + save(Promise.all(expressions.map(async_derived))).then((result) => { + fn(node, ...result.restore()); }); } diff --git a/packages/svelte/src/internal/client/dom/blocks/boundary.js b/packages/svelte/src/internal/client/dom/blocks/boundary.js index 8df3098a01..b0f3fc605f 100644 --- a/packages/svelte/src/internal/client/dom/blocks/boundary.js +++ b/packages/svelte/src/internal/client/dom/blocks/boundary.js @@ -253,15 +253,28 @@ export function boundary(node, props, boundary_fn) { // TODO separate this stuff out — suspending and context preservation should // be distinct concepts +function capture() { + var previous_effect = active_effect; + var previous_reaction = active_reaction; + var previous_component_context = component_context; + + return function restore() { + set_active_effect(previous_effect); + set_active_reaction(previous_reaction); + set_component_context(previous_component_context); + + // prevent the active effect from outstaying its welcome + queue_post_micro_task(exit); + }; +} + /** * @template T * @param {Promise} promise - * @returns {Promise<{ exit: () => T }>} + * @returns {Promise<{ restore: () => T }>} */ -export async function suspend(promise) { - var previous_effect = active_effect; - var previous_reaction = active_reaction; - var previous_component_context = component_context; +export async function save(promise) { + var restore = capture(); let boundary = active_effect; while (boundary !== null) { @@ -282,13 +295,8 @@ export async function suspend(promise) { const value = await promise; return { - exit() { - set_active_effect(previous_effect); - set_active_reaction(previous_reaction); - set_component_context(previous_component_context); - - // prevent the active effect from outstaying its welcome - queue_post_micro_task(exit); + restore() { + restore(); // @ts-ignore boundary?.fn(ASYNC_DECREMENT); diff --git a/packages/svelte/src/internal/client/index.js b/packages/svelte/src/internal/client/index.js index 842343a119..0bdf8281e0 100644 --- a/packages/svelte/src/internal/client/index.js +++ b/packages/svelte/src/internal/client/index.js @@ -130,7 +130,7 @@ export { update_store, mark_store_binding } from './reactivity/store.js'; -export { boundary, exit, suspend } from './dom/blocks/boundary.js'; +export { boundary, exit, save } from './dom/blocks/boundary.js'; export { set_text } from './render.js'; export { get, diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js index b8f58395e3..be0f54798a 100644 --- a/packages/svelte/src/internal/client/reactivity/deriveds.js +++ b/packages/svelte/src/internal/client/reactivity/deriveds.js @@ -27,7 +27,7 @@ import { block, destroy_effect } from './effects.js'; import { inspect_effects, internal_set, set_inspect_effects, source } from './sources.js'; import { get_stack } from '../dev/tracing.js'; import { tracing_mode_flag } from '../../flags/index.js'; -import { exit, suspend } from '../dom/blocks/boundary.js'; +import { exit, save } from '../dom/blocks/boundary.js'; /** * @template V @@ -95,7 +95,7 @@ export function async_derived(fn) { block(() => { var current = (promise = fn()); - var derived_promise = suspend(promise); + var derived_promise = save(promise); derived_promise.then((v) => { if ((effect.f & DESTROYED) !== 0) { @@ -103,14 +103,14 @@ export function async_derived(fn) { } if (promise === current) { - internal_set(value, v.exit()); + internal_set(value, v.restore()); // TODO at the very least the naming is weird here exit(); } }); - derived_promise.catch(e => { + derived_promise.catch((e) => { handle_error(e, effect, null, effect.ctx); }); }, EFFECT_HAS_DERIVED); diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index b543208653..dd5a9731a5 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -45,7 +45,7 @@ import { DEV } from 'esm-env'; import { define_property } from '../../shared/utils.js'; import { get_next_sibling } from '../dom/operations.js'; import { async_derived, derived, destroy_derived } from './deriveds.js'; -import { suspend } from '../dom/blocks/boundary.js'; +import { save } from '../dom/blocks/boundary.js'; /** * @param {'$effect' | '$effect.pre' | '$inspect'} rune @@ -353,12 +353,12 @@ export function template_effect(fn, sync = [], async = [], d = derived) { let effect = /** @type {Effect} */ (active_effect); if (async.length > 0) { - suspend(Promise.all(async.map(async_derived))).then((result) => { + save(Promise.all(async.map(async_derived))).then((result) => { if ((effect.f & DESTROYED) !== 0) { return; } - create_template_effect(fn, [...sync.map(d), ...result.exit()]); + create_template_effect(fn, [...sync.map(d), ...result.restore()]); }); } else { create_template_effect(fn, sync.map(d));