1- /** @import { Expression, ExpressionStatement, Identifier, MemberExpression, SequenceExpression, Statement, Super, Node, UnaryExpression, TemplateLiteral, BinaryExpression, LogicalExpression, ConditionalExpression } from 'estree' */
1+ /** @import { Expression, ExpressionStatement, Identifier, MemberExpression, SequenceExpression, Statement, Super } from 'estree' */
22/** @import { AST, ExpressionMetadata } from '#compiler' */
33/** @import { ComponentClientTransformState } from '../../types' */
44import { walk } from 'zimmerframe' ;
@@ -9,6 +9,7 @@ import { regex_is_valid_identifier } from '../../../../patterns.js';
99import is_reference from 'is-reference' ;
1010import { locator } from '../../../../../state.js' ;
1111import { create_derived } from '../../utils.js' ;
12+ import { evaluate_static_expression , DYNAMIC } from '../../../shared/static-evaluation.js' ;
1213
1314/**
1415 * @param {ComponentClientTransformState } state
@@ -74,201 +75,6 @@ function compare_expressions(a, b) {
7475
7576 return true ;
7677}
77- export const DYNAMIC = Symbol ( 'DYNAMIC' ) ;
78-
79- /**
80- * @param {Node } node
81- * @param {ComponentClientTransformState } state
82- * @returns {any }
83- */
84- export function evaluate_static_expression ( node , state ) {
85- if ( node == undefined ) return DYNAMIC ;
86- /**
87- * @param {BinaryExpression | LogicalExpression } node
88- */
89- function handle_left_right ( node ) {
90- const left = evaluate_static_expression ( node ?. left , state ) ;
91- const right = evaluate_static_expression ( node ?. right , state ) ;
92- if ( left === DYNAMIC || right === DYNAMIC ) {
93- return DYNAMIC ;
94- }
95- switch ( node . operator ) {
96- case '+' :
97- return left + right ;
98- case '-' :
99- return left - right ;
100- case '&' :
101- return left & right ;
102- case '|' :
103- return left | right ;
104- case '<<' :
105- return left << right ;
106- case '>>' :
107- return left >> right ;
108- case '>' :
109- return left > right ;
110- case '<' :
111- return left < right ;
112- case '>=' :
113- return left >= right ;
114- case '<=' :
115- return left <= right ;
116- case '==' :
117- return left == right ;
118- case '===' :
119- return left === right ;
120- case '||' :
121- return left || right ;
122- case '??' :
123- return left ?? right ;
124- case '&&' :
125- return left && right ;
126- case '%' :
127- return left % right ;
128- case '>>>' :
129- return left >>> right ;
130- case '^' :
131- return left ^ right ;
132- case '**' :
133- return left ** right ;
134- case '*' :
135- return left * right ;
136- case '/' :
137- return left / right ;
138- case '!=' :
139- return left != right ;
140- case '!==' :
141- return left !== right ;
142- default :
143- return DYNAMIC ;
144- }
145- }
146- /**
147- * @param {UnaryExpression } node
148- */
149- function handle_unary ( node ) {
150- const argument = evaluate_static_expression ( node ?. argument , state ) ;
151- if ( argument === DYNAMIC ) return DYNAMIC ;
152- /**
153- * @param {Expression } argument
154- */
155- function handle_void ( argument ) {
156- //@ts -ignore
157- const evaluated = evaluate_static_expression ( argument ) ;
158- if ( evaluated !== DYNAMIC ) {
159- return undefined ;
160- }
161- return DYNAMIC ;
162- }
163- switch ( node . operator ) {
164- case '!' :
165- return ! argument ;
166- case '-' :
167- return - argument ;
168- case 'typeof' :
169- return typeof argument ;
170- case '~' :
171- return ~ argument ;
172- case '+' :
173- return + argument ;
174- case 'void' :
175- return handle_void ( argument ) ;
176- default :
177- // `delete` is ignored, since it may have side effects
178- return DYNAMIC ;
179- }
180- }
181- /**
182- * @param {SequenceExpression } node
183- */
184- function handle_sequence ( node ) {
185- const is_static = node . expressions . reduce (
186- ( a , b ) => a && evaluate_static_expression ( b , state ) !== DYNAMIC ,
187- true
188- ) ;
189- if ( is_static ) {
190- //@ts -ignore
191- return evaluate_static_expression ( node . expressions . at ( - 1 ) , state ) ;
192- }
193- return DYNAMIC ;
194- }
195- /**
196- * @param {string } name
197- */
198- function handle_ident ( name ) {
199- const scope = state . scope . get ( name ) ;
200- if ( scope ?. kind === 'normal' && scope ?. declaration_kind !== 'import' ) {
201- if ( scope . initial && ! scope . mutated && ! scope . reassigned && ! scope . updated ) {
202- //@ts -ignore
203- let evaluated = evaluate_static_expression ( scope . initial , state ) ;
204- return evaluated ;
205- }
206- }
207- return DYNAMIC ;
208- }
209- /**
210- * @param {TemplateLiteral } node
211- */
212- function handle_template ( node ) {
213- const expressions = node . expressions ;
214- const quasis = node . quasis ;
215- const is_static = expressions . reduce (
216- ( a , b ) => a && evaluate_static_expression ( b , state ) !== DYNAMIC ,
217- true
218- ) ;
219- if ( is_static ) {
220- let res = '' ;
221- let last_was_quasi = false ;
222- let expr_index = 0 ;
223- let quasi_index = 0 ;
224- for ( let index = 0 ; index < quasis . length + expressions . length ; index ++ ) {
225- if ( last_was_quasi ) {
226- res += evaluate_static_expression ( expressions [ expr_index ++ ] , state ) ;
227- last_was_quasi = false ;
228- } else {
229- res += quasis [ quasi_index ++ ] . value . cooked ;
230- last_was_quasi = true ;
231- }
232- }
233- return res ;
234- }
235- return DYNAMIC ;
236- }
237- /**
238- * @param {ConditionalExpression } node
239- */
240- function handle_ternary ( node ) {
241- const test = evaluate_static_expression ( node . test , state ) ;
242- if ( test !== DYNAMIC ) {
243- if ( test ) {
244- return evaluate_static_expression ( node . consequent , state ) ;
245- } else {
246- return evaluate_static_expression ( node . alternate , state ) ;
247- }
248- }
249- return DYNAMIC ;
250- }
251- switch ( node . type ) {
252- case 'Literal' :
253- return node . value ;
254- case 'BinaryExpression' :
255- return handle_left_right ( node ) ;
256- case 'LogicalExpression' :
257- return handle_left_right ( node ) ;
258- case 'UnaryExpression' :
259- return handle_unary ( node ) ;
260- case 'Identifier' :
261- return handle_ident ( node . name ) ;
262- case 'SequenceExpression' :
263- return handle_sequence ( node ) ;
264- case 'TemplateLiteral' :
265- return handle_template ( node ) ;
266- case 'ConditionalExpression' :
267- return handle_ternary ( node ) ;
268- default :
269- return DYNAMIC ;
270- }
271- }
27278
27379/**
27480 * @param {Array<AST.Text | AST.ExpressionTag> } values
0 commit comments