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.
@@ -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 args = [];
161
+ const rawArgs = [];
162
162
  for (const arg of node.arguments) {
163
- args.push(await this.evaluateAsync(arg, env));
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 args = [];
6592
+ const rawArgs = [];
6593
6593
  for (const arg of node.arguments) {
6594
- args.push(await this.evaluateAsync(arg, env));
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 args = [];
7326
+ const rawArgs = [];
7327
7327
  for (const arg of node.arguments) {
7328
- args.push(await this.evaluateAsync(arg, env));
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 args = [];
7326
+ const rawArgs = [];
7327
7327
  for (const arg of node.arguments) {
7328
- args.push(await this.evaluateAsync(arg, env));
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 args = [];
6558
+ const rawArgs = [];
6559
6559
  for (const arg of node.arguments) {
6560
- args.push(await this.evaluateAsync(arg, env));
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jslike",
3
- "version": "1.6.2",
3
+ "version": "1.7.0",
4
4
  "description": "Production-ready JavaScript interpreter with full ES6+ support using Acorn parser",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",