From fbec895913ee413a80a4ae1ced7c80387d23eb64 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 18 Aug 2025 10:32:39 -0400 Subject: [PATCH] use helper for async bodies --- .../3-transform/client/transform-client.js | 72 ++++++------------- .../svelte/src/internal/client/async_body.js | 14 ++++ packages/svelte/src/internal/client/index.js | 1 + 3 files changed, 36 insertions(+), 51 deletions(-) create mode 100644 packages/svelte/src/internal/client/async_body.js diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js index eb32f9c98b..1bfd563635 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js @@ -359,22 +359,38 @@ export function client_component(analysis, options) { if (dev) push_args.push(b.id(analysis.name)); let component_block = b.block([ + store_init, ...store_setup, ...legacy_reactive_declarations, ...group_binding_declarations, - ...state.instance_level_snippets, - .../** @type {ESTree.Statement[]} */ (instance.body), - analysis.runes || !analysis.needs_context - ? b.empty - : b.stmt(b.call('$.init', analysis.immutable ? b.true : undefined)) + ...state.instance_level_snippets ]); + if (analysis.instance.has_await) { + const body = b.block([ + .../** @type {ESTree.Statement[]} */ (instance.body), + b.if(b.call('$.aborted'), b.return()), + .../** @type {ESTree.Statement[]} */ (template.body) + ]); + + component_block.body.push(b.stmt(b.call(`$.async_body`, b.arrow([], body, true)))); + } else { + component_block.body.push( + .../** @type {ESTree.Statement[]} */ (instance.body), + .../** @type {ESTree.Statement[]} */ (template.body) + ); + } + if (analysis.needs_mutation_validation) { component_block.body.unshift( b.var('$$ownership_validator', b.call('$.create_ownership_validator', b.id('$$props'))) ); } + if (!analysis.runes && analysis.needs_context) { + component_block.body.push(b.stmt(b.call('$.init', analysis.immutable ? b.true : undefined))); + } + const should_inject_context = dev || analysis.needs_context || @@ -389,52 +405,6 @@ export function client_component(analysis, options) { analysis.uses_slots || analysis.slot_names.size > 0; - if (analysis.instance.has_await) { - const params = [b.id('$$anchor')]; - if (should_inject_props) { - params.push(b.id('$$props')); - } - if (store_setup.length > 0) { - params.push(b.id('$$stores')); - } - const body = b.function_declaration( - b.id('$$body'), - params, - b.block([ - b.var('$$unsuspend', b.call('$.suspend')), - b.var('$$active', b.id('$.active_effect')), - b.try_catch( - b.block([ - ...component_block.body, - b.if(b.call('$.aborted'), b.return()), - .../** @type {ESTree.Statement[]} */ (template.body) - ]), - b.block([ - b.if( - b.unary('!', b.call('$.aborted', b.id('$$active'))), - b.stmt(b.call('$.invoke_error_boundary', b.id('$$error'), b.id('$$active'))) - ) - ]) - ), - b.stmt(b.call('$$unsuspend')) - ]), - true - ); - - state.hoisted.push(body); - - component_block = b.block([ - b.var('fragment', b.call('$.comment')), - b.var('node', b.call('$.first_child', b.id('fragment'))), - store_init, - b.stmt(b.call(body.id, b.id('node'), ...params.slice(1))), - b.stmt(b.call('$.append', b.id('$$anchor'), b.id('fragment'))) - ]); - } else { - component_block.body.unshift(store_init); - component_block.body.push(.../** @type {ESTree.Statement[]} */ (template.body)); - } - // trick esrap into including comments component_block.loc = instance.loc; diff --git a/packages/svelte/src/internal/client/async_body.js b/packages/svelte/src/internal/client/async_body.js new file mode 100644 index 0000000000..2336e25ae2 --- /dev/null +++ b/packages/svelte/src/internal/client/async_body.js @@ -0,0 +1,14 @@ +import { suspend } from './reactivity/batch.js'; + +/** + * @param {() => Promise} fn + */ +export async function async_body(fn) { + const unsuspend = suspend(); + + try { + await fn(); + } finally { + unsuspend(); + } +} diff --git a/packages/svelte/src/internal/client/index.js b/packages/svelte/src/internal/client/index.js index 4089401a7e..3e030cbd2d 100644 --- a/packages/svelte/src/internal/client/index.js +++ b/packages/svelte/src/internal/client/index.js @@ -1,5 +1,6 @@ export { createAttachmentKey as attachment } from '../../attachments/index.js'; export { FILENAME, HMR, NAMESPACE_SVG } from '../../constants.js'; +export { async_body } from './async_body.js'; export { push, pop, add_svelte_meta } from './context.js'; export { assign, assign_and, assign_or, assign_nullish } from './dev/assign.js'; export { cleanup_styles } from './dev/css.js';