From aa547c58e5442fdb683b62f04e5dca30d47f378b Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 25 Oct 2025 22:36:07 -0400 Subject: [PATCH] WIP --- .../server/visitors/SvelteElement.js | 28 ++++++++++++++++--- .../svelte/src/internal/server/renderer.js | 27 ++++++++++++++---- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteElement.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteElement.js index 2e61897924..145167a690 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteElement.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/SvelteElement.js @@ -6,7 +6,12 @@ import { dev, locator } from '../../../../state.js'; import * as b from '#compiler/builders'; import { determine_namespace_for_children } from '../../utils.js'; import { build_element_attributes } from './shared/element.js'; -import { build_template, create_child_block, PromiseOptimiser } from './shared/utils.js'; +import { + build_template, + create_async_block, + create_child_block, + PromiseOptimiser +} from './shared/utils.js'; /** * @param {AST.SvelteElement} node @@ -39,11 +44,14 @@ export function SvelteElement(node, context) { const optimiser = new PromiseOptimiser(); + /** @type {Statement[]} */ + let statements = []; + build_element_attributes(node, { ...context, state }, optimiser.transform); if (dev) { const location = /** @type {Location} */ (locator(node.start)); - context.state.template.push( + statements.push( b.stmt( b.call( '$.push_element', @@ -74,9 +82,21 @@ export function SvelteElement(node, context) { statement = create_child_block(b.block([optimiser.apply(), statement]), true); } - context.state.template.push(statement); + statements.push(statement); if (dev) { - context.state.template.push(b.stmt(b.call('$.pop_element'))); + statements.push(b.stmt(b.call('$.pop_element'))); } + + if (node.metadata.expression.is_async()) { + statements = [ + create_async_block( + b.block(statements), + node.metadata.expression.blockers(), + node.metadata.expression.has_await + ) + ]; + } + + context.state.template.push(...statements); } diff --git a/packages/svelte/src/internal/server/renderer.js b/packages/svelte/src/internal/server/renderer.js index d20792c91f..fa7b0116d2 100644 --- a/packages/svelte/src/internal/server/renderer.js +++ b/packages/svelte/src/internal/server/renderer.js @@ -104,10 +104,27 @@ export class Renderer { * @param {(renderer: Renderer) => void} fn */ async(blockers, fn) { + let callback = fn; + + if (blockers.length > 0) { + const context = ssr_context; + + callback = (renderer) => { + return Promise.all(blockers).then(() => { + const previous_context = ssr_context; + + try { + set_ssr_context(context); + return fn(renderer); + } finally { + set_ssr_context(previous_context); + } + }); + }; + } + this.#out.push(BLOCK_OPEN); - this.child( - blockers.length > 0 ? (renderer) => Promise.all(blockers).then(() => fn(renderer)) : fn - ); + this.child(callback); this.#out.push(BLOCK_CLOSE); } @@ -122,13 +139,13 @@ export class Renderer { for (const fn of thunks.slice(1)) { promise = promise.then(() => { - const previous_ssr_context = ssr_context; + const previous_context = ssr_context; set_ssr_context(context); try { return fn(); } finally { - set_ssr_context(previous_ssr_context); + set_ssr_context(previous_context); } }); }