jslike 1.4.5 → 1.6.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/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Self-contained Acorn parser (bundled for zero runtime dependencies)
2
+ * Self-contained Acorn parser with JSX support (bundled for zero runtime dependencies)
3
3
  * Acorn is MIT licensed: https://github.com/acornjs/acorn
4
+ * Acorn-JSX is MIT licensed: https://github.com/acornjs/acorn-jsx
4
5
  * This file is auto-generated by scripts/bundle-acorn.js
5
- * Original size: ~224KB
6
6
  */
7
7
 
8
8
  // This file was generated. Do not modify manually!
@@ -6212,14 +6212,748 @@ Parser.acorn = {
6212
6212
  nonASCIIwhitespace: nonASCIIwhitespace
6213
6213
  };
6214
6214
 
6215
- // The main exported interface (under `self.acorn` when in the
6216
- // browser) is a `parse` function that takes a code string and returns
6217
- // an abstract syntax tree as specified by the [ESTree spec][estree].
6218
- //
6219
- // [estree]: https://github.com/estree/estree
6215
+ const XHTMLEntities = {
6216
+ quot: '\u0022',
6217
+ amp: '&',
6218
+ apos: '\u0027',
6219
+ lt: '<',
6220
+ gt: '>',
6221
+ nbsp: '\u00A0',
6222
+ iexcl: '\u00A1',
6223
+ cent: '\u00A2',
6224
+ pound: '\u00A3',
6225
+ curren: '\u00A4',
6226
+ yen: '\u00A5',
6227
+ brvbar: '\u00A6',
6228
+ sect: '\u00A7',
6229
+ uml: '\u00A8',
6230
+ copy: '\u00A9',
6231
+ ordf: '\u00AA',
6232
+ laquo: '\u00AB',
6233
+ not: '\u00AC',
6234
+ shy: '\u00AD',
6235
+ reg: '\u00AE',
6236
+ macr: '\u00AF',
6237
+ deg: '\u00B0',
6238
+ plusmn: '\u00B1',
6239
+ sup2: '\u00B2',
6240
+ sup3: '\u00B3',
6241
+ acute: '\u00B4',
6242
+ micro: '\u00B5',
6243
+ para: '\u00B6',
6244
+ middot: '\u00B7',
6245
+ cedil: '\u00B8',
6246
+ sup1: '\u00B9',
6247
+ ordm: '\u00BA',
6248
+ raquo: '\u00BB',
6249
+ frac14: '\u00BC',
6250
+ frac12: '\u00BD',
6251
+ frac34: '\u00BE',
6252
+ iquest: '\u00BF',
6253
+ Agrave: '\u00C0',
6254
+ Aacute: '\u00C1',
6255
+ Acirc: '\u00C2',
6256
+ Atilde: '\u00C3',
6257
+ Auml: '\u00C4',
6258
+ Aring: '\u00C5',
6259
+ AElig: '\u00C6',
6260
+ Ccedil: '\u00C7',
6261
+ Egrave: '\u00C8',
6262
+ Eacute: '\u00C9',
6263
+ Ecirc: '\u00CA',
6264
+ Euml: '\u00CB',
6265
+ Igrave: '\u00CC',
6266
+ Iacute: '\u00CD',
6267
+ Icirc: '\u00CE',
6268
+ Iuml: '\u00CF',
6269
+ ETH: '\u00D0',
6270
+ Ntilde: '\u00D1',
6271
+ Ograve: '\u00D2',
6272
+ Oacute: '\u00D3',
6273
+ Ocirc: '\u00D4',
6274
+ Otilde: '\u00D5',
6275
+ Ouml: '\u00D6',
6276
+ times: '\u00D7',
6277
+ Oslash: '\u00D8',
6278
+ Ugrave: '\u00D9',
6279
+ Uacute: '\u00DA',
6280
+ Ucirc: '\u00DB',
6281
+ Uuml: '\u00DC',
6282
+ Yacute: '\u00DD',
6283
+ THORN: '\u00DE',
6284
+ szlig: '\u00DF',
6285
+ agrave: '\u00E0',
6286
+ aacute: '\u00E1',
6287
+ acirc: '\u00E2',
6288
+ atilde: '\u00E3',
6289
+ auml: '\u00E4',
6290
+ aring: '\u00E5',
6291
+ aelig: '\u00E6',
6292
+ ccedil: '\u00E7',
6293
+ egrave: '\u00E8',
6294
+ eacute: '\u00E9',
6295
+ ecirc: '\u00EA',
6296
+ euml: '\u00EB',
6297
+ igrave: '\u00EC',
6298
+ iacute: '\u00ED',
6299
+ icirc: '\u00EE',
6300
+ iuml: '\u00EF',
6301
+ eth: '\u00F0',
6302
+ ntilde: '\u00F1',
6303
+ ograve: '\u00F2',
6304
+ oacute: '\u00F3',
6305
+ ocirc: '\u00F4',
6306
+ otilde: '\u00F5',
6307
+ ouml: '\u00F6',
6308
+ divide: '\u00F7',
6309
+ oslash: '\u00F8',
6310
+ ugrave: '\u00F9',
6311
+ uacute: '\u00FA',
6312
+ ucirc: '\u00FB',
6313
+ uuml: '\u00FC',
6314
+ yacute: '\u00FD',
6315
+ thorn: '\u00FE',
6316
+ yuml: '\u00FF',
6317
+ OElig: '\u0152',
6318
+ oelig: '\u0153',
6319
+ Scaron: '\u0160',
6320
+ scaron: '\u0161',
6321
+ Yuml: '\u0178',
6322
+ fnof: '\u0192',
6323
+ circ: '\u02C6',
6324
+ tilde: '\u02DC',
6325
+ Alpha: '\u0391',
6326
+ Beta: '\u0392',
6327
+ Gamma: '\u0393',
6328
+ Delta: '\u0394',
6329
+ Epsilon: '\u0395',
6330
+ Zeta: '\u0396',
6331
+ Eta: '\u0397',
6332
+ Theta: '\u0398',
6333
+ Iota: '\u0399',
6334
+ Kappa: '\u039A',
6335
+ Lambda: '\u039B',
6336
+ Mu: '\u039C',
6337
+ Nu: '\u039D',
6338
+ Xi: '\u039E',
6339
+ Omicron: '\u039F',
6340
+ Pi: '\u03A0',
6341
+ Rho: '\u03A1',
6342
+ Sigma: '\u03A3',
6343
+ Tau: '\u03A4',
6344
+ Upsilon: '\u03A5',
6345
+ Phi: '\u03A6',
6346
+ Chi: '\u03A7',
6347
+ Psi: '\u03A8',
6348
+ Omega: '\u03A9',
6349
+ alpha: '\u03B1',
6350
+ beta: '\u03B2',
6351
+ gamma: '\u03B3',
6352
+ delta: '\u03B4',
6353
+ epsilon: '\u03B5',
6354
+ zeta: '\u03B6',
6355
+ eta: '\u03B7',
6356
+ theta: '\u03B8',
6357
+ iota: '\u03B9',
6358
+ kappa: '\u03BA',
6359
+ lambda: '\u03BB',
6360
+ mu: '\u03BC',
6361
+ nu: '\u03BD',
6362
+ xi: '\u03BE',
6363
+ omicron: '\u03BF',
6364
+ pi: '\u03C0',
6365
+ rho: '\u03C1',
6366
+ sigmaf: '\u03C2',
6367
+ sigma: '\u03C3',
6368
+ tau: '\u03C4',
6369
+ upsilon: '\u03C5',
6370
+ phi: '\u03C6',
6371
+ chi: '\u03C7',
6372
+ psi: '\u03C8',
6373
+ omega: '\u03C9',
6374
+ thetasym: '\u03D1',
6375
+ upsih: '\u03D2',
6376
+ piv: '\u03D6',
6377
+ ensp: '\u2002',
6378
+ emsp: '\u2003',
6379
+ thinsp: '\u2009',
6380
+ zwnj: '\u200C',
6381
+ zwj: '\u200D',
6382
+ lrm: '\u200E',
6383
+ rlm: '\u200F',
6384
+ ndash: '\u2013',
6385
+ mdash: '\u2014',
6386
+ lsquo: '\u2018',
6387
+ rsquo: '\u2019',
6388
+ sbquo: '\u201A',
6389
+ ldquo: '\u201C',
6390
+ rdquo: '\u201D',
6391
+ bdquo: '\u201E',
6392
+ dagger: '\u2020',
6393
+ Dagger: '\u2021',
6394
+ bull: '\u2022',
6395
+ hellip: '\u2026',
6396
+ permil: '\u2030',
6397
+ prime: '\u2032',
6398
+ Prime: '\u2033',
6399
+ lsaquo: '\u2039',
6400
+ rsaquo: '\u203A',
6401
+ oline: '\u203E',
6402
+ frasl: '\u2044',
6403
+ euro: '\u20AC',
6404
+ image: '\u2111',
6405
+ weierp: '\u2118',
6406
+ real: '\u211C',
6407
+ trade: '\u2122',
6408
+ alefsym: '\u2135',
6409
+ larr: '\u2190',
6410
+ uarr: '\u2191',
6411
+ rarr: '\u2192',
6412
+ darr: '\u2193',
6413
+ harr: '\u2194',
6414
+ crarr: '\u21B5',
6415
+ lArr: '\u21D0',
6416
+ uArr: '\u21D1',
6417
+ rArr: '\u21D2',
6418
+ dArr: '\u21D3',
6419
+ hArr: '\u21D4',
6420
+ forall: '\u2200',
6421
+ part: '\u2202',
6422
+ exist: '\u2203',
6423
+ empty: '\u2205',
6424
+ nabla: '\u2207',
6425
+ isin: '\u2208',
6426
+ notin: '\u2209',
6427
+ ni: '\u220B',
6428
+ prod: '\u220F',
6429
+ sum: '\u2211',
6430
+ minus: '\u2212',
6431
+ lowast: '\u2217',
6432
+ radic: '\u221A',
6433
+ prop: '\u221D',
6434
+ infin: '\u221E',
6435
+ ang: '\u2220',
6436
+ and: '\u2227',
6437
+ or: '\u2228',
6438
+ cap: '\u2229',
6439
+ cup: '\u222A',
6440
+ 'int': '\u222B',
6441
+ there4: '\u2234',
6442
+ sim: '\u223C',
6443
+ cong: '\u2245',
6444
+ asymp: '\u2248',
6445
+ ne: '\u2260',
6446
+ equiv: '\u2261',
6447
+ le: '\u2264',
6448
+ ge: '\u2265',
6449
+ sub: '\u2282',
6450
+ sup: '\u2283',
6451
+ nsub: '\u2284',
6452
+ sube: '\u2286',
6453
+ supe: '\u2287',
6454
+ oplus: '\u2295',
6455
+ otimes: '\u2297',
6456
+ perp: '\u22A5',
6457
+ sdot: '\u22C5',
6458
+ lceil: '\u2308',
6459
+ rceil: '\u2309',
6460
+ lfloor: '\u230A',
6461
+ rfloor: '\u230B',
6462
+ lang: '\u2329',
6463
+ rang: '\u232A',
6464
+ loz: '\u25CA',
6465
+ spades: '\u2660',
6466
+ clubs: '\u2663',
6467
+ hearts: '\u2665',
6468
+ diams: '\u2666'
6469
+ };
6470
+
6471
+ const hexNumber = /^[\da-fA-F]+$/;
6472
+ const decimalNumber = /^\d+$/;
6473
+
6474
+ // The map to `acorn-jsx` tokens from `acorn` namespace objects.
6475
+ const acornJsxMap = new WeakMap();
6476
+
6477
+ // Get the original tokens for the given `acorn` namespace object.
6478
+ function getJsxTokens(acorn) {
6479
+ acorn = acorn.Parser.acorn || acorn;
6480
+ let acornJsx = acornJsxMap.get(acorn);
6481
+ if (!acornJsx) {
6482
+ const tt = acorn.tokTypes;
6483
+ const TokContext = acorn.TokContext;
6484
+ const TokenType = acorn.TokenType;
6485
+ const tc_oTag = new TokContext('<tag', false);
6486
+ const tc_cTag = new TokContext('</tag', false);
6487
+ const tc_expr = new TokContext('<tag>...</tag>', true, true);
6488
+ const tokContexts = {
6489
+ tc_oTag: tc_oTag,
6490
+ tc_cTag: tc_cTag,
6491
+ tc_expr: tc_expr
6492
+ };
6493
+ const tokTypes = {
6494
+ jsxName: new TokenType('jsxName'),
6495
+ jsxText: new TokenType('jsxText', {beforeExpr: true}),
6496
+ jsxTagStart: new TokenType('jsxTagStart', {startsExpr: true}),
6497
+ jsxTagEnd: new TokenType('jsxTagEnd')
6498
+ };
6499
+
6500
+ tokTypes.jsxTagStart.updateContext = function() {
6501
+ this.context.push(tc_expr); // treat as beginning of JSX expression
6502
+ this.context.push(tc_oTag); // start opening tag context
6503
+ this.exprAllowed = false;
6504
+ };
6505
+ tokTypes.jsxTagEnd.updateContext = function(prevType) {
6506
+ let out = this.context.pop();
6507
+ if (out === tc_oTag && prevType === tt.slash || out === tc_cTag) {
6508
+ this.context.pop();
6509
+ this.exprAllowed = this.curContext() === tc_expr;
6510
+ } else {
6511
+ this.exprAllowed = true;
6512
+ }
6513
+ };
6514
+
6515
+ acornJsx = { tokContexts: tokContexts, tokTypes: tokTypes };
6516
+ acornJsxMap.set(acorn, acornJsx);
6517
+ }
6220
6518
 
6221
- function parse$1(input, options) {
6222
- return Parser.parse(input, options)
6519
+ return acornJsx;
6520
+ }
6521
+
6522
+ // Transforms JSX element name to string.
6523
+
6524
+ function getQualifiedJSXName(object) {
6525
+ if (!object)
6526
+ return object;
6527
+
6528
+ if (object.type === 'JSXIdentifier')
6529
+ return object.name;
6530
+
6531
+ if (object.type === 'JSXNamespacedName')
6532
+ return object.namespace.name + ':' + object.name.name;
6533
+
6534
+ if (object.type === 'JSXMemberExpression')
6535
+ return getQualifiedJSXName(object.object) + '.' +
6536
+ getQualifiedJSXName(object.property);
6537
+ }
6538
+
6539
+ function acornJsx(options) {
6540
+ options = options || {};
6541
+ return function(Parser) {
6542
+ return plugin({
6543
+ allowNamespaces: options.allowNamespaces !== false,
6544
+ allowNamespacedObjects: !!options.allowNamespacedObjects
6545
+ }, Parser);
6546
+ };
6547
+ }
6548
+ // This is `tokTypes` of the peer dep.
6549
+ // This can be different instances from the actual `tokTypes` this plugin uses.
6550
+ // tokTypes property removed for bundle
6551
+
6552
+ function plugin(options, Parser) {
6553
+ const acorn = Parser.acorn || { tokTypes: tt, TokContext, TokenType, isNewLine, isIdentifierStart, isIdentifierChar, tokContexts };
6554
+ const acornJsx = getJsxTokens(acorn);
6555
+ const tt = acorn.tokTypes;
6556
+ const tok = acornJsx.tokTypes;
6557
+ const tokContexts = acorn.tokContexts;
6558
+ const tc_oTag = acornJsx.tokContexts.tc_oTag;
6559
+ const tc_cTag = acornJsx.tokContexts.tc_cTag;
6560
+ const tc_expr = acornJsx.tokContexts.tc_expr;
6561
+ const isNewLine = acorn.isNewLine;
6562
+ const isIdentifierStart = acorn.isIdentifierStart;
6563
+ const isIdentifierChar = acorn.isIdentifierChar;
6564
+
6565
+ return class extends Parser {
6566
+ // Expose actual `tokTypes` and `tokContexts` to other plugins.
6567
+ static get acornJsx() {
6568
+ return acornJsx;
6569
+ }
6570
+
6571
+ // Reads inline JSX contents token.
6572
+ jsx_readToken() {
6573
+ let out = '', chunkStart = this.pos;
6574
+ for (;;) {
6575
+ if (this.pos >= this.input.length)
6576
+ this.raise(this.start, 'Unterminated JSX contents');
6577
+ let ch = this.input.charCodeAt(this.pos);
6578
+
6579
+ switch (ch) {
6580
+ case 60: // '<'
6581
+ case 123: // '{'
6582
+ if (this.pos === this.start) {
6583
+ if (ch === 60 && this.exprAllowed) {
6584
+ ++this.pos;
6585
+ return this.finishToken(tok.jsxTagStart);
6586
+ }
6587
+ return this.getTokenFromCode(ch);
6588
+ }
6589
+ out += this.input.slice(chunkStart, this.pos);
6590
+ return this.finishToken(tok.jsxText, out);
6591
+
6592
+ case 38: // '&'
6593
+ out += this.input.slice(chunkStart, this.pos);
6594
+ out += this.jsx_readEntity();
6595
+ chunkStart = this.pos;
6596
+ break;
6597
+
6598
+ case 62: // '>'
6599
+ case 125: // '}'
6600
+ this.raise(
6601
+ this.pos,
6602
+ "Unexpected token `" + this.input[this.pos] + "`. Did you mean `" +
6603
+ (ch === 62 ? "&gt;" : "&rbrace;") + "` or " + "`{\"" + this.input[this.pos] + "\"}" + "`?"
6604
+ );
6605
+
6606
+ default:
6607
+ if (isNewLine(ch)) {
6608
+ out += this.input.slice(chunkStart, this.pos);
6609
+ out += this.jsx_readNewLine(true);
6610
+ chunkStart = this.pos;
6611
+ } else {
6612
+ ++this.pos;
6613
+ }
6614
+ }
6615
+ }
6616
+ }
6617
+
6618
+ jsx_readNewLine(normalizeCRLF) {
6619
+ let ch = this.input.charCodeAt(this.pos);
6620
+ let out;
6621
+ ++this.pos;
6622
+ if (ch === 13 && this.input.charCodeAt(this.pos) === 10) {
6623
+ ++this.pos;
6624
+ out = normalizeCRLF ? '\n' : '\r\n';
6625
+ } else {
6626
+ out = String.fromCharCode(ch);
6627
+ }
6628
+ if (this.options.locations) {
6629
+ ++this.curLine;
6630
+ this.lineStart = this.pos;
6631
+ }
6632
+
6633
+ return out;
6634
+ }
6635
+
6636
+ jsx_readString(quote) {
6637
+ let out = '', chunkStart = ++this.pos;
6638
+ for (;;) {
6639
+ if (this.pos >= this.input.length)
6640
+ this.raise(this.start, 'Unterminated string constant');
6641
+ let ch = this.input.charCodeAt(this.pos);
6642
+ if (ch === quote) break;
6643
+ if (ch === 38) { // '&'
6644
+ out += this.input.slice(chunkStart, this.pos);
6645
+ out += this.jsx_readEntity();
6646
+ chunkStart = this.pos;
6647
+ } else if (isNewLine(ch)) {
6648
+ out += this.input.slice(chunkStart, this.pos);
6649
+ out += this.jsx_readNewLine(false);
6650
+ chunkStart = this.pos;
6651
+ } else {
6652
+ ++this.pos;
6653
+ }
6654
+ }
6655
+ out += this.input.slice(chunkStart, this.pos++);
6656
+ return this.finishToken(tt.string, out);
6657
+ }
6658
+
6659
+ jsx_readEntity() {
6660
+ let str = '', count = 0, entity;
6661
+ let ch = this.input[this.pos];
6662
+ if (ch !== '&')
6663
+ this.raise(this.pos, 'Entity must start with an ampersand');
6664
+ let startPos = ++this.pos;
6665
+ while (this.pos < this.input.length && count++ < 10) {
6666
+ ch = this.input[this.pos++];
6667
+ if (ch === ';') {
6668
+ if (str[0] === '#') {
6669
+ if (str[1] === 'x') {
6670
+ str = str.substr(2);
6671
+ if (hexNumber.test(str))
6672
+ entity = String.fromCharCode(parseInt(str, 16));
6673
+ } else {
6674
+ str = str.substr(1);
6675
+ if (decimalNumber.test(str))
6676
+ entity = String.fromCharCode(parseInt(str, 10));
6677
+ }
6678
+ } else {
6679
+ entity = XHTMLEntities[str];
6680
+ }
6681
+ break;
6682
+ }
6683
+ str += ch;
6684
+ }
6685
+ if (!entity) {
6686
+ this.pos = startPos;
6687
+ return '&';
6688
+ }
6689
+ return entity;
6690
+ }
6691
+
6692
+ // Read a JSX identifier (valid tag or attribute name).
6693
+ //
6694
+ // Optimized version since JSX identifiers can't contain
6695
+ // escape characters and so can be read as single slice.
6696
+ // Also assumes that first character was already checked
6697
+ // by isIdentifierStart in readToken.
6698
+
6699
+ jsx_readWord() {
6700
+ let ch, start = this.pos;
6701
+ do {
6702
+ ch = this.input.charCodeAt(++this.pos);
6703
+ } while (isIdentifierChar(ch) || ch === 45); // '-'
6704
+ return this.finishToken(tok.jsxName, this.input.slice(start, this.pos));
6705
+ }
6706
+
6707
+ // Parse next token as JSX identifier
6708
+
6709
+ jsx_parseIdentifier() {
6710
+ let node = this.startNode();
6711
+ if (this.type === tok.jsxName)
6712
+ node.name = this.value;
6713
+ else if (this.type.keyword)
6714
+ node.name = this.type.keyword;
6715
+ else
6716
+ this.unexpected();
6717
+ this.next();
6718
+ return this.finishNode(node, 'JSXIdentifier');
6719
+ }
6720
+
6721
+ // Parse namespaced identifier.
6722
+
6723
+ jsx_parseNamespacedName() {
6724
+ let startPos = this.start, startLoc = this.startLoc;
6725
+ let name = this.jsx_parseIdentifier();
6726
+ if (!options.allowNamespaces || !this.eat(tt.colon)) return name;
6727
+ var node = this.startNodeAt(startPos, startLoc);
6728
+ node.namespace = name;
6729
+ node.name = this.jsx_parseIdentifier();
6730
+ return this.finishNode(node, 'JSXNamespacedName');
6731
+ }
6732
+
6733
+ // Parses element name in any form - namespaced, member
6734
+ // or single identifier.
6735
+
6736
+ jsx_parseElementName() {
6737
+ if (this.type === tok.jsxTagEnd) return '';
6738
+ let startPos = this.start, startLoc = this.startLoc;
6739
+ let node = this.jsx_parseNamespacedName();
6740
+ if (this.type === tt.dot && node.type === 'JSXNamespacedName' && !options.allowNamespacedObjects) {
6741
+ this.unexpected();
6742
+ }
6743
+ while (this.eat(tt.dot)) {
6744
+ let newNode = this.startNodeAt(startPos, startLoc);
6745
+ newNode.object = node;
6746
+ newNode.property = this.jsx_parseIdentifier();
6747
+ node = this.finishNode(newNode, 'JSXMemberExpression');
6748
+ }
6749
+ return node;
6750
+ }
6751
+
6752
+ // Parses any type of JSX attribute value.
6753
+
6754
+ jsx_parseAttributeValue() {
6755
+ switch (this.type) {
6756
+ case tt.braceL:
6757
+ let node = this.jsx_parseExpressionContainer();
6758
+ if (node.expression.type === 'JSXEmptyExpression')
6759
+ this.raise(node.start, 'JSX attributes must only be assigned a non-empty expression');
6760
+ return node;
6761
+
6762
+ case tok.jsxTagStart:
6763
+ case tt.string:
6764
+ return this.parseExprAtom();
6765
+
6766
+ default:
6767
+ this.raise(this.start, 'JSX value should be either an expression or a quoted JSX text');
6768
+ }
6769
+ }
6770
+
6771
+ // JSXEmptyExpression is unique type since it doesn't actually parse anything,
6772
+ // and so it should start at the end of last read token (left brace) and finish
6773
+ // at the beginning of the next one (right brace).
6774
+
6775
+ jsx_parseEmptyExpression() {
6776
+ let node = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc);
6777
+ return this.finishNodeAt(node, 'JSXEmptyExpression', this.start, this.startLoc);
6778
+ }
6779
+
6780
+ // Parses JSX expression enclosed into curly brackets.
6781
+
6782
+ jsx_parseExpressionContainer() {
6783
+ let node = this.startNode();
6784
+ this.next();
6785
+ node.expression = this.type === tt.braceR
6786
+ ? this.jsx_parseEmptyExpression()
6787
+ : this.parseExpression();
6788
+ this.expect(tt.braceR);
6789
+ return this.finishNode(node, 'JSXExpressionContainer');
6790
+ }
6791
+
6792
+ // Parses following JSX attribute name-value pair.
6793
+
6794
+ jsx_parseAttribute() {
6795
+ let node = this.startNode();
6796
+ if (this.eat(tt.braceL)) {
6797
+ this.expect(tt.ellipsis);
6798
+ node.argument = this.parseMaybeAssign();
6799
+ this.expect(tt.braceR);
6800
+ return this.finishNode(node, 'JSXSpreadAttribute');
6801
+ }
6802
+ node.name = this.jsx_parseNamespacedName();
6803
+ node.value = this.eat(tt.eq) ? this.jsx_parseAttributeValue() : null;
6804
+ return this.finishNode(node, 'JSXAttribute');
6805
+ }
6806
+
6807
+ // Parses JSX opening tag starting after '<'.
6808
+
6809
+ jsx_parseOpeningElementAt(startPos, startLoc) {
6810
+ let node = this.startNodeAt(startPos, startLoc);
6811
+ node.attributes = [];
6812
+ let nodeName = this.jsx_parseElementName();
6813
+ if (nodeName) node.name = nodeName;
6814
+ while (this.type !== tt.slash && this.type !== tok.jsxTagEnd)
6815
+ node.attributes.push(this.jsx_parseAttribute());
6816
+ node.selfClosing = this.eat(tt.slash);
6817
+ this.expect(tok.jsxTagEnd);
6818
+ return this.finishNode(node, nodeName ? 'JSXOpeningElement' : 'JSXOpeningFragment');
6819
+ }
6820
+
6821
+ // Parses JSX closing tag starting after '</'.
6822
+
6823
+ jsx_parseClosingElementAt(startPos, startLoc) {
6824
+ let node = this.startNodeAt(startPos, startLoc);
6825
+ let nodeName = this.jsx_parseElementName();
6826
+ if (nodeName) node.name = nodeName;
6827
+ this.expect(tok.jsxTagEnd);
6828
+ return this.finishNode(node, nodeName ? 'JSXClosingElement' : 'JSXClosingFragment');
6829
+ }
6830
+
6831
+ // Parses entire JSX element, including it's opening tag
6832
+ // (starting after '<'), attributes, contents and closing tag.
6833
+
6834
+ jsx_parseElementAt(startPos, startLoc) {
6835
+ let node = this.startNodeAt(startPos, startLoc);
6836
+ let children = [];
6837
+ let openingElement = this.jsx_parseOpeningElementAt(startPos, startLoc);
6838
+ let closingElement = null;
6839
+
6840
+ if (!openingElement.selfClosing) {
6841
+ contents: for (;;) {
6842
+ switch (this.type) {
6843
+ case tok.jsxTagStart:
6844
+ startPos = this.start; startLoc = this.startLoc;
6845
+ this.next();
6846
+ if (this.eat(tt.slash)) {
6847
+ closingElement = this.jsx_parseClosingElementAt(startPos, startLoc);
6848
+ break contents;
6849
+ }
6850
+ children.push(this.jsx_parseElementAt(startPos, startLoc));
6851
+ break;
6852
+
6853
+ case tok.jsxText:
6854
+ children.push(this.parseExprAtom());
6855
+ break;
6856
+
6857
+ case tt.braceL:
6858
+ children.push(this.jsx_parseExpressionContainer());
6859
+ break;
6860
+
6861
+ default:
6862
+ this.unexpected();
6863
+ }
6864
+ }
6865
+ if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) {
6866
+ this.raise(
6867
+ closingElement.start,
6868
+ 'Expected corresponding JSX closing tag for <' + getQualifiedJSXName(openingElement.name) + '>');
6869
+ }
6870
+ }
6871
+ let fragmentOrElement = openingElement.name ? 'Element' : 'Fragment';
6872
+
6873
+ node['opening' + fragmentOrElement] = openingElement;
6874
+ node['closing' + fragmentOrElement] = closingElement;
6875
+ node.children = children;
6876
+ if (this.type === tt.relational && this.value === "<") {
6877
+ this.raise(this.start, "Adjacent JSX elements must be wrapped in an enclosing tag");
6878
+ }
6879
+ return this.finishNode(node, 'JSX' + fragmentOrElement);
6880
+ }
6881
+
6882
+ // Parse JSX text
6883
+
6884
+ jsx_parseText() {
6885
+ let node = this.parseLiteral(this.value);
6886
+ node.type = "JSXText";
6887
+ return node;
6888
+ }
6889
+
6890
+ // Parses entire JSX element from current position.
6891
+
6892
+ jsx_parseElement() {
6893
+ let startPos = this.start, startLoc = this.startLoc;
6894
+ this.next();
6895
+ return this.jsx_parseElementAt(startPos, startLoc);
6896
+ }
6897
+
6898
+ parseExprAtom(refShortHandDefaultPos) {
6899
+ if (this.type === tok.jsxText)
6900
+ return this.jsx_parseText();
6901
+ else if (this.type === tok.jsxTagStart)
6902
+ return this.jsx_parseElement();
6903
+ else
6904
+ return super.parseExprAtom(refShortHandDefaultPos);
6905
+ }
6906
+
6907
+ readToken(code) {
6908
+ let context = this.curContext();
6909
+
6910
+ if (context === tc_expr) return this.jsx_readToken();
6911
+
6912
+ if (context === tc_oTag || context === tc_cTag) {
6913
+ if (isIdentifierStart(code)) return this.jsx_readWord();
6914
+
6915
+ if (code == 62) {
6916
+ ++this.pos;
6917
+ return this.finishToken(tok.jsxTagEnd);
6918
+ }
6919
+
6920
+ if ((code === 34 || code === 39) && context == tc_oTag)
6921
+ return this.jsx_readString(code);
6922
+ }
6923
+
6924
+ if (code === 60 && this.exprAllowed && this.input.charCodeAt(this.pos + 1) !== 33) {
6925
+ ++this.pos;
6926
+ return this.finishToken(tok.jsxTagStart);
6927
+ }
6928
+ return super.readToken(code);
6929
+ }
6930
+
6931
+ updateContext(prevType) {
6932
+ if (this.type == tt.braceL) {
6933
+ var curContext = this.curContext();
6934
+ if (curContext == tc_oTag) this.context.push(tokContexts.b_expr);
6935
+ else if (curContext == tc_expr) this.context.push(tokContexts.b_tmpl);
6936
+ else super.updateContext(prevType);
6937
+ this.exprAllowed = true;
6938
+ } else if (this.type === tt.slash && prevType === tok.jsxTagStart) {
6939
+ this.context.length -= 2; // do not consider JSX expr -> JSX open tag -> ... anymore
6940
+ this.context.push(tc_cTag); // reconsider as closing tag context
6941
+ this.exprAllowed = false;
6942
+ } else {
6943
+ return super.updateContext(prevType);
6944
+ }
6945
+ }
6946
+ };
6947
+ }
6948
+
6949
+
6950
+ // ========== Create JSX-enabled Parser ==========
6951
+
6952
+ const JSXParser = Parser.extend(acornJsx());
6953
+
6954
+ // JSX-aware parse function that replaces the original
6955
+ function jsxParse(input, options) {
6956
+ return JSXParser.parse(input, options);
6223
6957
  }
