From d178106a73c42f28a1eee2e9424c62fdd8430535 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Fri, 24 Oct 2025 09:25:03 -0400 Subject: [PATCH] fix: better optimization of await expressions --- .changeset/odd-plants-lead.md | 5 +++++ .../svelte/src/compiler/phases/2-analyze/index.js | 2 +- .../3-transform/server/visitors/shared/utils.js | 4 ++-- packages/svelte/src/compiler/utils/ast.js | 12 ++++++++---- packages/svelte/src/compiler/utils/builders.js | 4 ++-- 5 files changed, 18 insertions(+), 9 deletions(-) create mode 100644 .changeset/odd-plants-lead.md diff --git a/.changeset/odd-plants-lead.md b/.changeset/odd-plants-lead.md new file mode 100644 index 000000000000..1df2236c2a4b --- /dev/null +++ b/.changeset/odd-plants-lead.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: better optimization of await expressions diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index 52be9973748e..b4c704c34d81 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -6,7 +6,7 @@ import { walk } from 'zimmerframe'; import { parse } from '../1-parse/acorn.js'; import * as e from '../../errors.js'; import * as w from '../../warnings.js'; -import { extract_identifiers } from '../../utils/ast.js'; +import { extract_identifiers, has_await_expression } from '../../utils/ast.js'; import * as b from '#compiler/builders'; import { Scope, ScopeRoot, create_scopes, get_rune, set_scope } from '../scope.js'; import check_graph_for_cycles from './utils/check_graph_for_cycles.js'; diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js index f5132c1cf81d..92653ed73c90 100644 --- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/utils.js @@ -12,7 +12,7 @@ import { import * as b from '#compiler/builders'; import { sanitize_template_string } from '../../../../../utils/sanitize_template_string.js'; import { regex_whitespaces_strict } from '../../../../patterns.js'; -import { has_await } from '../../../../../utils/ast.js'; +import { has_await_expression } from '../../../../../utils/ast.js'; /** Opens an if/each block, so that we can remove nodes in the case of a mismatch */ export const block_open = b.literal(BLOCK_OPEN); @@ -315,7 +315,7 @@ export class PromiseOptimiser { const promises = b.array( this.expressions.map((expression) => { - return expression.type === 'AwaitExpression' && !has_await(expression.argument) + return expression.type === 'AwaitExpression' && !has_await_expression(expression.argument) ? expression.argument : b.call(b.thunk(expression, true)); }) diff --git a/packages/svelte/src/compiler/utils/ast.js b/packages/svelte/src/compiler/utils/ast.js index 541921befbce..bd92dda5d968 100644 --- a/packages/svelte/src/compiler/utils/ast.js +++ b/packages/svelte/src/compiler/utils/ast.js @@ -611,16 +611,20 @@ export function build_assignment_value(operator, left, right) { } /** - * @param {ESTree.Expression} expression + * @param {ESTree.Node} node */ -export function has_await(expression) { +export function has_await_expression(node) { let has_await = false; - walk(expression, null, { + walk(node, null, { AwaitExpression(_node, context) { has_await = true; context.stop(); - } + }, + // don't traverse into these + FunctionDeclaration() {}, + FunctionExpression() {}, + ArrowFunctionExpression() {} }); return has_await; diff --git a/packages/svelte/src/compiler/utils/builders.js b/packages/svelte/src/compiler/utils/builders.js index 99306ce4d966..f21b0dc8b43f 100644 --- a/packages/svelte/src/compiler/utils/builders.js +++ b/packages/svelte/src/compiler/utils/builders.js @@ -2,7 +2,7 @@ import { walk } from 'zimmerframe'; import { regex_is_valid_identifier } from '../phases/patterns.js'; import { sanitize_template_string } from './sanitize_template_string.js'; -import { has_await } from './ast.js'; +import { has_await_expression } from './ast.js'; /** * @param {Array} elements @@ -451,7 +451,7 @@ export function thunk(expression, async = false) { export function unthunk(expression) { // optimize `async () => await x()`, but not `async () => await x(await y)` if (expression.async && expression.body.type === 'AwaitExpression') { - if (!has_await(expression.body.argument)) { + if (!has_await_expression(expression.body.argument)) { return unthunk(arrow(expression.params, expression.body.argument)); } }