jslike 1.6.2 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/interpreter/index.js +2 -1
- package/dist/esm/interpreter/interpreter.js +124 -2
- package/dist/index.cjs +95 -3
- package/dist/index.d.cts +126 -3
- package/dist/index.d.ts +126 -3
- package/dist/index.js +95 -3
- package/package.json +1 -1
|
@@ -102,7 +102,8 @@ export class WangInterpreter {
|
|
|
102
102
|
// Prepare execution options
|
|
103
103
|
const options = {
|
|
104
104
|
moduleResolver: this.moduleResolver,
|
|
105
|
-
executionController: userOptions.executionController
|
|
105
|
+
executionController: userOptions.executionController,
|
|
106
|
+
abortSignal: userOptions.abortSignal // Pass abort signal to interpreter for cancellation support
|
|
106
107
|
// sourceType will be auto-detected from code
|
|
107
108
|
};
|
|
108
109
|
|
|
@@ -158,10 +158,11 @@ export class Interpreter {
|
|
|
158
158
|
return undefined;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
const
|
|
161
|
+
const rawArgs = [];
|
|
162
162
|
for (const arg of node.arguments) {
|
|
163
|
-
|
|
163
|
+
rawArgs.push(await this.evaluateAsync(arg, env));
|
|
164
164
|
}
|
|
165
|
+
const args = this.flattenSpreadArgs(rawArgs);
|
|
165
166
|
|
|
166
167
|
if (typeof callee === 'function') {
|
|
167
168
|
if (thisContext !== undefined) {
|
|
@@ -218,6 +219,56 @@ export class Interpreter {
|
|
|
218
219
|
return result;
|
|
219
220
|
}
|
|
220
221
|
|
|
222
|
+
if (node.type === 'TaggedTemplateExpression') {
|
|
223
|
+
// 1. Evaluate tag function async (may contain awaits)
|
|
224
|
+
let thisContext = undefined;
|
|
225
|
+
let tagFunction;
|
|
226
|
+
|
|
227
|
+
if (node.tag.type === 'MemberExpression') {
|
|
228
|
+
thisContext = await this.evaluateAsync(node.tag.object, env);
|
|
229
|
+
const prop = node.tag.computed
|
|
230
|
+
? await this.evaluateAsync(node.tag.property, env)
|
|
231
|
+
: node.tag.property.name;
|
|
232
|
+
tagFunction = thisContext[prop];
|
|
233
|
+
} else {
|
|
234
|
+
tagFunction = await this.evaluateAsync(node.tag, env);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// 2. Build strings array (synchronous - no awaits in quasis)
|
|
238
|
+
const strings = [];
|
|
239
|
+
const rawStrings = [];
|
|
240
|
+
for (const quasi of node.quasi.quasis) {
|
|
241
|
+
strings.push(quasi.value.cooked || quasi.value.raw);
|
|
242
|
+
rawStrings.push(quasi.value.raw);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
Object.defineProperty(strings, 'raw', {
|
|
246
|
+
value: Object.freeze(rawStrings),
|
|
247
|
+
writable: false,
|
|
248
|
+
enumerable: false,
|
|
249
|
+
configurable: false
|
|
250
|
+
});
|
|
251
|
+
Object.freeze(strings);
|
|
252
|
+
|
|
253
|
+
// 3. Evaluate expressions async (may contain awaits)
|
|
254
|
+
const values = [];
|
|
255
|
+
for (const expr of node.quasi.expressions) {
|
|
256
|
+
values.push(await this.evaluateAsync(expr, env));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// 4. Call tag function (may be async)
|
|
260
|
+
if (typeof tagFunction === 'function') {
|
|
261
|
+
if (thisContext !== undefined) {
|
|
262
|
+
return await tagFunction.call(thisContext, strings, ...values);
|
|
263
|
+
}
|
|
264
|
+
return await tagFunction(strings, ...values);
|
|
265
|
+
} else if (tagFunction && tagFunction.__isFunction) {
|
|
266
|
+
return await this.callUserFunction(tagFunction, [strings, ...values], env, thisContext);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
throw new TypeError('Tag must be a function');
|
|
270
|
+
}
|
|
271
|
+
|
|
221
272
|
// For logical expressions with async operands (await support)
|
|
222
273
|
if (node.type === 'LogicalExpression') {
|
|
223
274
|
const left = await this.evaluateAsync(node.left, env);
|
|
@@ -656,6 +707,24 @@ export class Interpreter {
|
|
|
656
707
|
return this.normalizeJSXText(node.value);
|
|
657
708
|
}
|
|
658
709
|
|
|
710
|
+
// For SpreadElement - return spread marker for flattenSpreadArgs
|
|
711
|
+
if (node.type === 'SpreadElement') {
|
|
712
|
+
const arg = await this.evaluateAsync(node.argument, env);
|
|
713
|
+
if (Array.isArray(arg)) {
|
|
714
|
+
return { __spread: true, __values: arg };
|
|
715
|
+
}
|
|
716
|
+
if (typeof arg === 'string') {
|
|
717
|
+
return { __spread: true, __values: [...arg] };
|
|
718
|
+
}
|
|
719
|
+
if (arg !== null && arg !== undefined && typeof arg[Symbol.iterator] === 'function') {
|
|
720
|
+
return { __spread: true, __values: [...arg] };
|
|
721
|
+
}
|
|
722
|
+
if (typeof arg === 'object' && arg !== null) {
|
|
723
|
+
return { __spread: true, __values: Object.entries(arg) };
|
|
724
|
+
}
|
|
725
|
+
throw new TypeError('Spread syntax requires an iterable');
|
|
726
|
+
}
|
|
727
|
+
|
|
659
728
|
// Only leaf nodes should fall through to sync evaluate
|
|
660
729
|
// These have no sub-expressions that could contain await
|
|
661
730
|
if (['Literal', 'Identifier', 'BreakStatement', 'ContinueStatement',
|
|
@@ -803,6 +872,9 @@ export class Interpreter {
|
|
|
803
872
|
case 'TemplateLiteral':
|
|
804
873
|
return this.evaluateTemplateLiteral(node, env);
|
|
805
874
|
|
|
875
|
+
case 'TaggedTemplateExpression':
|
|
876
|
+
return this.evaluateTaggedTemplateExpression(node, env);
|
|
877
|
+
|
|
806
878
|
case 'ClassDeclaration':
|
|
807
879
|
return this.evaluateClassDeclaration(node, env);
|
|
808
880
|
|
|
@@ -2047,6 +2119,56 @@ export class Interpreter {
|
|
|
2047
2119
|
return result;
|
|
2048
2120
|
}
|
|
2049
2121
|
|
|
2122
|
+
evaluateTaggedTemplateExpression(node, env) {
|
|
2123
|
+
// 1. Evaluate the tag function, preserving 'this' context for member expressions
|
|
2124
|
+
let thisContext = undefined;
|
|
2125
|
+
let tagFunction;
|
|
2126
|
+
|
|
2127
|
+
if (node.tag.type === 'MemberExpression') {
|
|
2128
|
+
// For method calls like obj.tag`...`, set this to obj
|
|
2129
|
+
thisContext = this.evaluate(node.tag.object, env);
|
|
2130
|
+
const prop = node.tag.computed
|
|
2131
|
+
? this.evaluate(node.tag.property, env)
|
|
2132
|
+
: node.tag.property.name;
|
|
2133
|
+
tagFunction = thisContext[prop];
|
|
2134
|
+
} else {
|
|
2135
|
+
tagFunction = this.evaluate(node.tag, env);
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
// 2. Build the strings array from quasis (cooked values)
|
|
2139
|
+
const strings = [];
|
|
2140
|
+
const rawStrings = [];
|
|
2141
|
+
for (const quasi of node.quasi.quasis) {
|
|
2142
|
+
strings.push(quasi.value.cooked || quasi.value.raw);
|
|
2143
|
+
rawStrings.push(quasi.value.raw);
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
// 3. Add the raw property (frozen per ES6 spec)
|
|
2147
|
+
Object.defineProperty(strings, 'raw', {
|
|
2148
|
+
value: Object.freeze(rawStrings),
|
|
2149
|
+
writable: false,
|
|
2150
|
+
enumerable: false,
|
|
2151
|
+
configurable: false
|
|
2152
|
+
});
|
|
2153
|
+
Object.freeze(strings);
|
|
2154
|
+
|
|
2155
|
+
// 4. Evaluate the embedded expressions
|
|
2156
|
+
const values = node.quasi.expressions.map(expr => this.evaluate(expr, env));
|
|
2157
|
+
|
|
2158
|
+
// 5. Call the tag function with proper this context
|
|
2159
|
+
if (typeof tagFunction === 'function') {
|
|
2160
|
+
if (thisContext !== undefined) {
|
|
2161
|
+
return tagFunction.call(thisContext, strings, ...values);
|
|
2162
|
+
}
|
|
2163
|
+
return tagFunction(strings, ...values);
|
|
2164
|
+
} else if (tagFunction && tagFunction.__isFunction) {
|
|
2165
|
+
// User-defined function
|
|
2166
|
+
return this.callUserFunction(tagFunction, [strings, ...values], env, thisContext);
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
throw new TypeError('Tag must be a function');
|
|
2170
|
+
}
|
|
2171
|
+
|
|
2050
2172
|
evaluateClassDeclaration(node, env) {
|
|
2051
2173
|
const className = node.id.name;
|
|
2052
2174
|
const classFunc = this.createClass(node, env);
|
package/dist/index.cjs
CHANGED
|
@@ -6589,10 +6589,11 @@ var Interpreter = class _Interpreter {
|
|
|
6589
6589
|
if (node.optional && (callee === null || callee === void 0)) {
|
|
6590
6590
|
return void 0;
|
|
6591
6591
|
}
|
|
6592
|
-
const
|
|
6592
|
+
const rawArgs = [];
|
|
6593
6593
|
for (const arg of node.arguments) {
|
|
6594
|
-
|
|
6594
|
+
rawArgs.push(await this.evaluateAsync(arg, env));
|
|
6595
6595
|
}
|
|
6596
|
+
const args = this.flattenSpreadArgs(rawArgs);
|
|
6596
6597
|
if (typeof callee === "function") {
|
|
6597
6598
|
if (thisContext !== void 0) {
|
|
6598
6599
|
return await callee.call(thisContext, ...args);
|
|
@@ -6631,6 +6632,43 @@ var Interpreter = class _Interpreter {
|
|
|
6631
6632
|
}
|
|
6632
6633
|
return result;
|
|
6633
6634
|
}
|
|
6635
|
+
if (node.type === "TaggedTemplateExpression") {
|
|
6636
|
+
let thisContext = void 0;
|
|
6637
|
+
let tagFunction;
|
|
6638
|
+
if (node.tag.type === "MemberExpression") {
|
|
6639
|
+
thisContext = await this.evaluateAsync(node.tag.object, env);
|
|
6640
|
+
const prop = node.tag.computed ? await this.evaluateAsync(node.tag.property, env) : node.tag.property.name;
|
|
6641
|
+
tagFunction = thisContext[prop];
|
|
6642
|
+
} else {
|
|
6643
|
+
tagFunction = await this.evaluateAsync(node.tag, env);
|
|
6644
|
+
}
|
|
6645
|
+
const strings = [];
|
|
6646
|
+
const rawStrings = [];
|
|
6647
|
+
for (const quasi of node.quasi.quasis) {
|
|
6648
|
+
strings.push(quasi.value.cooked || quasi.value.raw);
|
|
6649
|
+
rawStrings.push(quasi.value.raw);
|
|
6650
|
+
}
|
|
6651
|
+
Object.defineProperty(strings, "raw", {
|
|
6652
|
+
value: Object.freeze(rawStrings),
|
|
6653
|
+
writable: false,
|
|
6654
|
+
enumerable: false,
|
|
6655
|
+
configurable: false
|
|
6656
|
+
});
|
|
6657
|
+
Object.freeze(strings);
|
|
6658
|
+
const values = [];
|
|
6659
|
+
for (const expr of node.quasi.expressions) {
|
|
6660
|
+
values.push(await this.evaluateAsync(expr, env));
|
|
6661
|
+
}
|
|
6662
|
+
if (typeof tagFunction === "function") {
|
|
6663
|
+
if (thisContext !== void 0) {
|
|
6664
|
+
return await tagFunction.call(thisContext, strings, ...values);
|
|
6665
|
+
}
|
|
6666
|
+
return await tagFunction(strings, ...values);
|
|
6667
|
+
} else if (tagFunction && tagFunction.__isFunction) {
|
|
6668
|
+
return await this.callUserFunction(tagFunction, [strings, ...values], env, thisContext);
|
|
6669
|
+
}
|
|
6670
|
+
throw new TypeError("Tag must be a function");
|
|
6671
|
+
}
|
|
6634
6672
|
if (node.type === "LogicalExpression") {
|
|
6635
6673
|
const left = await this.evaluateAsync(node.left, env);
|
|
6636
6674
|
if (node.operator === "&&") {
|
|
@@ -6994,6 +7032,22 @@ var Interpreter = class _Interpreter {
|
|
|
6994
7032
|
if (node.type === "JSXText") {
|
|
6995
7033
|
return this.normalizeJSXText(node.value);
|
|
6996
7034
|
}
|
|
7035
|
+
if (node.type === "SpreadElement") {
|
|
7036
|
+
const arg = await this.evaluateAsync(node.argument, env);
|
|
7037
|
+
if (Array.isArray(arg)) {
|
|
7038
|
+
return { __spread: true, __values: arg };
|
|
7039
|
+
}
|
|
7040
|
+
if (typeof arg === "string") {
|
|
7041
|
+
return { __spread: true, __values: [...arg] };
|
|
7042
|
+
}
|
|
7043
|
+
if (arg !== null && arg !== void 0 && typeof arg[Symbol.iterator] === "function") {
|
|
7044
|
+
return { __spread: true, __values: [...arg] };
|
|
7045
|
+
}
|
|
7046
|
+
if (typeof arg === "object" && arg !== null) {
|
|
7047
|
+
return { __spread: true, __values: Object.entries(arg) };
|
|
7048
|
+
}
|
|
7049
|
+
throw new TypeError("Spread syntax requires an iterable");
|
|
7050
|
+
}
|
|
6997
7051
|
if ([
|
|
6998
7052
|
"Literal",
|
|
6999
7053
|
"Identifier",
|
|
@@ -7098,6 +7152,8 @@ var Interpreter = class _Interpreter {
|
|
|
7098
7152
|
// ES6+ Features
|
|
7099
7153
|
case "TemplateLiteral":
|
|
7100
7154
|
return this.evaluateTemplateLiteral(node, env);
|
|
7155
|
+
case "TaggedTemplateExpression":
|
|
7156
|
+
return this.evaluateTaggedTemplateExpression(node, env);
|
|
7101
7157
|
case "ClassDeclaration":
|
|
7102
7158
|
return this.evaluateClassDeclaration(node, env);
|
|
7103
7159
|
case "ClassExpression":
|
|
@@ -8041,6 +8097,40 @@ var Interpreter = class _Interpreter {
|
|
|
8041
8097
|
}
|
|
8042
8098
|
return result;
|
|
8043
8099
|
}
|
|
8100
|
+
evaluateTaggedTemplateExpression(node, env) {
|
|
8101
|
+
let thisContext = void 0;
|
|
8102
|
+
let tagFunction;
|
|
8103
|
+
if (node.tag.type === "MemberExpression") {
|
|
8104
|
+
thisContext = this.evaluate(node.tag.object, env);
|
|
8105
|
+
const prop = node.tag.computed ? this.evaluate(node.tag.property, env) : node.tag.property.name;
|
|
8106
|
+
tagFunction = thisContext[prop];
|
|
8107
|
+
} else {
|
|
8108
|
+
tagFunction = this.evaluate(node.tag, env);
|
|
8109
|
+
}
|
|
8110
|
+
const strings = [];
|
|
8111
|
+
const rawStrings = [];
|
|
8112
|
+
for (const quasi of node.quasi.quasis) {
|
|
8113
|
+
strings.push(quasi.value.cooked || quasi.value.raw);
|
|
8114
|
+
rawStrings.push(quasi.value.raw);
|
|
8115
|
+
}
|
|
8116
|
+
Object.defineProperty(strings, "raw", {
|
|
8117
|
+
value: Object.freeze(rawStrings),
|
|
8118
|
+
writable: false,
|
|
8119
|
+
enumerable: false,
|
|
8120
|
+
configurable: false
|
|
8121
|
+
});
|
|
8122
|
+
Object.freeze(strings);
|
|
8123
|
+
const values = node.quasi.expressions.map((expr) => this.evaluate(expr, env));
|
|
8124
|
+
if (typeof tagFunction === "function") {
|
|
8125
|
+
if (thisContext !== void 0) {
|
|
8126
|
+
return tagFunction.call(thisContext, strings, ...values);
|
|
8127
|
+
}
|
|
8128
|
+
return tagFunction(strings, ...values);
|
|
8129
|
+
} else if (tagFunction && tagFunction.__isFunction) {
|
|
8130
|
+
return this.callUserFunction(tagFunction, [strings, ...values], env, thisContext);
|
|
8131
|
+
}
|
|
8132
|
+
throw new TypeError("Tag must be a function");
|
|
8133
|
+
}
|
|
8044
8134
|
evaluateClassDeclaration(node, env) {
|
|
8045
8135
|
const className = node.id.name;
|
|
8046
8136
|
const classFunc = this.createClass(node, env);
|
|
@@ -8885,7 +8975,9 @@ var WangInterpreter = class {
|
|
|
8885
8975
|
const hasTopLevelReturn = this.hasTopLevelReturn(code);
|
|
8886
8976
|
const options = {
|
|
8887
8977
|
moduleResolver: this.moduleResolver,
|
|
8888
|
-
executionController: userOptions.executionController
|
|
8978
|
+
executionController: userOptions.executionController,
|
|
8979
|
+
abortSignal: userOptions.abortSignal
|
|
8980
|
+
// Pass abort signal to interpreter for cancellation support
|
|
8889
8981
|
// sourceType will be auto-detected from code
|
|
8890
8982
|
};
|
|
8891
8983
|
let result;
|
package/dist/index.d.cts
CHANGED
|
@@ -7323,10 +7323,11 @@ class Interpreter {
|
|
|
7323
7323
|
return undefined;
|
|
7324
7324
|
}
|
|
7325
7325
|
|
|
7326
|
-
const
|
|
7326
|
+
const rawArgs = [];
|
|
7327
7327
|
for (const arg of node.arguments) {
|
|
7328
|
-
|
|
7328
|
+
rawArgs.push(await this.evaluateAsync(arg, env));
|
|
7329
7329
|
}
|
|
7330
|
+
const args = this.flattenSpreadArgs(rawArgs);
|
|
7330
7331
|
|
|
7331
7332
|
if (typeof callee === 'function') {
|
|
7332
7333
|
if (thisContext !== undefined) {
|
|
@@ -7383,6 +7384,56 @@ class Interpreter {
|
|
|
7383
7384
|
return result;
|
|
7384
7385
|
}
|
|
7385
7386
|
|
|
7387
|
+
if (node.type === 'TaggedTemplateExpression') {
|
|
7388
|
+
// 1. Evaluate tag function async (may contain awaits)
|
|
7389
|
+
let thisContext = undefined;
|
|
7390
|
+
let tagFunction;
|
|
7391
|
+
|
|
7392
|
+
if (node.tag.type === 'MemberExpression') {
|
|
7393
|
+
thisContext = await this.evaluateAsync(node.tag.object, env);
|
|
7394
|
+
const prop = node.tag.computed
|
|
7395
|
+
? await this.evaluateAsync(node.tag.property, env)
|
|
7396
|
+
: node.tag.property.name;
|
|
7397
|
+
tagFunction = thisContext[prop];
|
|
7398
|
+
} else {
|
|
7399
|
+
tagFunction = await this.evaluateAsync(node.tag, env);
|
|
7400
|
+
}
|
|
7401
|
+
|
|
7402
|
+
// 2. Build strings array (synchronous - no awaits in quasis)
|
|
7403
|
+
const strings = [];
|
|
7404
|
+
const rawStrings = [];
|
|
7405
|
+
for (const quasi of node.quasi.quasis) {
|
|
7406
|
+
strings.push(quasi.value.cooked || quasi.value.raw);
|
|
7407
|
+
rawStrings.push(quasi.value.raw);
|
|
7408
|
+
}
|
|
7409
|
+
|
|
7410
|
+
Object.defineProperty(strings, 'raw', {
|
|
7411
|
+
value: Object.freeze(rawStrings),
|
|
7412
|
+
writable: false,
|
|
7413
|
+
enumerable: false,
|
|
7414
|
+
configurable: false
|
|
7415
|
+
});
|
|
7416
|
+
Object.freeze(strings);
|
|
7417
|
+
|
|
7418
|
+
// 3. Evaluate expressions async (may contain awaits)
|
|
7419
|
+
const values = [];
|
|
7420
|
+
for (const expr of node.quasi.expressions) {
|
|
7421
|
+
values.push(await this.evaluateAsync(expr, env));
|
|
7422
|
+
}
|
|
7423
|
+
|
|
7424
|
+
// 4. Call tag function (may be async)
|
|
7425
|
+
if (typeof tagFunction === 'function') {
|
|
7426
|
+
if (thisContext !== undefined) {
|
|
7427
|
+
return await tagFunction.call(thisContext, strings, ...values);
|
|
7428
|
+
}
|
|
7429
|
+
return await tagFunction(strings, ...values);
|
|
7430
|
+
} else if (tagFunction && tagFunction.__isFunction) {
|
|
7431
|
+
return await this.callUserFunction(tagFunction, [strings, ...values], env, thisContext);
|
|
7432
|
+
}
|
|
7433
|
+
|
|
7434
|
+
throw new TypeError('Tag must be a function');
|
|
7435
|
+
}
|
|
7436
|
+
|
|
7386
7437
|
// For logical expressions with async operands (await support)
|
|
7387
7438
|
if (node.type === 'LogicalExpression') {
|
|
7388
7439
|
const left = await this.evaluateAsync(node.left, env);
|
|
@@ -7821,6 +7872,24 @@ class Interpreter {
|
|
|
7821
7872
|
return this.normalizeJSXText(node.value);
|
|
7822
7873
|
}
|
|
7823
7874
|
|
|
7875
|
+
// For SpreadElement - return spread marker for flattenSpreadArgs
|
|
7876
|
+
if (node.type === 'SpreadElement') {
|
|
7877
|
+
const arg = await this.evaluateAsync(node.argument, env);
|
|
7878
|
+
if (Array.isArray(arg)) {
|
|
7879
|
+
return { __spread: true, __values: arg };
|
|
7880
|
+
}
|
|
7881
|
+
if (typeof arg === 'string') {
|
|
7882
|
+
return { __spread: true, __values: [...arg] };
|
|
7883
|
+
}
|
|
7884
|
+
if (arg !== null && arg !== undefined && typeof arg[Symbol.iterator] === 'function') {
|
|
7885
|
+
return { __spread: true, __values: [...arg] };
|
|
7886
|
+
}
|
|
7887
|
+
if (typeof arg === 'object' && arg !== null) {
|
|
7888
|
+
return { __spread: true, __values: Object.entries(arg) };
|
|
7889
|
+
}
|
|
7890
|
+
throw new TypeError('Spread syntax requires an iterable');
|
|
7891
|
+
}
|
|
7892
|
+
|
|
7824
7893
|
// Only leaf nodes should fall through to sync evaluate
|
|
7825
7894
|
// These have no sub-expressions that could contain await
|
|
7826
7895
|
if (['Literal', 'Identifier', 'BreakStatement', 'ContinueStatement',
|
|
@@ -7968,6 +8037,9 @@ class Interpreter {
|
|
|
7968
8037
|
case 'TemplateLiteral':
|
|
7969
8038
|
return this.evaluateTemplateLiteral(node, env);
|
|
7970
8039
|
|
|
8040
|
+
case 'TaggedTemplateExpression':
|
|
8041
|
+
return this.evaluateTaggedTemplateExpression(node, env);
|
|
8042
|
+
|
|
7971
8043
|
case 'ClassDeclaration':
|
|
7972
8044
|
return this.evaluateClassDeclaration(node, env);
|
|
7973
8045
|
|
|
@@ -9212,6 +9284,56 @@ class Interpreter {
|
|
|
9212
9284
|
return result;
|
|
9213
9285
|
}
|
|
9214
9286
|
|
|
9287
|
+
evaluateTaggedTemplateExpression(node, env) {
|
|
9288
|
+
// 1. Evaluate the tag function, preserving 'this' context for member expressions
|
|
9289
|
+
let thisContext = undefined;
|
|
9290
|
+
let tagFunction;
|
|
9291
|
+
|
|
9292
|
+
if (node.tag.type === 'MemberExpression') {
|
|
9293
|
+
// For method calls like obj.tag`...`, set this to obj
|
|
9294
|
+
thisContext = this.evaluate(node.tag.object, env);
|
|
9295
|
+
const prop = node.tag.computed
|
|
9296
|
+
? this.evaluate(node.tag.property, env)
|
|
9297
|
+
: node.tag.property.name;
|
|
9298
|
+
tagFunction = thisContext[prop];
|
|
9299
|
+
} else {
|
|
9300
|
+
tagFunction = this.evaluate(node.tag, env);
|
|
9301
|
+
}
|
|
9302
|
+
|
|
9303
|
+
// 2. Build the strings array from quasis (cooked values)
|
|
9304
|
+
const strings = [];
|
|
9305
|
+
const rawStrings = [];
|
|
9306
|
+
for (const quasi of node.quasi.quasis) {
|
|
9307
|
+
strings.push(quasi.value.cooked || quasi.value.raw);
|
|
9308
|
+
rawStrings.push(quasi.value.raw);
|
|
9309
|
+
}
|
|
9310
|
+
|
|
9311
|
+
// 3. Add the raw property (frozen per ES6 spec)
|
|
9312
|
+
Object.defineProperty(strings, 'raw', {
|
|
9313
|
+
value: Object.freeze(rawStrings),
|
|
9314
|
+
writable: false,
|
|
9315
|
+
enumerable: false,
|
|
9316
|
+
configurable: false
|
|
9317
|
+
});
|
|
9318
|
+
Object.freeze(strings);
|
|
9319
|
+
|
|
9320
|
+
// 4. Evaluate the embedded expressions
|
|
9321
|
+
const values = node.quasi.expressions.map(expr => this.evaluate(expr, env));
|
|
9322
|
+
|
|
9323
|
+
// 5. Call the tag function with proper this context
|
|
9324
|
+
if (typeof tagFunction === 'function') {
|
|
9325
|
+
if (thisContext !== undefined) {
|
|
9326
|
+
return tagFunction.call(thisContext, strings, ...values);
|
|
9327
|
+
}
|
|
9328
|
+
return tagFunction(strings, ...values);
|
|
9329
|
+
} else if (tagFunction && tagFunction.__isFunction) {
|
|
9330
|
+
// User-defined function
|
|
9331
|
+
return this.callUserFunction(tagFunction, [strings, ...values], env, thisContext);
|
|
9332
|
+
}
|
|
9333
|
+
|
|
9334
|
+
throw new TypeError('Tag must be a function');
|
|
9335
|
+
}
|
|
9336
|
+
|
|
9215
9337
|
evaluateClassDeclaration(node, env) {
|
|
9216
9338
|
const className = node.id.name;
|
|
9217
9339
|
const classFunc = this.createClass(node, env);
|
|
@@ -10328,7 +10450,8 @@ class WangInterpreter {
|
|
|
10328
10450
|
// Prepare execution options
|
|
10329
10451
|
const options = {
|
|
10330
10452
|
moduleResolver: this.moduleResolver,
|
|
10331
|
-
executionController: userOptions.executionController
|
|
10453
|
+
executionController: userOptions.executionController,
|
|
10454
|
+
abortSignal: userOptions.abortSignal // Pass abort signal to interpreter for cancellation support
|
|
10332
10455
|
// sourceType will be auto-detected from code
|
|
10333
10456
|
};
|
|
10334
10457
|
|
package/dist/index.d.ts
CHANGED
|
@@ -7323,10 +7323,11 @@ class Interpreter {
|
|
|
7323
7323
|
return undefined;
|
|
7324
7324
|
}
|
|
7325
7325
|
|
|
7326
|
-
const
|
|
7326
|
+
const rawArgs = [];
|
|
7327
7327
|
for (const arg of node.arguments) {
|
|
7328
|
-
|
|
7328
|
+
rawArgs.push(await this.evaluateAsync(arg, env));
|
|
7329
7329
|
}
|
|
7330
|
+
const args = this.flattenSpreadArgs(rawArgs);
|
|
7330
7331
|
|
|
7331
7332
|
if (typeof callee === 'function') {
|
|
7332
7333
|
if (thisContext !== undefined) {
|
|
@@ -7383,6 +7384,56 @@ class Interpreter {
|
|
|
7383
7384
|
return result;
|
|
7384
7385
|
}
|
|
7385
7386
|
|
|
7387
|
+
if (node.type === 'TaggedTemplateExpression') {
|
|
7388
|
+
// 1. Evaluate tag function async (may contain awaits)
|
|
7389
|
+
let thisContext = undefined;
|
|
7390
|
+
let tagFunction;
|
|
7391
|
+
|
|
7392
|
+
if (node.tag.type === 'MemberExpression') {
|
|
7393
|
+
thisContext = await this.evaluateAsync(node.tag.object, env);
|
|
7394
|
+
const prop = node.tag.computed
|
|
7395
|
+
? await this.evaluateAsync(node.tag.property, env)
|
|
7396
|
+
: node.tag.property.name;
|
|
7397
|
+
tagFunction = thisContext[prop];
|
|
7398
|
+
} else {
|
|
7399
|
+
tagFunction = await this.evaluateAsync(node.tag, env);
|
|
7400
|
+
}
|
|
7401
|
+
|
|
7402
|
+
// 2. Build strings array (synchronous - no awaits in quasis)
|
|
7403
|
+
const strings = [];
|
|
7404
|
+
const rawStrings = [];
|
|
7405
|
+
for (const quasi of node.quasi.quasis) {
|
|
7406
|
+
strings.push(quasi.value.cooked || quasi.value.raw);
|
|
7407
|
+
rawStrings.push(quasi.value.raw);
|
|
7408
|
+
}
|
|
7409
|
+
|
|
7410
|
+
Object.defineProperty(strings, 'raw', {
|
|
7411
|
+
value: Object.freeze(rawStrings),
|
|
7412
|
+
writable: false,
|
|
7413
|
+
enumerable: false,
|
|
7414
|
+
configurable: false
|
|
7415
|
+
});
|
|
7416
|
+
Object.freeze(strings);
|
|
7417
|
+
|
|
7418
|
+
// 3. Evaluate expressions async (may contain awaits)
|
|
7419
|
+
const values = [];
|
|
7420
|
+
for (const expr of node.quasi.expressions) {
|
|
7421
|
+
values.push(await this.evaluateAsync(expr, env));
|
|
7422
|
+
}
|
|
7423
|
+
|
|
7424
|
+
// 4. Call tag function (may be async)
|
|
7425
|
+
if (typeof tagFunction === 'function') {
|
|
7426
|
+
if (thisContext !== undefined) {
|
|
7427
|
+
return await tagFunction.call(thisContext, strings, ...values);
|
|
7428
|
+
}
|
|
7429
|
+
return await tagFunction(strings, ...values);
|
|
7430
|
+
} else if (tagFunction && tagFunction.__isFunction) {
|
|
7431
|
+
return await this.callUserFunction(tagFunction, [strings, ...values], env, thisContext);
|
|
7432
|
+
}
|
|
7433
|
+
|
|
7434
|
+
throw new TypeError('Tag must be a function');
|
|
7435
|
+
}
|
|
7436
|
+
|
|
7386
7437
|
// For logical expressions with async operands (await support)
|
|
7387
7438
|
if (node.type === 'LogicalExpression') {
|
|
7388
7439
|
const left = await this.evaluateAsync(node.left, env);
|
|
@@ -7821,6 +7872,24 @@ class Interpreter {
|
|
|
7821
7872
|
return this.normalizeJSXText(node.value);
|
|
7822
7873
|
}
|
|
7823
7874
|
|
|
7875
|
+
// For SpreadElement - return spread marker for flattenSpreadArgs
|
|
7876
|
+
if (node.type === 'SpreadElement') {
|
|
7877
|
+
const arg = await this.evaluateAsync(node.argument, env);
|
|
7878
|
+
if (Array.isArray(arg)) {
|
|
7879
|
+
return { __spread: true, __values: arg };
|
|
7880
|
+
}
|
|
7881
|
+
if (typeof arg === 'string') {
|
|
7882
|
+
return { __spread: true, __values: [...arg] };
|
|
7883
|
+
}
|
|
7884
|
+
if (arg !== null && arg !== undefined && typeof arg[Symbol.iterator] === 'function') {
|
|
7885
|
+
return { __spread: true, __values: [...arg] };
|
|
7886
|
+
}
|
|
7887
|
+
if (typeof arg === 'object' && arg !== null) {
|
|
7888
|
+
return { __spread: true, __values: Object.entries(arg) };
|
|
7889
|
+
}
|
|
7890
|
+
throw new TypeError('Spread syntax requires an iterable');
|
|
7891
|
+
}
|
|
7892
|
+
|
|
7824
7893
|
// Only leaf nodes should fall through to sync evaluate
|
|
7825
7894
|
// These have no sub-expressions that could contain await
|
|
7826
7895
|
if (['Literal', 'Identifier', 'BreakStatement', 'ContinueStatement',
|
|
@@ -7968,6 +8037,9 @@ class Interpreter {
|
|
|
7968
8037
|
case 'TemplateLiteral':
|
|
7969
8038
|
return this.evaluateTemplateLiteral(node, env);
|
|
7970
8039
|
|
|
8040
|
+
case 'TaggedTemplateExpression':
|
|
8041
|
+
return this.evaluateTaggedTemplateExpression(node, env);
|
|
8042
|
+
|
|
7971
8043
|
case 'ClassDeclaration':
|
|
7972
8044
|
return this.evaluateClassDeclaration(node, env);
|
|
7973
8045
|
|
|
@@ -9212,6 +9284,56 @@ class Interpreter {
|
|
|
9212
9284
|
return result;
|
|
9213
9285
|
}
|
|
9214
9286
|
|
|
9287
|
+
evaluateTaggedTemplateExpression(node, env) {
|
|
9288
|
+
// 1. Evaluate the tag function, preserving 'this' context for member expressions
|
|
9289
|
+
let thisContext = undefined;
|
|
9290
|
+
let tagFunction;
|
|
9291
|
+
|
|
9292
|
+
if (node.tag.type === 'MemberExpression') {
|
|
9293
|
+
// For method calls like obj.tag`...`, set this to obj
|
|
9294
|
+
thisContext = this.evaluate(node.tag.object, env);
|
|
9295
|
+
const prop = node.tag.computed
|
|
9296
|
+
? this.evaluate(node.tag.property, env)
|
|
9297
|
+
: node.tag.property.name;
|
|
9298
|
+
tagFunction = thisContext[prop];
|
|
9299
|
+
} else {
|
|
9300
|
+
tagFunction = this.evaluate(node.tag, env);
|
|
9301
|
+
}
|
|
9302
|
+
|
|
9303
|
+
// 2. Build the strings array from quasis (cooked values)
|
|
9304
|
+
const strings = [];
|
|
9305
|
+
const rawStrings = [];
|
|
9306
|
+
for (const quasi of node.quasi.quasis) {
|
|
9307
|
+
strings.push(quasi.value.cooked || quasi.value.raw);
|
|
9308
|
+
rawStrings.push(quasi.value.raw);
|
|
9309
|
+
}
|
|
9310
|
+
|
|
9311
|
+
// 3. Add the raw property (frozen per ES6 spec)
|
|
9312
|
+
Object.defineProperty(strings, 'raw', {
|
|
9313
|
+
value: Object.freeze(rawStrings),
|
|
9314
|
+
writable: false,
|
|
9315
|
+
enumerable: false,
|
|
9316
|
+
configurable: false
|
|
9317
|
+
});
|
|
9318
|
+
Object.freeze(strings);
|
|
9319
|
+
|
|
9320
|
+
// 4. Evaluate the embedded expressions
|
|
9321
|
+
const values = node.quasi.expressions.map(expr => this.evaluate(expr, env));
|
|
9322
|
+
|
|
9323
|
+
// 5. Call the tag function with proper this context
|
|
9324
|
+
if (typeof tagFunction === 'function') {
|
|
9325
|
+
if (thisContext !== undefined) {
|
|
9326
|
+
return tagFunction.call(thisContext, strings, ...values);
|
|
9327
|
+
}
|
|
9328
|
+
return tagFunction(strings, ...values);
|
|
9329
|
+
} else if (tagFunction && tagFunction.__isFunction) {
|
|
9330
|
+
// User-defined function
|
|
9331
|
+
return this.callUserFunction(tagFunction, [strings, ...values], env, thisContext);
|
|
9332
|
+
}
|
|
9333
|
+
|
|
9334
|
+
throw new TypeError('Tag must be a function');
|
|
9335
|
+
}
|
|
9336
|
+
|
|
9215
9337
|
evaluateClassDeclaration(node, env) {
|
|
9216
9338
|
const className = node.id.name;
|
|
9217
9339
|
const classFunc = this.createClass(node, env);
|
|
@@ -10328,7 +10450,8 @@ class WangInterpreter {
|
|
|
10328
10450
|
// Prepare execution options
|
|
10329
10451
|
const options = {
|
|
10330
10452
|
moduleResolver: this.moduleResolver,
|
|
10331
|
-
executionController: userOptions.executionController
|
|
10453
|
+
executionController: userOptions.executionController,
|
|
10454
|
+
abortSignal: userOptions.abortSignal // Pass abort signal to interpreter for cancellation support
|
|
10332
10455
|
// sourceType will be auto-detected from code
|
|
10333
10456
|
};
|
|
10334
10457
|
|
package/dist/index.js
CHANGED
|
@@ -6555,10 +6555,11 @@ var Interpreter = class _Interpreter {
|
|
|
6555
6555
|
if (node.optional && (callee === null || callee === void 0)) {
|
|
6556
6556
|
return void 0;
|
|
6557
6557
|
}
|
|
6558
|
-
const
|
|
6558
|
+
const rawArgs = [];
|
|
6559
6559
|
for (const arg of node.arguments) {
|
|
6560
|
-
|
|
6560
|
+
rawArgs.push(await this.evaluateAsync(arg, env));
|
|
6561
6561
|
}
|
|
6562
|
+
const args = this.flattenSpreadArgs(rawArgs);
|
|
6562
6563
|
if (typeof callee === "function") {
|
|
6563
6564
|
if (thisContext !== void 0) {
|
|
6564
6565
|
return await callee.call(thisContext, ...args);
|
|
@@ -6597,6 +6598,43 @@ var Interpreter = class _Interpreter {
|
|
|
6597
6598
|
}
|
|
6598
6599
|
return result;
|
|
6599
6600
|
}
|
|
6601
|
+
if (node.type === "TaggedTemplateExpression") {
|
|
6602
|
+
let thisContext = void 0;
|
|
6603
|
+
let tagFunction;
|
|
6604
|
+
if (node.tag.type === "MemberExpression") {
|
|
6605
|
+
thisContext = await this.evaluateAsync(node.tag.object, env);
|
|
6606
|
+
const prop = node.tag.computed ? await this.evaluateAsync(node.tag.property, env) : node.tag.property.name;
|
|
6607
|
+
tagFunction = thisContext[prop];
|
|
6608
|
+
} else {
|
|
6609
|
+
tagFunction = await this.evaluateAsync(node.tag, env);
|
|
6610
|
+
}
|
|
6611
|
+
const strings = [];
|
|
6612
|
+
const rawStrings = [];
|
|
6613
|
+
for (const quasi of node.quasi.quasis) {
|
|
6614
|
+
strings.push(quasi.value.cooked || quasi.value.raw);
|
|
6615
|
+
rawStrings.push(quasi.value.raw);
|
|
6616
|
+
}
|
|
6617
|
+
Object.defineProperty(strings, "raw", {
|
|
6618
|
+
value: Object.freeze(rawStrings),
|
|
6619
|
+
writable: false,
|
|
6620
|
+
enumerable: false,
|
|
6621
|
+
configurable: false
|
|
6622
|
+
});
|
|
6623
|
+
Object.freeze(strings);
|
|
6624
|
+
const values = [];
|
|
6625
|
+
for (const expr of node.quasi.expressions) {
|
|
6626
|
+
values.push(await this.evaluateAsync(expr, env));
|
|
6627
|
+
}
|
|
6628
|
+
if (typeof tagFunction === "function") {
|
|
6629
|
+
if (thisContext !== void 0) {
|
|
6630
|
+
return await tagFunction.call(thisContext, strings, ...values);
|
|
6631
|
+
}
|
|
6632
|
+
return await tagFunction(strings, ...values);
|
|
6633
|
+
} else if (tagFunction && tagFunction.__isFunction) {
|
|
6634
|
+
return await this.callUserFunction(tagFunction, [strings, ...values], env, thisContext);
|
|
6635
|
+
}
|
|
6636
|
+
throw new TypeError("Tag must be a function");
|
|
6637
|
+
}
|
|
6600
6638
|
if (node.type === "LogicalExpression") {
|
|
6601
6639
|
const left = await this.evaluateAsync(node.left, env);
|
|
6602
6640
|
if (node.operator === "&&") {
|
|
@@ -6960,6 +6998,22 @@ var Interpreter = class _Interpreter {
|
|
|
6960
6998
|
if (node.type === "JSXText") {
|
|
6961
6999
|
return this.normalizeJSXText(node.value);
|
|
6962
7000
|
}
|
|
7001
|
+
if (node.type === "SpreadElement") {
|
|
7002
|
+
const arg = await this.evaluateAsync(node.argument, env);
|
|
7003
|
+
if (Array.isArray(arg)) {
|
|
7004
|
+
return { __spread: true, __values: arg };
|
|
7005
|
+
}
|
|
7006
|
+
if (typeof arg === "string") {
|
|
7007
|
+
return { __spread: true, __values: [...arg] };
|
|
7008
|
+
}
|
|
7009
|
+
if (arg !== null && arg !== void 0 && typeof arg[Symbol.iterator] === "function") {
|
|
7010
|
+
return { __spread: true, __values: [...arg] };
|
|
7011
|
+
}
|
|
7012
|
+
if (typeof arg === "object" && arg !== null) {
|
|
7013
|
+
return { __spread: true, __values: Object.entries(arg) };
|
|
7014
|
+
}
|
|
7015
|
+
throw new TypeError("Spread syntax requires an iterable");
|
|
7016
|
+
}
|
|
6963
7017
|
if ([
|
|
6964
7018
|
"Literal",
|
|
6965
7019
|
"Identifier",
|
|
@@ -7064,6 +7118,8 @@ var Interpreter = class _Interpreter {
|
|
|
7064
7118
|
// ES6+ Features
|
|
7065
7119
|
case "TemplateLiteral":
|
|
7066
7120
|
return this.evaluateTemplateLiteral(node, env);
|
|
7121
|
+
case "TaggedTemplateExpression":
|
|
7122
|
+
return this.evaluateTaggedTemplateExpression(node, env);
|
|
7067
7123
|
case "ClassDeclaration":
|
|
7068
7124
|
return this.evaluateClassDeclaration(node, env);
|
|
7069
7125
|
case "ClassExpression":
|
|
@@ -8007,6 +8063,40 @@ var Interpreter = class _Interpreter {
|
|
|
8007
8063
|
}
|
|
8008
8064
|
return result;
|
|
8009
8065
|
}
|
|
8066
|
+
evaluateTaggedTemplateExpression(node, env) {
|
|
8067
|
+
let thisContext = void 0;
|
|
8068
|
+
let tagFunction;
|
|
8069
|
+
if (node.tag.type === "MemberExpression") {
|
|
8070
|
+
thisContext = this.evaluate(node.tag.object, env);
|
|
8071
|
+
const prop = node.tag.computed ? this.evaluate(node.tag.property, env) : node.tag.property.name;
|
|
8072
|
+
tagFunction = thisContext[prop];
|
|
8073
|
+
} else {
|
|
8074
|
+
tagFunction = this.evaluate(node.tag, env);
|
|
8075
|
+
}
|
|
8076
|
+
const strings = [];
|
|
8077
|
+
const rawStrings = [];
|
|
8078
|
+
for (const quasi of node.quasi.quasis) {
|
|
8079
|
+
strings.push(quasi.value.cooked || quasi.value.raw);
|
|
8080
|
+
rawStrings.push(quasi.value.raw);
|
|
8081
|
+
}
|
|
8082
|
+
Object.defineProperty(strings, "raw", {
|
|
8083
|
+
value: Object.freeze(rawStrings),
|
|
8084
|
+
writable: false,
|
|
8085
|
+
enumerable: false,
|
|
8086
|
+
configurable: false
|
|
8087
|
+
});
|
|
8088
|
+
Object.freeze(strings);
|
|
8089
|
+
const values = node.quasi.expressions.map((expr) => this.evaluate(expr, env));
|
|
8090
|
+
if (typeof tagFunction === "function") {
|
|
8091
|
+
if (thisContext !== void 0) {
|
|
8092
|
+
return tagFunction.call(thisContext, strings, ...values);
|
|
8093
|
+
}
|
|
8094
|
+
return tagFunction(strings, ...values);
|
|
8095
|
+
} else if (tagFunction && tagFunction.__isFunction) {
|
|
8096
|
+
return this.callUserFunction(tagFunction, [strings, ...values], env, thisContext);
|
|
8097
|
+
}
|
|
8098
|
+
throw new TypeError("Tag must be a function");
|
|
8099
|
+
}
|
|
8010
8100
|
evaluateClassDeclaration(node, env) {
|
|
8011
8101
|
const className = node.id.name;
|
|
8012
8102
|
const classFunc = this.createClass(node, env);
|
|
@@ -8851,7 +8941,9 @@ var WangInterpreter = class {
|
|
|
8851
8941
|
const hasTopLevelReturn = this.hasTopLevelReturn(code);
|
|
8852
8942
|
const options = {
|
|
8853
8943
|
moduleResolver: this.moduleResolver,
|
|
8854
|
-
executionController: userOptions.executionController
|
|
8944
|
+
executionController: userOptions.executionController,
|
|
8945
|
+
abortSignal: userOptions.abortSignal
|
|
8946
|
+
// Pass abort signal to interpreter for cancellation support
|
|
8855
8947
|
// sourceType will be auto-detected from code
|
|
8856
8948
|
};
|
|
8857
8949
|
let result;
|