6224
6958
 
6225
6959
  // Runtime Environment for variable scoping and storage
@@ -6440,10 +7174,17 @@ class Interpreter {
6440
7174
  this.moduleCache = new Map(); // Cache loaded modules
6441
7175
  this.moduleExports = {}; // Track exports in current module
6442
7176
  this.abortSignal = options.abortSignal;
7177
+ this.executionController = options.executionController;
6443
7178
  }
6444
7179
 
6445
- // Check if execution should be aborted
7180
+ // Check if execution should be aborted (sync version)
6446
7181
  checkAbortSignal() {
7182
+ // Check controller first if available
7183
+ if (this.executionController) {
7184
+ this.executionController._checkAbortSync();
7185
+ return;
7186
+ }
7187
+ // Fall back to legacy abortSignal
6447
7188
  if (this.abortSignal && this.abortSignal.aborted) {
6448
7189
  const error = new Error('The operation was aborted');
6449
7190
  error.name = 'AbortError';
@@ -6451,12 +7192,26 @@ class Interpreter {
6451
7192
  }
6452
7193
  }
6453
7194
 
7195
+ // Checkpoint that returns a promise only when controller is present
7196
+ // When no controller, returns null to signal no await needed
7197
+ _getCheckpointPromise(node, env) {
7198
+ if (this.executionController) {
7199
+ this.executionController._setEnv(env);
7200
+ return this.executionController._checkpoint(node);
7201
+ } else {
7202
+ this.checkAbortSignal();
7203
+ return null; // Signal that no await is needed
7204
+ }
7205
+ }
7206
+
6454
7207
  // Async evaluation for async functions - handles await expressions
6455
7208
  async evaluateAsync(node, env) {
6456
7209
  if (!node) return undefined;
6457
7210
 
6458
- // Check for abort signal before evaluating
6459
- this.checkAbortSignal();
7211
+ // Checkpoint - yields if paused, throws if aborted
7212
+ // Only await when there's actually a promise (controller present)
7213
+ const checkpointPromise = this._getCheckpointPromise(node, env);
7214
+ if (checkpointPromise) await checkpointPromise;
6460
7215
 
6461
7216
  // Handle await expressions by actually awaiting the promise
6462
7217
  if (node.type === 'AwaitExpression') {
@@ -6693,6 +7448,9 @@ class Interpreter {
6693
7448
  await this.evaluateAsync(node.init, forEnv);
6694
7449
  }
6695
7450
  while (!node.test || await this.evaluateAsync(node.test, forEnv)) {
7451
+ // Checkpoint at each loop iteration (only await if controller present)
7452
+ const cp1 = this._getCheckpointPromise(node, forEnv);
7453
+ if (cp1) await cp1;
6696
7454
  const result = await this.evaluateAsync(node.body, forEnv);
6697
7455
  if (result instanceof BreakSignal) {
6698
7456
  break;
@@ -6721,6 +7479,9 @@ class Interpreter {
6721
7479
  const isConst = node.left.kind === 'const';
6722
7480
 
6723
7481
  for (const value of iterable) {
7482
+ // Checkpoint at each loop iteration (only await if controller present)
7483
+ const cp2 = this._getCheckpointPromise(node, forEnv);
7484
+ if (cp2) await cp2;
6724
7485
  const iterEnv = forEnv.extend();
6725
7486
  if (declarator.id.type === 'Identifier') {
6726
7487
  iterEnv.define(declarator.id.name, value, isConst);
@@ -6754,6 +7515,9 @@ class Interpreter {
6754
7515
  forEnv.define(varName, undefined);
6755
7516
 
6756
7517
  for (const key in obj) {
7518
+ // Checkpoint at each loop iteration (only await if controller present)
7519
+ const cp3 = this._getCheckpointPromise(node, forEnv);
7520
+ if (cp3) await cp3;
6757
7521
  forEnv.set(varName, key);
6758
7522
  const result = await this.evaluateAsync(node.body, forEnv);
6759
7523
  if (result instanceof BreakSignal) {
@@ -6772,6 +7536,9 @@ class Interpreter {
6772
7536
  // For WhileStatement with async body
6773
7537
  if (node.type === 'WhileStatement') {
6774
7538
  while (await this.evaluateAsync(node.test, env)) {
7539
+ // Checkpoint at each loop iteration (only await if controller present)
7540
+ const cp4 = this._getCheckpointPromise(node, env);
7541
+ if (cp4) await cp4;
6775
7542
  const result = await this.evaluateAsync(node.body, env);
6776
7543
  if (result instanceof BreakSignal) {
6777
7544
  break;
@@ -6789,6 +7556,9 @@ class Interpreter {
6789
7556
  // For DoWhileStatement with async body
6790
7557
  if (node.type === 'DoWhileStatement') {
6791
7558
  do {
7559
+ // Checkpoint at each loop iteration (only await if controller present)
7560
+ const cp5 = this._getCheckpointPromise(node, env);
7561
+ if (cp5) await cp5;
6792
7562
  const result = await this.evaluateAsync(node.body, env);
6793
7563
  if (result instanceof BreakSignal) {
6794
7564
  break;
@@ -7031,6 +7801,26 @@ class Interpreter {
7031
7801
  return this.evaluateClassExpression(node, env);
7032
7802
  }
7033
7803
 
7804
+ // JSX Support (async)
7805
+ if (node.type === 'JSXElement') {
7806
+ return await this.evaluateJSXElementAsync(node, env);
7807
+ }
7808
+
7809
+ if (node.type === 'JSXFragment') {
7810
+ return await this.evaluateJSXFragmentAsync(node, env);
7811
+ }
7812
+
7813
+ if (node.type === 'JSXExpressionContainer') {
7814
+ if (node.expression.type === 'JSXEmptyExpression') {
7815
+ return undefined;
7816
+ }
7817
+ return await this.evaluateAsync(node.expression, env);
7818
+ }
7819
+
7820
+ if (node.type === 'JSXText') {
7821
+ return this.normalizeJSXText(node.value);
7822
+ }
7823
+
7034
7824
  // Only leaf nodes should fall through to sync evaluate
7035
7825
  // These have no sub-expressions that could contain await
7036
7826
  if (['Literal', 'Identifier', 'BreakStatement', 'ContinueStatement',
@@ -7205,6 +7995,22 @@ class Interpreter {
7205
7995
  case 'Property':
7206
7996
  return this.evaluateProperty(node, env);
7207
7997
 
7998
+ // JSX Support
7999
+ case 'JSXElement':
8000
+ return this.evaluateJSXElement(node, env);
8001
+
8002
+ case 'JSXFragment':
8003
+ return this.evaluateJSXFragment(node, env);
8004
+
8005
+ case 'JSXExpressionContainer':
8006
+ if (node.expression.type === 'JSXEmptyExpression') {
8007
+ return undefined;
8008
+ }
8009
+ return this.evaluate(node.expression, env);
8010
+
8011
+ case 'JSXText':
8012
+ return this.normalizeJSXText(node.value);
8013
+
7208
8014
  default:
7209
8015
  throw new Error(`Unknown node type: ${node.type}`);
7210
8016
  }
@@ -7592,6 +8398,9 @@ class Interpreter {
7592
8398
  const metadata = func.__metadata || func;
7593
8399
  const funcEnv = new Environment(metadata.closure);
7594
8400
 
8401
+ // Get function name for call stack tracking
8402
+ const funcName = metadata.name || func.name || 'anonymous';
8403
+
7595
8404
  // Bind 'this' if provided (for method calls)
7596
8405
  if (thisContext !== undefined) {
7597
8406
  funcEnv.define('this', thisContext);
@@ -7627,18 +8436,54 @@ class Interpreter {
7627
8436
  // Execute function body
7628
8437
  // If async, use async evaluation and return a promise
7629
8438
  if (metadata.async) {
8439
+ // Track call stack for async functions
8440
+ if (this.executionController) {
8441
+ this.executionController._pushCall(funcName);
8442
+ }
7630
8443
  return (async () => {
8444
+ try {
8445
+ if (metadata.expression) {
8446
+ // Arrow function with expression body
8447
+ const result = await this.evaluateAsync(metadata.body, funcEnv);
8448
+ // If the result is a ThrowSignal, throw the error
8449
+ if (result instanceof ThrowSignal) {
8450
+ throw result.value;
8451
+ }
8452
+ return result;
8453
+ } else {
8454
+ // Block statement body
8455
+ const result = await this.evaluateAsync(metadata.body, funcEnv);
8456
+ if (result instanceof ReturnValue) {
8457
+ return result.value;
8458
+ }
8459
+ // If the result is a ThrowSignal, throw the error
8460
+ if (result instanceof ThrowSignal) {
8461
+ throw result.value;
8462
+ }
8463
+ return undefined;
8464
+ }
8465
+ } finally {
8466
+ if (this.executionController) {
8467
+ this.executionController._popCall();
8468
+ }
8469
+ }
8470
+ })();
8471
+ } else {
8472
+ // Synchronous evaluation for non-async functions
8473
+ // Track call stack for sync functions
8474
+ if (this.executionController) {
8475
+ this.executionController._pushCall(funcName);
8476
+ }
8477
+ try {
7631
8478
  if (metadata.expression) {
7632
- // Arrow function with expression body
7633
- const result = await this.evaluateAsync(metadata.body, funcEnv);
8479
+ const result = this.evaluate(metadata.body, funcEnv);
7634
8480
  // If the result is a ThrowSignal, throw the error
7635
8481
  if (result instanceof ThrowSignal) {
7636
8482
  throw result.value;
7637
8483
  }
7638
8484
  return result;
7639
8485
  } else {
7640
- // Block statement body
7641
- const result = await this.evaluateAsync(metadata.body, funcEnv);
8486
+ const result = this.evaluate(metadata.body, funcEnv);
7642
8487
  if (result instanceof ReturnValue) {
7643
8488
  return result.value;
7644
8489
  }
@@ -7648,26 +8493,10 @@ class Interpreter {
7648
8493
  }
7649
8494
  return undefined;
7650
8495
  }
7651
- })();
7652
- } else {
7653
- // Synchronous evaluation for non-async functions
7654
- if (metadata.expression) {
7655
- const result = this.evaluate(metadata.body, funcEnv);
7656
- // If the result is a ThrowSignal, throw the error
7657
- if (result instanceof ThrowSignal) {
7658
- throw result.value;
7659
- }
7660
- return result;
7661
- } else {
7662
- const result = this.evaluate(metadata.body, funcEnv);
7663
- if (result instanceof ReturnValue) {
7664
- return result.value;
7665
- }
7666
- // If the result is a ThrowSignal, throw the error
7667
- if (result instanceof ThrowSignal) {
7668
- throw result.value;
8496
+ } finally {
8497
+ if (this.executionController) {
8498
+ this.executionController._popCall();
7669
8499
  }
7670
- return undefined;
7671
8500
  }
7672
8501
  }
7673
8502
  }
@@ -8011,7 +8840,7 @@ class Interpreter {
8011
8840
  const moduleCode = typeof resolution === 'string' ? resolution : resolution.code;
8012
8841
 
8013
8842
  // Parse and execute module in its own environment
8014
- const moduleAst = parse$1(moduleCode, {
8843
+ const moduleAst = jsxParse(moduleCode, {
8015
8844
  ecmaVersion: 2020,
8016
8845
  sourceType: 'module',
8017
8846
  locations: false
@@ -8606,6 +9435,255 @@ class Interpreter {
8606
9435
  // Already handled in evaluateObjectExpression
8607
9436
  return undefined;
8608
9437
  }
9438
+
9439
+ // ===== JSX Support =====
9440
+
9441
+ evaluateJSXElement(node, env) {
9442
+ const createElement = this.getCreateElement(env);
9443
+ const { type, props } = this.evaluateJSXOpeningElement(node.openingElement, env);
9444
+ const children = this.evaluateJSXChildren(node.children, env);
9445
+
9446
+ if (children.length === 0) {
9447
+ return createElement(type, props);
9448
+ } else if (children.length === 1) {
9449
+ return createElement(type, props, children[0]);
9450
+ }
9451
+ return createElement(type, props, ...children);
9452
+ }
9453
+
9454
+ evaluateJSXFragment(node, env) {
9455
+ const createElement = this.getCreateElement(env);
9456
+ const Fragment = this.getFragment(env);
9457
+ const children = this.evaluateJSXChildren(node.children, env);
9458
+
9459
+ if (children.length === 0) {
9460
+ return createElement(Fragment, null);
9461
+ } else if (children.length === 1) {
9462
+ return createElement(Fragment, null, children[0]);
9463
+ }
9464
+ return createElement(Fragment, null, ...children);
9465
+ }
9466
+
9467
+ evaluateJSXOpeningElement(node, env) {
9468
+ const type = this.evaluateJSXElementName(node.name, env);
9469
+ const props = {};
9470
+
9471
+ for (const attr of node.attributes) {
9472
+ if (attr.type === 'JSXAttribute') {
9473
+ const name = attr.name.type === 'JSXIdentifier'
9474
+ ? attr.name.name
9475
+ : `${attr.name.namespace.name}:${attr.name.name.name}`;
9476
+ const value = attr.value
9477
+ ? this.evaluateJSXAttributeValue(attr.value, env)
9478
+ : true;
9479
+ props[name] = value;
9480
+ } else if (attr.type === 'JSXSpreadAttribute') {
9481
+ Object.assign(props, this.evaluate(attr.argument, env));
9482
+ }
9483
+ }
9484
+
9485
+ return { type, props: Object.keys(props).length > 0 ? props : null };
9486
+ }
9487
+
9488
+ evaluateJSXElementName(node, env) {
9489
+ if (node.type === 'JSXIdentifier') {
9490
+ const name = node.name;
9491
+ // Lowercase = intrinsic ('div'), Uppercase = component
9492
+ if (name[0] === name[0].toLowerCase()) {
9493
+ return name;
9494
+ }
9495
+ return env.get(name);
9496
+ } else if (node.type === 'JSXMemberExpression') {
9497
+ const object = this.evaluateJSXElementName(node.object, env);
9498
+ return object[node.property.name];
9499
+ } else if (node.type === 'JSXNamespacedName') {
9500
+ return `${node.namespace.name}:${node.name.name}`;
9501
+ }
9502
+ throw new Error(`Unknown JSX element name type: ${node.type}`);
9503
+ }
9504
+
9505
+ evaluateJSXAttributeValue(node, env) {
9506
+ if (node.type === 'Literal') return node.value;
9507
+ if (node.type === 'JSXExpressionContainer') {
9508
+ return this.evaluate(node.expression, env);
9509
+ }
9510
+ if (node.type === 'JSXElement') return this.evaluateJSXElement(node, env);
9511
+ if (node.type === 'JSXFragment') return this.evaluateJSXFragment(node, env);
9512
+ throw new Error(`Unknown JSX attribute value type: ${node.type}`);
9513
+ }
9514
+
9515
+ evaluateJSXChildren(children, env) {
9516
+ const result = [];
9517
+ for (const child of children) {
9518
+ if (child.type === 'JSXText') {
9519
+ const text = this.normalizeJSXText(child.value);
9520
+ if (text) result.push(text);
9521
+ } else if (child.type === 'JSXExpressionContainer') {
9522
+ if (child.expression.type !== 'JSXEmptyExpression') {
9523
+ const value = this.evaluate(child.expression, env);
9524
+ if (Array.isArray(value)) {
9525
+ result.push(...value);
9526
+ } else if (value !== null && value !== undefined && value !== false) {
9527
+ result.push(value);
9528
+ }
9529
+ }
9530
+ } else if (child.type === 'JSXElement') {
9531
+ result.push(this.evaluateJSXElement(child, env));
9532
+ } else if (child.type === 'JSXFragment') {
9533
+ result.push(this.evaluateJSXFragment(child, env));
9534
+ }
9535
+ }
9536
+ return result;
9537
+ }
9538
+
9539
+ normalizeJSXText(text) {
9540
+ // React's JSX whitespace normalization
9541
+ const lines = text.split('\n');
9542
+ const normalized = lines
9543
+ .map((line, i) => {
9544
+ let result = line;
9545
+ if (i === 0) result = result.trimStart();
9546
+ if (i === lines.length - 1) result = result.trimEnd();
9547
+ return result;
9548
+ })
9549
+ .filter(line => line.length > 0)
9550
+ .join(' ');
9551
+ return normalized || null;
9552
+ }
9553
+
9554
+ getCreateElement(env) {
9555
+ // Try React.createElement first
9556
+ try {
9557
+ const React = env.get('React');
9558
+ if (React && React.createElement) {
9559
+ return React.createElement.bind(React);
9560
+ }
9561
+ } catch (e) { /* not defined */ }
9562
+
9563
+ // Try standalone createElement
9564
+ try {
9565
+ return env.get('createElement');
9566
+ } catch (e) { /* not defined */ }
9567
+
9568
+ // Fallback: simple element factory for non-React usage
9569
+ return (type, props, ...children) => ({
9570
+ $$typeof: Symbol.for('react.element'),
9571
+ type,
9572
+ props: {
9573
+ ...props,
9574
+ children: children.length === 0 ? undefined : children.length === 1 ? children[0] : children
9575
+ },
9576
+ key: props?.key ?? null,
9577
+ ref: props?.ref ?? null
9578
+ });
9579
+ }
9580
+
9581
+ getFragment(env) {
9582
+ // Try React.Fragment
9583
+ try {
9584
+ const React = env.get('React');
9585
+ if (React && React.Fragment) {
9586
+ return React.Fragment;
9587
+ }
9588
+ } catch (e) { /* not defined */ }
9589
+
9590
+ // Try standalone Fragment
9591
+ try {
9592
+ return env.get('Fragment');
9593
+ } catch (e) { /* not defined */ }
9594
+
9595
+ // Fallback: Symbol for fragments
9596
+ return Symbol.for('react.fragment');
9597
+ }
9598
+
9599
+ // ===== Async JSX Support =====
9600
+
9601
+ async evaluateJSXElementAsync(node, env) {
9602
+ const checkpointPromise = this._getCheckpointPromise(node, env);
9603
+ if (checkpointPromise) await checkpointPromise;
9604
+
9605
+ const createElement = this.getCreateElement(env);
9606
+ const { type, props } = await this.evaluateJSXOpeningElementAsync(node.openingElement, env);
9607
+ const children = await this.evaluateJSXChildrenAsync(node.children, env);
9608
+
9609
+ if (children.length === 0) {
9610
+ return createElement(type, props);
9611
+ } else if (children.length === 1) {
9612
+ return createElement(type, props, children[0]);
9613
+ }
9614
+ return createElement(type, props, ...children);
9615
+ }
9616
+
9617
+ async evaluateJSXFragmentAsync(node, env) {
9618
+ const checkpointPromise = this._getCheckpointPromise(node, env);
9619
+ if (checkpointPromise) await checkpointPromise;
9620
+
9621
+ const createElement = this.getCreateElement(env);
9622
+ const Fragment = this.getFragment(env);
9623
+ const children = await this.evaluateJSXChildrenAsync(node.children, env);
9624
+
9625
+ if (children.length === 0) {
9626
+ return createElement(Fragment, null);
9627
+ } else if (children.length === 1) {
9628
+ return createElement(Fragment, null, children[0]);
9629
+ }
9630
+ return createElement(Fragment, null, ...children);
9631
+ }
9632
+
9633
+ async evaluateJSXOpeningElementAsync(node, env) {
9634
+ const type = this.evaluateJSXElementName(node.name, env);
9635
+ const props = {};
9636
+
9637
+ for (const attr of node.attributes) {
9638
+ if (attr.type === 'JSXAttribute') {
9639
+ const name = attr.name.type === 'JSXIdentifier'
9640
+ ? attr.name.name
9641
+ : `${attr.name.namespace.name}:${attr.name.name.name}`;
9642
+ const value = attr.value
9643
+ ? await this.evaluateJSXAttributeValueAsync(attr.value, env)
9644
+ : true;
9645
+ props[name] = value;
9646
+ } else if (attr.type === 'JSXSpreadAttribute') {
9647
+ Object.assign(props, await this.evaluateAsync(attr.argument, env));
9648
+ }
9649
+ }
9650
+
9651
+ return { type, props: Object.keys(props).length > 0 ? props : null };
9652
+ }
9653
+
9654
+ async evaluateJSXAttributeValueAsync(node, env) {
9655
+ if (node.type === 'Literal') return node.value;
9656
+ if (node.type === 'JSXExpressionContainer') {
9657
+ return await this.evaluateAsync(node.expression, env);
9658
+ }
9659
+ if (node.type === 'JSXElement') return await this.evaluateJSXElementAsync(node, env);
9660
+ if (node.type === 'JSXFragment') return await this.evaluateJSXFragmentAsync(node, env);
9661
+ throw new Error(`Unknown JSX attribute value type: ${node.type}`);
9662
+ }
9663
+
9664
+ async evaluateJSXChildrenAsync(children, env) {
9665
+ const result = [];
9666
+ for (const child of children) {
9667
+ if (child.type === 'JSXText') {
9668
+ const text = this.normalizeJSXText(child.value);
9669
+ if (text) result.push(text);
9670
+ } else if (child.type === 'JSXExpressionContainer') {
9671
+ if (child.expression.type !== 'JSXEmptyExpression') {
9672
+ const value = await this.evaluateAsync(child.expression, env);
9673
+ if (Array.isArray(value)) {
9674
+ result.push(...value);
9675
+ } else if (value !== null && value !== undefined && value !== false) {
9676
+ result.push(value);
9677
+ }
9678
+ }
9679
+ } else if (child.type === 'JSXElement') {
9680
+ result.push(await this.evaluateJSXElementAsync(child, env));
9681
+ } else if (child.type === 'JSXFragment') {
9682
+ result.push(await this.evaluateJSXFragmentAsync(child, env));
9683
+ }
9684
+ }
9685
+ return result;
9686
+ }
8609
9687
  }
8610
9688
 
8611
9689
  // Built-in global objects and functions
@@ -8724,6 +9802,20 @@ function createGlobalEnvironment(env) {
8724
9802
  env.define('SyntaxError', SyntaxError);
8725
9803
  env.define('RangeError', RangeError);
8726
9804
 
9805
+ // JSX Runtime Support
9806
+ env.define('createElement', (type, props, ...children) => ({
9807
+ $$typeof: Symbol.for('react.element'),
9808
+ type,
9809
+ props: {
9810
+ ...props,
9811
+ children: children.length === 0 ? undefined : children.length === 1 ? children[0] : children
9812
+ },
9813
+ key: props?.key ?? null,
9814
+ ref: props?.ref ?? null
9815
+ }));
9816
+
9817
+ env.define('Fragment', Symbol.for('react.fragment'));
9818
+
8727
9819
  // Global console functions (shortcuts for console.log/warn/error)
8728
9820
  env.define('log', (...args) => {
8729
9821
  console.log(...args);
@@ -9228,7 +10320,8 @@ class WangInterpreter {
9228
10320
 
9229
10321
  // Prepare execution options
9230
10322
  const options = {
9231
- moduleResolver: this.moduleResolver
10323
+ moduleResolver: this.moduleResolver,
10324
+ executionController: userOptions.executionController
9232
10325
  // sourceType will be auto-detected from code
9233
10326
  };
9234
10327
 
@@ -9327,6 +10420,219 @@ class InMemoryModuleResolver {
9327
10420
  }
9328
10421
  }
9329
10422
 
10423
+ /**
10424
+ * ExecutionController - Controls and monitors interpreter execution
10425
+ *
10426
+ * Provides pause/resume/abort capabilities and execution status introspection.
10427
+ * Works with async evaluation only - sync evaluation can only abort.
10428
+ */
10429
+ class ExecutionController {
10430
+ constructor() {
10431
+ this.state = 'idle'; // 'idle' | 'running' | 'paused' | 'aborted' | 'completed'
10432
+ this.pauseRequested = false;
10433
+ this.abortRequested = false;
10434
+
10435
+ // Debug info
10436
+ this.stepCount = 0;
10437
+ this.currentNode = null;
10438
+ this.callStack = [];
10439
+ this.currentEnv = null;
10440
+
10441
+ this._resolveResume = null;
10442
+ }
10443
+
10444
+ // --- Control methods (called by user) ---
10445
+
10446
+ /**
10447
+ * Request pause at next checkpoint. Only works during async evaluation.
10448
+ */
10449
+ pause() {
10450
+ if (this.state === 'running') {
10451
+ this.pauseRequested = true;
10452
+ }
10453
+ }
10454
+
10455
+ /**
10456
+ * Resume execution after pause.
10457
+ */
10458
+ resume() {
10459
+ if (this.state === 'paused' && this._resolveResume) {
10460
+ this.pauseRequested = false;
10461
+ this._resolveResume();
10462
+ this._resolveResume = null;
10463
+ }
10464
+ }
10465
+
10466
+ /**
10467
+ * Abort execution. Works for both sync and async evaluation.
10468
+ * If paused, will resume and then abort.
10469
+ */
10470
+ abort() {
10471
+ this.abortRequested = true;
10472
+ // Also resume if paused to allow abort to take effect
10473
+ if (this._resolveResume) {
10474
+ this._resolveResume();
10475
+ this._resolveResume = null;
10476
+ }
10477
+ }
10478
+
10479
+ // --- Status (called by user) ---
10480
+
10481
+ /**
10482
+ * Get current execution status with full debug information.
10483
+ * @returns {Object} Status object with state, stepCount, currentNode, callStack, and variables
10484
+ */
10485
+ getStatus() {
10486
+ return {
10487
+ state: this.state,
10488
+ stepCount: this.stepCount,
10489
+ currentNode: this.currentNode?.type || null,
10490
+ callStack: [...this.callStack],
10491
+ variables: this._getEnvironmentVariables()
10492
+ };
10493
+ }
10494
+
10495
+ /**
10496
+ * Check if abort has been requested.
10497
+ * Compatible with AbortSignal interface.
10498
+ */
10499
+ get aborted() {
10500
+ return this.abortRequested;
10501
+ }
10502
+
10503
+ // --- Internal methods (called by interpreter) ---
10504
+
10505
+ /**
10506
+ * Mark execution as started. Called by execute().
10507
+ * @internal
10508
+ */
10509
+ _start() {
10510
+ this.state = 'running';
10511
+ this.stepCount = 0;
10512
+ this.currentNode = null;
10513
+ this.callStack = [];
10514
+ this.pauseRequested = false;
10515
+ // Note: don't reset abortRequested - allow pre-abort
10516
+ }
10517
+
10518
+ /**
10519
+ * Mark execution as completed. Called by execute().
10520
+ * @internal
10521
+ */
10522
+ _complete() {
10523
+ this.state = 'completed';
10524
+ }
10525
+
10526
+ /**
10527
+ * Push a function call onto the call stack.
10528
+ * @internal
10529
+ */
10530
+ _pushCall(name) {
10531
+ this.callStack.push(name);
10532
+ }
10533
+
10534
+ /**
10535
+ * Pop a function call from the call stack.
10536
+ * @internal
10537
+ */
10538
+ _popCall() {
10539
+ this.callStack.pop();
10540
+ }
10541
+
10542
+ /**
10543
+ * Set the current environment for variable introspection.
10544
+ * @internal
10545
+ */
10546
+ _setEnv(env) {
10547
+ this.currentEnv = env;
10548
+ }
10549
+
10550
+ /**
10551
+ * Async checkpoint - yields if paused, throws if aborted.
10552
+ * Called at coarse granularity points (loops, function calls).
10553
+ * @internal
10554
+ */
10555
+ async _checkpoint(node) {
10556
+ this.stepCount++;
10557
+ this.currentNode = node;
10558
+
10559
+ if (this.abortRequested) {
10560
+ this.state = 'aborted';
10561
+ const error = new Error('The operation was aborted');
10562
+ error.name = 'AbortError';
10563
+ throw error;
10564
+ }
10565
+
10566
+ if (this.pauseRequested && this.state === 'running') {
10567
+ this.state = 'paused';
10568
+ await new Promise(resolve => { this._resolveResume = resolve; });
10569
+ this.state = 'running';
10570
+
10571
+ // Check abort after resume (user may have called abort while paused)
10572
+ if (this.abortRequested) {
10573
+ this.state = 'aborted';
10574
+ const error = new Error('The operation was aborted');
10575
+ error.name = 'AbortError';
10576
+ throw error;
10577
+ }
10578
+ }
10579
+ }
10580
+
10581
+ /**
10582
+ * Sync abort check - only throws if aborted, cannot pause.
10583
+ * Used in sync evaluate() path.
10584
+ * @internal
10585
+ */
10586
+ _checkAbortSync() {
10587
+ if (this.abortRequested) {
10588
+ this.state = 'aborted';
10589
+ const error = new Error('The operation was aborted');
10590
+ error.name = 'AbortError';
10591
+ throw error;
10592
+ }
10593
+ }
10594
+
10595
+ /**
10596
+ * Get all variables from current environment chain.
10597
+ * @internal
10598
+ */
10599
+ _getEnvironmentVariables() {
10600
+ if (!this.currentEnv) return {};
10601
+ const vars = {};
10602
+ let env = this.currentEnv;
10603
+ while (env) {
10604
+ if (env.vars) {
10605
+ for (const [key, value] of env.vars) {
10606
+ if (!(key in vars)) {
10607
+ vars[key] = this._serializeValue(value);
10608
+ }
10609
+ }
10610
+ }
10611
+ env = env.parent;
10612
+ }
10613
+ return vars;
10614
+ }
10615
+
10616
+ /**
10617
+ * Serialize a value for status reporting.
10618
+ * @internal
10619
+ */
10620
+ _serializeValue(value) {
10621
+ if (value === undefined) return { type: 'undefined' };
10622
+ if (value === null) return { type: 'null' };
10623
+ if (typeof value === 'function' || (value && value.__isFunction)) {
10624
+ return { type: 'function', name: value.name || 'anonymous' };
10625
+ }
10626
+ if (Array.isArray(value)) {
10627
+ return { type: 'array', length: value.length };
10628
+ }
10629
+ if (typeof value === 'object') {
10630
+ return { type: 'object', preview: Object.keys(value).slice(0, 5) };
10631
+ }
10632
+ return { type: typeof value, value };
10633
+ }
10634
+ }
10635
+
9330
10636
  // Use bundled Acorn parser for zero runtime dependencies
9331
10637
 
9332
10638
  // Helper to detect if code contains module syntax or top-level await
@@ -9359,7 +10665,7 @@ function parse(code, options = {}) {
9359
10665
 
9360
10666
  // Parse with Acorn
9361
10667
  try {
9362
- return parse$1(code, {
10668
+ return jsxParse(code, {
9363
10669
  ecmaVersion: 2022, // Support ES2022 features (including top-level await)
9364
10670
  sourceType: sourceType,
9365
10671
  locations: true, // Track source locations for better error messages
@@ -9423,34 +10729,59 @@ function containsTopLevelAwait(node) {
9423
10729
  }
9424
10730
 
9425
10731
  async function execute(code, env = null, options = {}) {
9426
- // Parse the code
9427
- const ast = parse(code, options);
10732
+ // Get execution controller if provided
10733
+ const controller = options.executionController;
9428
10734
 
9429
- // Create global environment if not provided
9430
- if (!env) {
9431
- env = createGlobalEnvironment(new Environment());
10735
+ // Mark execution as starting
10736
+ if (controller) {
10737
+ controller._start();
9432
10738
  }
9433
10739
 
9434
- // Create interpreter with module resolver and abort signal if provided
9435
- const interpreter = new Interpreter(env, {
9436
- moduleResolver: options.moduleResolver,
9437
- abortSignal: options.abortSignal
9438
- });
10740
+ try {
10741
+ // Parse the code
10742
+ const ast = parse(code, options);
9439
10743
 
9440
- // Use async evaluation if:
9441
- // 1. Explicitly requested module mode
9442
- // 2. AST contains import/export declarations
9443
- // 3. Code contains top-level await
9444
- const needsAsync = options.sourceType === 'module' ||
9445
- containsModuleDeclarations(ast) ||
9446
- containsTopLevelAwait(ast);
9447
-
9448
- if (needsAsync) {
9449
- const result = await interpreter.evaluateAsync(ast, env);
9450
- return result instanceof ReturnValue ? result.value : result;
9451
- } else {
9452
- const result = interpreter.evaluate(ast, env);
9453
- return result instanceof ReturnValue ? result.value : result;
10744
+ // Create global environment if not provided
10745
+ if (!env) {
10746
+ env = createGlobalEnvironment(new Environment());
10747
+ }
10748
+
10749
+ // Create interpreter with module resolver, abort signal, and execution controller
10750
+ const interpreter = new Interpreter(env, {
10751
+ moduleResolver: options.moduleResolver,
10752
+ abortSignal: options.abortSignal,
10753
+ executionController: controller
10754
+ });
10755
+
10756
+ // Use async evaluation if:
10757
+ // 1. Explicitly requested module mode
10758
+ // 2. AST contains import/export declarations
10759
+ // 3. Code contains top-level await
10760
+ // 4. Execution controller provided (needs async for pause/resume)
10761
+ const needsAsync = options.sourceType === 'module' ||
10762
+ containsModuleDeclarations(ast) ||
10763
+ containsTopLevelAwait(ast) ||
10764
+ controller != null;
10765
+
10766
+ if (needsAsync) {
10767
+ const result = await interpreter.evaluateAsync(ast, env);
10768
+ if (controller) {
10769
+ controller._complete();
10770
+ }
10771
+ return result instanceof ReturnValue ? result.value : result;
10772
+ } else {
10773
+ const result = interpreter.evaluate(ast, env);
10774
+ if (controller) {
10775
+ controller._complete();
10776
+ }
10777
+ return result instanceof ReturnValue ? result.value : result;
10778
+ }
10779
+ } catch (e) {
10780
+ // Mark as aborted if that's the error type
10781
+ if (controller && e.name === 'AbortError') {
10782
+ controller.state = 'aborted';
10783
+ }
10784
+ throw e;
9454
10785
  }
9455
10786
  }
9456
10787
 
@@ -9503,4 +10834,4 @@ class ModuleResolver {
9503
10834
  * @property {any} [metadata] - Optional metadata about the module
9504
10835
  */
9505
10836
 
9506
- export { Environment, InMemoryModuleResolver, Interpreter, ModuleResolver, WangInterpreter, createEnvironment, execute, isTopLevelAwait, parse };
10837
+ export { Environment, ExecutionController, InMemoryModuleResolver, Interpreter, ModuleResolver, WangInterpreter, createEnvironment, execute, isTopLevelAwait, parse };