jslike 1.5.0 → 1.6.1
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/interpreter.js +312 -20
- package/dist/esm/parser.js +781 -3
- package/dist/esm/runtime/builtins.js +14 -0
- package/dist/index.cjs +931 -20
- package/dist/index.d.cts +1070 -30
- package/dist/index.d.ts +1070 -30
- package/dist/index.js +931 -20
- package/dist/validator/index.cjs +669 -5
- package/dist/validator/index.js +669 -5
- package/package.json +5 -2
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
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
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
|
+
}
|
|
6518
|
+
|
|
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 ? ">" : "}") + "` 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());
|
|
6220
6953
|
|
|
6221
|
-
|
|
6222
|
-
|
|
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
|
|
@@ -7067,6 +7801,26 @@ class Interpreter {
|
|
|
7067
7801
|
return this.evaluateClassExpression(node, env);
|
|
7068
7802
|
}
|
|
7069
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
|
+
|
|
7070
7824
|
// Only leaf nodes should fall through to sync evaluate
|
|
7071
7825
|
// These have no sub-expressions that could contain await
|
|
7072
7826
|
if (['Literal', 'Identifier', 'BreakStatement', 'ContinueStatement',
|
|
@@ -7241,6 +7995,22 @@ class Interpreter {
|
|
|
7241
7995
|
case 'Property':
|
|
7242
7996
|
return this.evaluateProperty(node, env);
|
|
7243
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
|
+
|
|
7244
8014
|
default:
|
|
7245
8015
|
throw new Error(`Unknown node type: ${node.type}`);
|
|
7246
8016
|
}
|
|
@@ -8066,29 +8836,36 @@ class Interpreter {
|
|
|
8066
8836
|
throw new Error(`Cannot find module '${modulePath}'`);
|
|
8067
8837
|
}
|
|
8068
8838
|
|
|
8069
|
-
// Handle
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
|
|
8073
|
-
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
|
|
8078
|
-
|
|
8839
|
+
// Handle native module exports (for libraries like React)
|
|
8840
|
+
// If resolution has 'exports' property, use it directly without parsing
|
|
8841
|
+
if (resolution.exports) {
|
|
8842
|
+
moduleExports = resolution.exports;
|
|
8843
|
+
this.moduleCache.set(modulePath, moduleExports);
|
|
8844
|
+
} else {
|
|
8845
|
+
// Handle both old (string) and new (ModuleResolution) formats
|
|
8846
|
+
const moduleCode = typeof resolution === 'string' ? resolution : resolution.code;
|
|
8847
|
+
|
|
8848
|
+
// Parse and execute module in its own environment
|
|
8849
|
+
const moduleAst = jsxParse(moduleCode, {
|
|
8850
|
+
ecmaVersion: 2020,
|
|
8851
|
+
sourceType: 'module',
|
|
8852
|
+
locations: false
|
|
8853
|
+
});
|
|
8854
|
+
const moduleEnv = new Environment(this.globalEnv);
|
|
8079
8855
|
|
|
8080
|
-
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
|
|
8084
|
-
|
|
8856
|
+
// Create a new interpreter for the module with shared module cache
|
|
8857
|
+
const moduleInterpreter = new Interpreter(this.globalEnv, {
|
|
8858
|
+
moduleResolver: this.moduleResolver
|
|
8859
|
+
});
|
|
8860
|
+
moduleInterpreter.moduleCache = this.moduleCache; // Share cache
|
|
8085
8861
|
|
|
8086
|
-
|
|
8087
|
-
|
|
8862
|
+
// Execute module and collect exports
|
|
8863
|
+
await moduleInterpreter.evaluateAsync(moduleAst, moduleEnv);
|
|
8088
8864
|
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8865
|
+
// Cache the module exports
|
|
8866
|
+
moduleExports = moduleInterpreter.moduleExports;
|
|
8867
|
+
this.moduleCache.set(modulePath, moduleExports);
|
|
8868
|
+
}
|
|
8092
8869
|
}
|
|
8093
8870
|
|
|
8094
8871
|
// Import specified bindings into current environment
|
|
@@ -8665,6 +9442,255 @@ class Interpreter {
|
|
|
8665
9442
|
// Already handled in evaluateObjectExpression
|
|
8666
9443
|
return undefined;
|
|
8667
9444
|
}
|
|
9445
|
+
|
|
9446
|
+
// ===== JSX Support =====
|
|
9447
|
+
|
|
9448
|
+
evaluateJSXElement(node, env) {
|
|
9449
|
+
const createElement = this.getCreateElement(env);
|
|
9450
|
+
const { type, props } = this.evaluateJSXOpeningElement(node.openingElement, env);
|
|
9451
|
+
const children = this.evaluateJSXChildren(node.children, env);
|
|
9452
|
+
|
|
9453
|
+
if (children.length === 0) {
|
|
9454
|
+
return createElement(type, props);
|
|
9455
|
+
} else if (children.length === 1) {
|
|
9456
|
+
return createElement(type, props, children[0]);
|
|
9457
|
+
}
|
|
9458
|
+
return createElement(type, props, ...children);
|
|
9459
|
+
}
|
|
9460
|
+
|
|
9461
|
+
evaluateJSXFragment(node, env) {
|
|
9462
|
+
const createElement = this.getCreateElement(env);
|
|
9463
|
+
const Fragment = this.getFragment(env);
|
|
9464
|
+
const children = this.evaluateJSXChildren(node.children, env);
|
|
9465
|
+
|
|
9466
|
+
if (children.length === 0) {
|
|
9467
|
+
return createElement(Fragment, null);
|
|
9468
|
+
} else if (children.length === 1) {
|
|
9469
|
+
return createElement(Fragment, null, children[0]);
|
|
9470
|
+
}
|
|
9471
|
+
return createElement(Fragment, null, ...children);
|
|
9472
|
+
}
|
|
9473
|
+
|
|
9474
|
+
evaluateJSXOpeningElement(node, env) {
|
|
9475
|
+
const type = this.evaluateJSXElementName(node.name, env);
|
|
9476
|
+
const props = {};
|
|
9477
|
+
|
|
9478
|
+
for (const attr of node.attributes) {
|
|
9479
|
+
if (attr.type === 'JSXAttribute') {
|
|
9480
|
+
const name = attr.name.type === 'JSXIdentifier'
|
|
9481
|
+
? attr.name.name
|
|
9482
|
+
: `${attr.name.namespace.name}:${attr.name.name.name}`;
|
|
9483
|
+
const value = attr.value
|
|
9484
|
+
? this.evaluateJSXAttributeValue(attr.value, env)
|
|
9485
|
+
: true;
|
|
9486
|
+
props[name] = value;
|
|
9487
|
+
} else if (attr.type === 'JSXSpreadAttribute') {
|
|
9488
|
+
Object.assign(props, this.evaluate(attr.argument, env));
|
|
9489
|
+
}
|
|
9490
|
+
}
|
|
9491
|
+
|
|
9492
|
+
return { type, props: Object.keys(props).length > 0 ? props : null };
|
|
9493
|
+
}
|
|
9494
|
+
|
|
9495
|
+
evaluateJSXElementName(node, env) {
|
|
9496
|
+
if (node.type === 'JSXIdentifier') {
|
|
9497
|
+
const name = node.name;
|
|
9498
|
+
// Lowercase = intrinsic ('div'), Uppercase = component
|
|
9499
|
+
if (name[0] === name[0].toLowerCase()) {
|
|
9500
|
+
return name;
|
|
9501
|
+
}
|
|
9502
|
+
return env.get(name);
|
|
9503
|
+
} else if (node.type === 'JSXMemberExpression') {
|
|
9504
|
+
const object = this.evaluateJSXElementName(node.object, env);
|
|
9505
|
+
return object[node.property.name];
|
|
9506
|
+
} else if (node.type === 'JSXNamespacedName') {
|
|
9507
|
+
return `${node.namespace.name}:${node.name.name}`;
|
|
9508
|
+
}
|
|
9509
|
+
throw new Error(`Unknown JSX element name type: ${node.type}`);
|
|
9510
|
+
}
|
|
9511
|
+
|
|
9512
|
+
evaluateJSXAttributeValue(node, env) {
|
|
9513
|
+
if (node.type === 'Literal') return node.value;
|
|
9514
|
+
if (node.type === 'JSXExpressionContainer') {
|
|
9515
|
+
return this.evaluate(node.expression, env);
|
|
9516
|
+
}
|
|
9517
|
+
if (node.type === 'JSXElement') return this.evaluateJSXElement(node, env);
|
|
9518
|
+
if (node.type === 'JSXFragment') return this.evaluateJSXFragment(node, env);
|
|
9519
|
+
throw new Error(`Unknown JSX attribute value type: ${node.type}`);
|
|
9520
|
+
}
|
|
9521
|
+
|
|
9522
|
+
evaluateJSXChildren(children, env) {
|
|
9523
|
+
const result = [];
|
|
9524
|
+
for (const child of children) {
|
|
9525
|
+
if (child.type === 'JSXText') {
|
|
9526
|
+
const text = this.normalizeJSXText(child.value);
|
|
9527
|
+
if (text) result.push(text);
|
|
9528
|
+
} else if (child.type === 'JSXExpressionContainer') {
|
|
9529
|
+
if (child.expression.type !== 'JSXEmptyExpression') {
|
|
9530
|
+
const value = this.evaluate(child.expression, env);
|
|
9531
|
+
if (Array.isArray(value)) {
|
|
9532
|
+
result.push(...value);
|
|
9533
|
+
} else if (value !== null && value !== undefined && value !== false) {
|
|
9534
|
+
result.push(value);
|
|
9535
|
+
}
|
|
9536
|
+
}
|
|
9537
|
+
} else if (child.type === 'JSXElement') {
|
|
9538
|
+
result.push(this.evaluateJSXElement(child, env));
|
|
9539
|
+
} else if (child.type === 'JSXFragment') {
|
|
9540
|
+
result.push(this.evaluateJSXFragment(child, env));
|
|
9541
|
+
}
|
|
9542
|
+
}
|
|
9543
|
+
return result;
|
|
9544
|
+
}
|
|
9545
|
+
|
|
9546
|
+
normalizeJSXText(text) {
|
|
9547
|
+
// React's JSX whitespace normalization
|
|
9548
|
+
const lines = text.split('\n');
|
|
9549
|
+
const normalized = lines
|
|
9550
|
+
.map((line, i) => {
|
|
9551
|
+
let result = line;
|
|
9552
|
+
if (i === 0) result = result.trimStart();
|
|
9553
|
+
if (i === lines.length - 1) result = result.trimEnd();
|
|
9554
|
+
return result;
|
|
9555
|
+
})
|
|
9556
|
+
.filter(line => line.length > 0)
|
|
9557
|
+
.join(' ');
|
|
9558
|
+
return normalized || null;
|
|
9559
|
+
}
|
|
9560
|
+
|
|
9561
|
+
getCreateElement(env) {
|
|
9562
|
+
// Try React.createElement first
|
|
9563
|
+
try {
|
|
9564
|
+
const React = env.get('React');
|
|
9565
|
+
if (React && React.createElement) {
|
|
9566
|
+
return React.createElement.bind(React);
|
|
9567
|
+
}
|
|
9568
|
+
} catch (e) { /* not defined */ }
|
|
9569
|
+
|
|
9570
|
+
// Try standalone createElement
|
|
9571
|
+
try {
|
|
9572
|
+
return env.get('createElement');
|
|
9573
|
+
} catch (e) { /* not defined */ }
|
|
9574
|
+
|
|
9575
|
+
// Fallback: simple element factory for non-React usage
|
|
9576
|
+
return (type, props, ...children) => ({
|
|
9577
|
+
$$typeof: Symbol.for('react.element'),
|
|
9578
|
+
type,
|
|
9579
|
+
props: {
|
|
9580
|
+
...props,
|
|
9581
|
+
children: children.length === 0 ? undefined : children.length === 1 ? children[0] : children
|
|
9582
|
+
},
|
|
9583
|
+
key: props?.key ?? null,
|
|
9584
|
+
ref: props?.ref ?? null
|
|
9585
|
+
});
|
|
9586
|
+
}
|
|
9587
|
+
|
|
9588
|
+
getFragment(env) {
|
|
9589
|
+
// Try React.Fragment
|
|
9590
|
+
try {
|
|
9591
|
+
const React = env.get('React');
|
|
9592
|
+
if (React && React.Fragment) {
|
|
9593
|
+
return React.Fragment;
|
|
9594
|
+
}
|
|
9595
|
+
} catch (e) { /* not defined */ }
|
|
9596
|
+
|
|
9597
|
+
// Try standalone Fragment
|
|
9598
|
+
try {
|
|
9599
|
+
return env.get('Fragment');
|
|
9600
|
+
} catch (e) { /* not defined */ }
|
|
9601
|
+
|
|
9602
|
+
// Fallback: Symbol for fragments
|
|
9603
|
+
return Symbol.for('react.fragment');
|
|
9604
|
+
}
|
|
9605
|
+
|
|
9606
|
+
// ===== Async JSX Support =====
|
|
9607
|
+
|
|
9608
|
+
async evaluateJSXElementAsync(node, env) {
|
|
9609
|
+
const checkpointPromise = this._getCheckpointPromise(node, env);
|
|
9610
|
+
if (checkpointPromise) await checkpointPromise;
|
|
9611
|
+
|
|
9612
|
+
const createElement = this.getCreateElement(env);
|
|
9613
|
+
const { type, props } = await this.evaluateJSXOpeningElementAsync(node.openingElement, env);
|
|
9614
|
+
const children = await this.evaluateJSXChildrenAsync(node.children, env);
|
|
9615
|
+
|
|
9616
|
+
if (children.length === 0) {
|
|
9617
|
+
return createElement(type, props);
|
|
9618
|
+
} else if (children.length === 1) {
|
|
9619
|
+
return createElement(type, props, children[0]);
|
|
9620
|
+
}
|
|
9621
|
+
return createElement(type, props, ...children);
|
|
9622
|
+
}
|
|
9623
|
+
|
|
9624
|
+
async evaluateJSXFragmentAsync(node, env) {
|
|
9625
|
+
const checkpointPromise = this._getCheckpointPromise(node, env);
|
|
9626
|
+
if (checkpointPromise) await checkpointPromise;
|
|
9627
|
+
|
|
9628
|
+
const createElement = this.getCreateElement(env);
|
|
9629
|
+
const Fragment = this.getFragment(env);
|
|
9630
|
+
const children = await this.evaluateJSXChildrenAsync(node.children, env);
|
|
9631
|
+
|
|
9632
|
+
if (children.length === 0) {
|
|
9633
|
+
return createElement(Fragment, null);
|
|
9634
|
+
} else if (children.length === 1) {
|
|
9635
|
+
return createElement(Fragment, null, children[0]);
|
|
9636
|
+
}
|
|
9637
|
+
return createElement(Fragment, null, ...children);
|
|
9638
|
+
}
|
|
9639
|
+
|
|
9640
|
+
async evaluateJSXOpeningElementAsync(node, env) {
|
|
9641
|
+
const type = this.evaluateJSXElementName(node.name, env);
|
|
9642
|
+
const props = {};
|
|
9643
|
+
|
|
9644
|
+
for (const attr of node.attributes) {
|
|
9645
|
+
if (attr.type === 'JSXAttribute') {
|
|
9646
|
+
const name = attr.name.type === 'JSXIdentifier'
|
|
9647
|
+
? attr.name.name
|
|
9648
|
+
: `${attr.name.namespace.name}:${attr.name.name.name}`;
|
|
9649
|
+
const value = attr.value
|
|
9650
|
+
? await this.evaluateJSXAttributeValueAsync(attr.value, env)
|
|
9651
|
+
: true;
|
|
9652
|
+
props[name] = value;
|
|
9653
|
+
} else if (attr.type === 'JSXSpreadAttribute') {
|
|
9654
|
+
Object.assign(props, await this.evaluateAsync(attr.argument, env));
|
|
9655
|
+
}
|
|
9656
|
+
}
|
|
9657
|
+
|
|
9658
|
+
return { type, props: Object.keys(props).length > 0 ? props : null };
|
|
9659
|
+
}
|
|
9660
|
+
|
|
9661
|
+
async evaluateJSXAttributeValueAsync(node, env) {
|
|
9662
|
+
if (node.type === 'Literal') return node.value;
|
|
9663
|
+
if (node.type === 'JSXExpressionContainer') {
|
|
9664
|
+
return await this.evaluateAsync(node.expression, env);
|
|
9665
|
+
}
|
|
9666
|
+
if (node.type === 'JSXElement') return await this.evaluateJSXElementAsync(node, env);
|
|
9667
|
+
if (node.type === 'JSXFragment') return await this.evaluateJSXFragmentAsync(node, env);
|
|
9668
|
+
throw new Error(`Unknown JSX attribute value type: ${node.type}`);
|
|
9669
|
+
}
|
|
9670
|
+
|
|
9671
|
+
async evaluateJSXChildrenAsync(children, env) {
|
|
9672
|
+
const result = [];
|
|
9673
|
+
for (const child of children) {
|
|
9674
|
+
if (child.type === 'JSXText') {
|
|
9675
|
+
const text = this.normalizeJSXText(child.value);
|
|
9676
|
+
if (text) result.push(text);
|
|
9677
|
+
} else if (child.type === 'JSXExpressionContainer') {
|
|
9678
|
+
if (child.expression.type !== 'JSXEmptyExpression') {
|
|
9679
|
+
const value = await this.evaluateAsync(child.expression, env);
|
|
9680
|
+
if (Array.isArray(value)) {
|
|
9681
|
+
result.push(...value);
|
|
9682
|
+
} else if (value !== null && value !== undefined && value !== false) {
|
|
9683
|
+
result.push(value);
|
|
9684
|
+
}
|
|
9685
|
+
}
|
|
9686
|
+
} else if (child.type === 'JSXElement') {
|
|
9687
|
+
result.push(await this.evaluateJSXElementAsync(child, env));
|
|
9688
|
+
} else if (child.type === 'JSXFragment') {
|
|
9689
|
+
result.push(await this.evaluateJSXFragmentAsync(child, env));
|
|
9690
|
+
}
|
|
9691
|
+
}
|
|
9692
|
+
return result;
|
|
9693
|
+
}
|
|
8668
9694
|
}
|
|
8669
9695
|
|
|
8670
9696
|
// Built-in global objects and functions
|
|
@@ -8783,6 +9809,20 @@ function createGlobalEnvironment(env) {
|
|
|
8783
9809
|
env.define('SyntaxError', SyntaxError);
|
|
8784
9810
|
env.define('RangeError', RangeError);
|
|
8785
9811
|
|
|
9812
|
+
// JSX Runtime Support
|
|
9813
|
+
env.define('createElement', (type, props, ...children) => ({
|
|
9814
|
+
$$typeof: Symbol.for('react.element'),
|
|
9815
|
+
type,
|
|
9816
|
+
props: {
|
|
9817
|
+
...props,
|
|
9818
|
+
children: children.length === 0 ? undefined : children.length === 1 ? children[0] : children
|
|
9819
|
+
},
|
|
9820
|
+
key: props?.key ?? null,
|
|
9821
|
+
ref: props?.ref ?? null
|
|
9822
|
+
}));
|
|
9823
|
+
|
|
9824
|
+
env.define('Fragment', Symbol.for('react.fragment'));
|
|
9825
|
+
|
|
8786
9826
|
// Global console functions (shortcuts for console.log/warn/error)
|
|
8787
9827
|
env.define('log', (...args) => {
|
|
8788
9828
|
console.log(...args);
|
|
@@ -9632,7 +10672,7 @@ function parse(code, options = {}) {
|
|
|
9632
10672
|
|
|
9633
10673
|
// Parse with Acorn
|
|
9634
10674
|
try {
|
|
9635
|
-
return
|
|
10675
|
+
return jsxParse(code, {
|
|
9636
10676
|
ecmaVersion: 2022, // Support ES2022 features (including top-level await)
|
|
9637
10677
|
sourceType: sourceType,
|
|
9638
10678
|
locations: true, // Track source locations for better error messages
|