fix: better optimization of await expressions (#17025)

pull/17019/head
Rich Harris 2 weeks ago committed by GitHub
parent 2e1dd489f6
commit f45d9cfe2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: better optimization of await expressions

@ -6,7 +6,7 @@ import { walk } from 'zimmerframe';
import { parse } from '../1-parse/acorn.js'; import { parse } from '../1-parse/acorn.js';
import * as e from '../../errors.js'; import * as e from '../../errors.js';
import * as w from '../../warnings.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 * as b from '#compiler/builders';
import { Scope, ScopeRoot, create_scopes, get_rune, set_scope } from '../scope.js'; import { Scope, ScopeRoot, create_scopes, get_rune, set_scope } from '../scope.js';
import check_graph_for_cycles from './utils/check_graph_for_cycles.js'; import check_graph_for_cycles from './utils/check_graph_for_cycles.js';

@ -12,7 +12,7 @@ import {
import * as b from '#compiler/builders'; import * as b from '#compiler/builders';
import { sanitize_template_string } from '../../../../../utils/sanitize_template_string.js'; import { sanitize_template_string } from '../../../../../utils/sanitize_template_string.js';
import { regex_whitespaces_strict } from '../../../../patterns.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 */ /** 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); export const block_open = b.literal(BLOCK_OPEN);
@ -315,7 +315,7 @@ export class PromiseOptimiser {
const promises = b.array( const promises = b.array(
this.expressions.map((expression) => { this.expressions.map((expression) => {
return expression.type === 'AwaitExpression' && !has_await(expression.argument) return expression.type === 'AwaitExpression' && !has_await_expression(expression.argument)
? expression.argument ? expression.argument
: b.call(b.thunk(expression, true)); : b.call(b.thunk(expression, true));
}) })

@ -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; let has_await = false;
walk(expression, null, { walk(node, null, {
AwaitExpression(_node, context) { AwaitExpression(_node, context) {
has_await = true; has_await = true;
context.stop(); context.stop();
} },
// don't traverse into these
FunctionDeclaration() {},
FunctionExpression() {},
ArrowFunctionExpression() {}
}); });
return has_await; return has_await;

@ -2,7 +2,7 @@
import { walk } from 'zimmerframe'; import { walk } from 'zimmerframe';
import { regex_is_valid_identifier } from '../phases/patterns.js'; import { regex_is_valid_identifier } from '../phases/patterns.js';
import { sanitize_template_string } from './sanitize_template_string.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<ESTree.Expression | ESTree.SpreadElement | null>} elements * @param {Array<ESTree.Expression | ESTree.SpreadElement | null>} elements
@ -451,7 +451,7 @@ export function thunk(expression, async = false) {
export function unthunk(expression) { export function unthunk(expression) {
// optimize `async () => await x()`, but not `async () => await x(await y)` // optimize `async () => await x()`, but not `async () => await x(await y)`
if (expression.async && expression.body.type === 'AwaitExpression') { 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)); return unthunk(arrow(expression.params, expression.body.argument));
} }
} }

Loading…
Cancel
Save