From 82cb5156c79f8648f0474fba8c29a6c40ea4a6ea Mon Sep 17 00:00:00 2001 From: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com> Date: Sat, 30 Aug 2025 17:21:08 -0700 Subject: [PATCH] parallelize `await` expressions in instance --- .../phases/3-transform/client/types.d.ts | 4 +- .../client/visitors/ExpressionStatement.js | 40 ++++++++++++++++++- .../3-transform/client/visitors/Program.js | 26 +++++++----- .../client/visitors/VariableDeclaration.js | 9 ++++- 4 files changed, 64 insertions(+), 15 deletions(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/types.d.ts b/packages/svelte/src/compiler/phases/3-transform/client/types.d.ts index 9a569f3a9f..46c922aa33 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/types.d.ts +++ b/packages/svelte/src/compiler/phases/3-transform/client/types.d.ts @@ -90,10 +90,10 @@ export interface ComponentClientTransformState extends ClientTransformState { export interface ParallelizedChunk { declarators: Array<{ - id: Pattern; + id: Pattern | null; init: Expression; }>; - kind: VariableDeclaration['kind']; + kind: VariableDeclaration['kind'] | null; /** index in instance body */ position: number; bindings: Binding[]; diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ExpressionStatement.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ExpressionStatement.js index 859842ebc3..75c003c0ad 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ExpressionStatement.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ExpressionStatement.js @@ -1,13 +1,16 @@ -/** @import { Expression, ExpressionStatement } from 'estree' */ -/** @import { ComponentContext } from '../types' */ +/** @import { Expression, ExpressionStatement, Node, Program } from 'estree' */ +/** @import { ComponentContext, ParallelizedChunk } from '../types' */ import * as b from '#compiler/builders'; import { get_rune } from '../../../scope.js'; +import { can_be_parallelized } from '../utils.js'; /** * @param {ExpressionStatement} node * @param {ComponentContext} context */ export function ExpressionStatement(node, context) { + const parent = /** @type {Node} */ (context.path.at(-1)); + const position = /** @type {Program} */ (parent).body?.indexOf?.(node); if (node.expression.type === 'CallExpression') { const rune = get_rune(node.expression, context.state.scope); @@ -25,6 +28,39 @@ export function ExpressionStatement(node, context) { return b.empty; } } + if ( + node.expression.type === 'AwaitExpression' && + context.state.analysis.instance?.scope === context.state.scope + ) { + const current_chunk = context.state.current_parallelized_chunk; + const parallelize = can_be_parallelized( + node.expression.argument, + context.state.scope, + context.state.analysis, + current_chunk?.bindings ?? [] + ); + if (parallelize) { + const declarator = { + id: null, + init: /** @type {Expression} */ (context.visit(node.expression)) + }; + if (current_chunk) { + current_chunk.declarators.push(declarator); + current_chunk.position = position; + } else { + /** @type {ParallelizedChunk} */ + const chunk = { + kind: null, + declarators: [declarator], + position, + bindings: [] + }; + context.state.current_parallelized_chunk = chunk; + context.state.parallelized_chunks.push(chunk); + } + return; + } + } context.next(); } diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js index b3f86c01d2..3336389686 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/Program.js @@ -148,20 +148,28 @@ export function Program(node, context) { for (const chunk of context.state.parallelized_chunks) { if (chunk.declarators.length === 1) { const declarator = chunk.declarators[0]; - body.splice( - chunk.position + offset, - 0, - b.declaration(chunk.kind, [ - b.declarator(declarator.id, b.call(b.await(b.call('$.save', declarator.init)))) - ]) - ); + if (declarator.id === null || chunk.kind === null) { + body.splice( + chunk.position + offset, + 0, + b.stmt(b.call(b.await(b.call('$.save', declarator.init)))) + ); + } else { + body.splice( + chunk.position + offset, + 0, + b.declaration(chunk.kind, [ + b.declarator(declarator.id, b.call(b.await(b.call('$.save', declarator.init)))) + ]) + ); + } } else { const pattern = b.array_pattern(chunk.declarators.map(({ id }) => id)); - const init = b.call(`$.all`, ...chunk.declarators.map(({ init }) => init)); + const init = b.call('$.all', ...chunk.declarators.map(({ init }) => init)); body.splice( chunk.position + offset, 0, - b.declaration(chunk.kind, [b.declarator(pattern, b.await(init))]) + b.declaration(chunk.kind ?? 'const', [b.declarator(pattern, b.await(init))]) ); } offset++; 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 ad9f6993d9..10a8c2f8fd 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 @@ -69,10 +69,14 @@ export function VariableDeclaration(node, context) { id, init: /** @type {Expression} */ (visited_init) }; - if (current_chunk && current_chunk.kind === node.kind) { + if ( + current_chunk && + (current_chunk.kind === node.kind || current_chunk.kind === null) + ) { current_chunk.declarators.push(_declarator); current_chunk.bindings.push(...bindings); current_chunk.position = /** @type {Program} */ (parent).body.indexOf(node); + current_chunk.kind = node.kind; } else { /** @type {ParallelizedChunk} */ const chunk = { @@ -370,10 +374,11 @@ export function VariableDeclaration(node, context) { id, init: /** @type {Expression} */ (init) })); - if (current_chunk && current_chunk.kind === node.kind) { + if (current_chunk && (current_chunk.kind === node.kind || current_chunk.kind === null)) { current_chunk.declarators.push(...declarators); current_chunk.bindings.push(...bindings); current_chunk.position = position; + current_chunk.kind = node.kind; } else { /** @type {ParallelizedChunk} */ const chunk = {