|
|
|
@ -1,5 +1,5 @@
|
|
|
|
|
/** @import { AssignmentOperator, Expression, Identifier, Node, Statement, BlockStatement } from 'estree' */
|
|
|
|
|
/** @import { AST } from '#compiler' */
|
|
|
|
|
/** @import { AST, ExpressionMetadata } from '#compiler' */
|
|
|
|
|
/** @import { ComponentContext, ServerTransformState } from '../../types.js' */
|
|
|
|
|
|
|
|
|
|
import { escape_html } from '../../../../../../escaping.js';
|
|
|
|
@ -11,6 +11,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';
|
|
|
|
|
|
|
|
|
|
/** 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);
|
|
|
|
@ -183,13 +184,15 @@ export function build_template(template, out = b.id('$$payload'), operator = 'pu
|
|
|
|
|
* @param {ComponentContext} context
|
|
|
|
|
* @param {boolean} trim_whitespace
|
|
|
|
|
* @param {boolean} is_component
|
|
|
|
|
* @param {(expression: Expression, metadata: ExpressionMetadata) => Expression} transform
|
|
|
|
|
* @returns {Expression}
|
|
|
|
|
*/
|
|
|
|
|
export function build_attribute_value(
|
|
|
|
|
value,
|
|
|
|
|
context,
|
|
|
|
|
trim_whitespace = false,
|
|
|
|
|
is_component = false
|
|
|
|
|
is_component = false,
|
|
|
|
|
transform = (expression) => expression
|
|
|
|
|
) {
|
|
|
|
|
if (value === true) {
|
|
|
|
|
return b.true;
|
|
|
|
@ -206,7 +209,10 @@ export function build_attribute_value(
|
|
|
|
|
return b.literal(is_component ? data : escape_html(data, true));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return /** @type {Expression} */ (context.visit(chunk.expression));
|
|
|
|
|
return transform(
|
|
|
|
|
/** @type {Expression} */ (context.visit(chunk.expression)),
|
|
|
|
|
chunk.metadata.expression
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let quasi = b.quasi('', false);
|
|
|
|
@ -224,7 +230,13 @@ export function build_attribute_value(
|
|
|
|
|
: node.data;
|
|
|
|
|
} else {
|
|
|
|
|
expressions.push(
|
|
|
|
|
b.call('$.stringify', /** @type {Expression} */ (context.visit(node.expression)))
|
|
|
|
|
b.call(
|
|
|
|
|
'$.stringify',
|
|
|
|
|
transform(
|
|
|
|
|
/** @type {Expression} */ (context.visit(node.expression)),
|
|
|
|
|
node.metadata.expression
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
quasi = b.quasi('', i + 1 === value.length);
|
|
|
|
@ -269,3 +281,41 @@ export function build_getter(node, state) {
|
|
|
|
|
export function call_child_payload(body, async) {
|
|
|
|
|
return b.stmt(b.call('$$payload.child', b.arrow([b.id('$$payload')], body, async)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class PromiseOptimiser {
|
|
|
|
|
/** @type {Expression[]} */
|
|
|
|
|
expressions = [];
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param {Expression} expression
|
|
|
|
|
* @param {ExpressionMetadata} metadata
|
|
|
|
|
*/
|
|
|
|
|
transform = (expression, metadata) => {
|
|
|
|
|
if (metadata.has_await) {
|
|
|
|
|
const length = this.expressions.push(expression);
|
|
|
|
|
return b.id(`$$${length - 1}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return expression;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
apply() {
|
|
|
|
|
if (this.expressions.length === 1) {
|
|
|
|
|
return b.const('$$0', this.expressions[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const promises = b.array(
|
|
|
|
|
this.expressions.map((expression) => {
|
|
|
|
|
return expression.type === 'AwaitExpression' && !has_await(expression.argument)
|
|
|
|
|
? expression.argument
|
|
|
|
|
: b.call(b.thunk(expression, true));
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return b.const(
|
|
|
|
|
b.array_pattern(this.expressions.map((_, i) => b.id(`$$${i}`))),
|
|
|
|
|
b.await(b.call('Promise.all', promises))
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|