Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: static template expression evaluation #15374

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
5 changes: 5 additions & 0 deletions .changeset/calm-beds-decide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

feat: static template expression evaluation
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { is_event_attribute } from '../../../../../utils/ast.js';
import * as b from '../../../../../utils/builders.js';
import { build_class_directives_object, build_style_directives_object } from '../RegularElement.js';
import { build_template_chunk, get_expression_id } from './utils.js';
import { evaluate_static_expression, DYNAMIC } from '../../../shared/static-evaluation.js';

/**
* @param {Array<AST.Attribute | AST.SpreadAttribute>} attributes
Expand Down Expand Up @@ -131,7 +132,10 @@ export function build_attribute_value(value, context, memoize = (value) => value
}

let expression = /** @type {Expression} */ (context.visit(chunk.expression));

let evaluated = evaluate_static_expression(expression, context.state);
if (evaluated !== DYNAMIC) {
return { value: b.literal(evaluated), has_state: false };
}
return {
value: memoize(expression, chunk.metadata.expression),
has_state: chunk.metadata.expression.has_state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { regex_is_valid_identifier } from '../../../../patterns.js';
import is_reference from 'is-reference';
import { locator } from '../../../../../state.js';
import { create_derived } from '../../utils.js';
import { evaluate_static_expression, DYNAMIC } from '../../../shared/static-evaluation.js';

/**
* @param {ComponentClientTransformState} state
Expand Down Expand Up @@ -64,6 +65,13 @@ export function build_template_chunk(
node.expression.name !== 'undefined' ||
state.scope.get('undefined')
) {
let evaluated = evaluate_static_expression(node.expression, state);
if (evaluated !== DYNAMIC) {
if (evaluated != null) {
quasi.value.cooked += evaluated + '';
}
continue;
}
let value = memoize(
/** @type {Expression} */ (visit(node.expression, state)),
node.metadata.expression
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import * as b from '../../../../../utils/builders.js';
import { sanitize_template_string } from '../../../../../utils/sanitize_template_string.js';
import { regex_whitespaces_strict } from '../../../../patterns.js';
import { evaluate_static_expression, DYNAMIC } from '../../../shared/static-evaluation.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);
Expand Down Expand Up @@ -49,7 +50,15 @@ export function process_children(nodes, { visit, state }) {
quasi.value.cooked += escape_html(node.expression.value + '');
}
} else {
expressions.push(b.call('$.escape', /** @type {Expression} */ (visit(node.expression))));
let evaluated = evaluate_static_expression(node.expression, state, true);
if (evaluated === DYNAMIC) {
expressions.push(b.call('$.escape', /** @type {Expression} */ (visit(node.expression))));
} else {
if (evaluated != null) {
quasi.value.cooked += escape_html(evaluated + '');
}
continue;
}

quasi = b.quasi('', i + 1 === sequence.length);
quasis.push(quasi);
Expand Down
Loading