@ibyar/expressions 0.5.6 → 0.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.
Files changed (97) hide show
  1. package/api/abstract.js +5 -0
  2. package/api/abstract.js.map +1 -1
  3. package/api/class/class.d.ts +28 -13
  4. package/api/class/class.js +46 -41
  5. package/api/class/class.js.map +1 -1
  6. package/api/computing/return.d.ts +4 -0
  7. package/api/computing/return.js +5 -0
  8. package/api/computing/return.js.map +1 -1
  9. package/api/computing/throw.d.ts +4 -0
  10. package/api/computing/throw.js +4 -0
  11. package/api/computing/throw.js.map +1 -1
  12. package/api/definition/bind.d.ts +6 -0
  13. package/api/definition/bind.js +6 -0
  14. package/api/definition/bind.js.map +1 -1
  15. package/api/definition/function.js +6 -5
  16. package/api/definition/function.js.map +1 -1
  17. package/api/definition/member.js.map +1 -1
  18. package/api/definition/object.js +1 -1
  19. package/api/definition/object.js.map +1 -1
  20. package/api/definition/values.d.ts +12 -3
  21. package/api/definition/values.js +25 -4
  22. package/api/definition/values.js.map +1 -1
  23. package/api/deserialize/deserialize.d.ts +5 -0
  24. package/api/deserialize/deserialize.js +5 -0
  25. package/api/deserialize/deserialize.js.map +1 -1
  26. package/api/expression.d.ts +151 -5
  27. package/api/expression.js.map +1 -1
  28. package/api/module/export.d.ts +63 -0
  29. package/api/module/export.js +64 -1
  30. package/api/module/export.js.map +1 -1
  31. package/api/module/import.d.ts +53 -0
  32. package/api/module/import.js +53 -0
  33. package/api/module/import.js.map +1 -1
  34. package/api/operators/grouping.d.ts +7 -0
  35. package/api/operators/grouping.js +7 -0
  36. package/api/operators/grouping.js.map +1 -1
  37. package/api/operators/pipeline.d.ts +12 -0
  38. package/api/operators/pipeline.js +12 -0
  39. package/api/operators/pipeline.js.map +1 -1
  40. package/api/operators/unary.js +3 -0
  41. package/api/operators/unary.js.map +1 -1
  42. package/api/program.d.ts +2 -2
  43. package/api/program.js.map +1 -1
  44. package/api/statement/control/block.d.ts +4 -0
  45. package/api/statement/control/block.js +4 -0
  46. package/api/statement/control/block.js.map +1 -1
  47. package/api/statement/control/empty.d.ts +7 -0
  48. package/api/statement/control/empty.js +7 -0
  49. package/api/statement/control/empty.js.map +1 -1
  50. package/api/statement/control/if.d.ts +5 -0
  51. package/api/statement/control/if.js +5 -0
  52. package/api/statement/control/if.js.map +1 -1
  53. package/api/statement/control/switch.d.ts +6 -0
  54. package/api/statement/control/switch.js +9 -0
  55. package/api/statement/control/switch.js.map +1 -1
  56. package/api/statement/control/terminate.d.ts +8 -0
  57. package/api/statement/control/terminate.js +8 -0
  58. package/api/statement/control/terminate.js.map +1 -1
  59. package/api/statement/iterations/for.d.ts +5 -0
  60. package/api/statement/iterations/for.js +13 -0
  61. package/api/statement/iterations/for.js.map +1 -1
  62. package/api/statement/iterations/while.d.ts +6 -0
  63. package/api/statement/iterations/while.js +10 -0
  64. package/api/statement/iterations/while.js.map +1 -1
  65. package/package.json +5 -3
  66. package/scope/event.d.ts +3 -3
  67. package/scope/event.js +2 -2
  68. package/scope/event.js.map +1 -1
  69. package/scope/pool.d.ts +7 -0
  70. package/scope/pool.js +29 -0
  71. package/scope/pool.js.map +1 -0
  72. package/scope/proxy.d.ts +6 -9
  73. package/scope/proxy.js +22 -31
  74. package/scope/proxy.js.map +1 -1
  75. package/scope/scope.d.ts +161 -38
  76. package/scope/scope.js +260 -106
  77. package/scope/scope.js.map +1 -1
  78. package/scope/stack.d.ts +95 -19
  79. package/scope/stack.js +13 -0
  80. package/scope/stack.js.map +1 -1
  81. package/v8/enums.js +31 -0
  82. package/v8/enums.js.map +1 -1
  83. package/v8/inline.d.ts +36 -0
  84. package/v8/inline.js +407 -5
  85. package/v8/inline.js.map +1 -1
  86. package/v8/nodes.js +2 -1
  87. package/v8/nodes.js.map +1 -1
  88. package/v8/parser.d.ts +8 -0
  89. package/v8/parser.js +304 -1
  90. package/v8/parser.js.map +1 -1
  91. package/v8/stream.d.ts +4 -0
  92. package/v8/stream.js +79 -17
  93. package/v8/stream.js.map +1 -1
  94. package/v8/token.d.ts +229 -0
  95. package/v8/token.js +236 -1
  96. package/v8/token.js.map +1 -1
  97. package/visit/visitor.d.ts +3 -0
package/v8/inline.js CHANGED
@@ -172,7 +172,11 @@ export class AbstractParser {
172
172
  case Token.LBRACK:
173
173
  case Token.IDENTIFIER:
174
174
  case Token.STATIC:
175
- case Token.LET:
175
+ case Token.LET: // `let let;` is disallowed by static semantics, but the
176
+ // token must be first interpreted as a keyword in order
177
+ // for those semantics to apply. This ensures that ASI is
178
+ // not honored when a LineTerminator separates the
179
+ // tokens.
176
180
  case Token.YIELD:
177
181
  case Token.AWAIT:
178
182
  case Token.GET:
@@ -196,6 +200,7 @@ export class AbstractParser {
196
200
  return Reflect.get(expression, 'parenthesized') === true;
197
201
  }
198
202
  isAssignableIdentifier(expression) {
203
+ // return expression instanceof AssignmentNode;
199
204
  if (!(expression instanceof Identifier)) {
200
205
  return false;
201
206
  }
@@ -312,6 +317,24 @@ export class JavaScriptInlineParser extends AbstractParser {
312
317
  }
313
318
  return new ExpressionStatement(list);
314
319
  }
320
+ /**
321
+ * Statement ::
322
+ * Block
323
+ * VariableStatement
324
+ * EmptyStatement
325
+ * ExpressionStatement
326
+ * IfStatement
327
+ * IterationStatement
328
+ * ContinueStatement
329
+ * BreakStatement
330
+ * ReturnStatement
331
+ * WithStatement
332
+ * LabelledStatement
333
+ * SwitchStatement
334
+ * ThrowStatement
335
+ * TryStatement
336
+ * DebuggerStatement
337
+ */
315
338
  parseStatement(allowFunction = AllowLabelledFunctionStatement.DisallowLabelledFunctionStatement) {
316
339
  switch (this.peek().token) {
317
340
  case Token.LBRACE:
@@ -362,6 +385,16 @@ export class JavaScriptInlineParser extends AbstractParser {
362
385
  return DebuggerStatement.INSTANCE;
363
386
  }
364
387
  parseTryStatement() {
388
+ // TryStatement ::
389
+ // 'try' Block Catch
390
+ // 'try' Block Finally
391
+ // 'try' Block Catch Finally
392
+ //
393
+ // Catch ::
394
+ // 'catch' '(' Identifier ')' Block
395
+ //
396
+ // Finally ::
397
+ // 'finally' Block
365
398
  this.consume(Token.TRY);
366
399
  const tryBlock = this.parseBlock();
367
400
  let peek = this.peek();
@@ -414,6 +447,24 @@ export class JavaScriptInlineParser extends AbstractParser {
414
447
  this.expect(Token.RBRACE);
415
448
  return block;
416
449
  }
450
+ /**
451
+ * ECMA 262 6th Edition
452
+ * StatementListItem[Yield, Return] :
453
+ * Statement[?Yield, ?Return]
454
+ * Declaration[?Yield]
455
+ * //
456
+ * Declaration[Yield] :
457
+ * HoistableDeclaration[?Yield]
458
+ * ClassDeclaration[?Yield]
459
+ * LexicalDeclaration[In, ?Yield]
460
+ * //
461
+ * HoistableDeclaration[Yield, Default] :
462
+ * FunctionDeclaration[?Yield, ?Default]
463
+ * GeneratorDeclaration[?Yield, ?Default]
464
+ * //
465
+ * LexicalDeclaration[In, Yield] :
466
+ * LetOrConst BindingList[?In, ?Yield] ;
467
+ */
417
468
  parseStatementListItem() {
418
469
  switch (this.peek().token) {
419
470
  case Token.FUNCTION:
@@ -453,6 +504,9 @@ export class JavaScriptInlineParser extends AbstractParser {
453
504
  return this.parseFunctionLiteral(functionKind, functionSyntaxKind, name);
454
505
  }
455
506
  parseAsyncFunctionDeclaration(names, defaultExport) {
507
+ // AsyncFunctionDeclaration ::
508
+ // async [no LineTerminator here] function BindingIdentifier[Await]
509
+ // ( FormalParameters[Await] ) { AsyncFunctionBody }
456
510
  if (this.scanner.hasLineTerminatorBeforeNext()) {
457
511
  throw new SyntaxError(this.errorMessage('Line Terminator Before `function` parsing `async function`.'));
458
512
  }
@@ -481,6 +535,8 @@ export class JavaScriptInlineParser extends AbstractParser {
481
535
  }
482
536
  }
483
537
  parseDoWhileStatement() {
538
+ // DoStatement ::
539
+ // 'do' Statement 'while' '(' Expression ')' ';'
484
540
  this.consume(Token.DO);
485
541
  const body = this.parseStatement();
486
542
  this.expect(Token.WHILE);
@@ -491,6 +547,8 @@ export class JavaScriptInlineParser extends AbstractParser {
491
547
  return new DoWhileNode(condition, body);
492
548
  }
493
549
  parseWhileStatement() {
550
+ // WhileStatement ::
551
+ // 'while' '(' Expression ')' Statement
494
552
  this.consume(Token.WHILE);
495
553
  this.expect(Token.LPAREN);
496
554
  const condition = this.parseExpression();
@@ -499,6 +557,8 @@ export class JavaScriptInlineParser extends AbstractParser {
499
557
  return new WhileNode(condition, body);
500
558
  }
501
559
  parseThrowStatement() {
560
+ // ThrowStatement ::
561
+ // 'throw' Expression ';'
502
562
  this.consume(Token.THROW);
503
563
  if (this.scanner.hasLineTerminatorBeforeNext()) {
504
564
  throw new Error(this.scanner.createError(`New line After Throw`));
@@ -508,6 +568,11 @@ export class JavaScriptInlineParser extends AbstractParser {
508
568
  return new ThrowStatement(exception);
509
569
  }
510
570
  parseSwitchStatement() {
571
+ // SwitchStatement ::
572
+ // 'switch' '(' Expression ')' '{' CaseClause* '}'
573
+ // CaseClause ::
574
+ // 'case' Expression ':' StatementList
575
+ // 'default' ':' StatementList
511
576
  this.consume(Token.SWITCH);
512
577
  this.expect(Token.LPAREN);
513
578
  const tag = this.parseExpression();
@@ -547,31 +612,58 @@ export class JavaScriptInlineParser extends AbstractParser {
547
612
  return switchStatement;
548
613
  }
549
614
  parseForStatement() {
615
+ // Either a standard for loop
616
+ // for (<init>; <cond>; <next>) { ... }
617
+ // or a for-each loop
618
+ // for (<each> of|in <iterable>) { ... }
619
+ //
620
+ // We parse a declaration/expression after the 'for (' and then read the first
621
+ // expression/declaration before we know if this is a for or a for-each.
622
+ // typename FunctionState::LoopScope loop_scope(function_state_);
550
623
  this.consume(Token.FOR);
551
624
  this.expect(Token.LPAREN);
552
625
  const peek = this.peek();
553
626
  const starts_with_let = peek.isType(Token.LET);
554
627
  if (peek.isType(Token.CONST) || (starts_with_let && this.isNextLetKeyword())) {
628
+ // The initializer contains lexical declarations,
629
+ // so create an in-between scope.
630
+ // Also record whether inner functions or evals are found inside
631
+ // this loop, as this information is used to simplify the desugaring
632
+ // if none are found.
633
+ // typename FunctionState::FunctionOrEvalRecordingScope recording_scope(function_state_);
555
634
  const initializer = this.parseVariableDeclarations(VariableDeclarationContext.ForStatement);
556
635
  const forMode = this.checkInOrOf();
557
636
  if (forMode) {
558
637
  return this.parseForEachStatementWithDeclarations(initializer, forMode);
559
638
  }
560
639
  this.expect(Token.SEMICOLON);
640
+ // Parse the remaining code in the inner block scope since the declaration
641
+ // above was parsed there. We'll finalize the unnecessary outer block scope
642
+ // after parsing the rest of the loop.
561
643
  return this.parseStandardForLoopWithLexicalDeclarations(initializer);
562
644
  }
563
645
  let initializer;
564
646
  if (peek.isType(Token.VAR)) {
565
647
  initializer = this.parseVariableDeclarations(VariableDeclarationContext.ForStatement);
648
+ // ParseVariableDeclarations(kForStatement, & for_info.parsing_result,& for_info.bound_names);
649
+ // DCHECK_EQ(for_info.parsing_result.descriptor.mode, VariableMode:: kVar);
650
+ // for_info.position = scanner() -> location().beg_pos;
566
651
  const forMode = this.checkInOrOf();
567
652
  if (forMode) {
568
653
  return this.parseForEachStatementWithDeclarations(initializer, forMode);
569
654
  }
655
+ // init = impl() -> BuildInitializationBlock(& for_info.parsing_result);
570
656
  }
571
657
  else if (this.peek().isNotType(Token.SEMICOLON)) {
658
+ // The initializer does not contain declarations.
572
659
  this.setAcceptIN(false);
573
660
  initializer = this.parseExpressionCoverGrammar();
574
661
  this.restoreAcceptIN();
662
+ // ExpressionParsingScope parsing_scope(impl());
663
+ // AcceptINScope scope(this, false);
664
+ // `for (async of` is disallowed but `for (async.x of` is allowed, so
665
+ // check if the token is ASYNC after parsing the expression.
666
+ // Initializer is reference followed by in/of.
575
667
  const expression_is_async = this.current().isType(Token.ASYNC);
576
668
  const forMode = this.checkInOrOf();
577
669
  if (forMode) {
@@ -585,9 +677,12 @@ export class JavaScriptInlineParser extends AbstractParser {
585
677
  return this.parseStandardForLoop(initializer);
586
678
  }
587
679
  parseStandardForLoopWithLexicalDeclarations(initializer) {
680
+ // The condition and the next statement of the for loop must be parsed
681
+ // in a new scope.
588
682
  return this.parseStandardForLoop(initializer);
589
683
  }
590
684
  parseForEachStatementWithDeclarations(initializer, forMode) {
685
+ // Just one declaration followed by in/of.
591
686
  if (initializer.getDeclarations().length != 1) {
592
687
  throw new SyntaxError(this.errorMessage('For In/Of loop Multi Bindings'));
593
688
  }
@@ -616,6 +711,9 @@ export class JavaScriptInlineParser extends AbstractParser {
616
711
  }
617
712
  }
618
713
  parseStandardForLoop(initializer) {
714
+ // CheckStackOverflow();
715
+ // ForStatementT loop = factory() -> NewForStatement(stmt_pos);
716
+ // Target target(this, loop, labels, own_labels, Target:: TARGET_FOR_ANONYMOUS);
619
717
  let cond = new EmptyStatement();
620
718
  if (this.peek().isNotType(Token.SEMICOLON)) {
621
719
  cond = this.parseExpression();
@@ -630,6 +728,9 @@ export class JavaScriptInlineParser extends AbstractParser {
630
728
  return new ForNode(body, initializer, cond, next);
631
729
  }
632
730
  parseForAwaitStatement() {
731
+ // for await '(' ForDeclaration of AssignmentExpression ')'
732
+ // Create an in-between scope for let-bound iteration variables.
733
+ // BlockState for_state(zone(), & scope_);
633
734
  if (!this.isAwaitAllowed()) {
634
735
  throw new SyntaxError(this.errorMessage('"await" is not allowed'));
635
736
  }
@@ -637,11 +738,17 @@ export class JavaScriptInlineParser extends AbstractParser {
637
738
  this.expect(Token.AWAIT);
638
739
  this.expect(Token.LPAREN);
639
740
  let hasDeclarations = false;
741
+ // Scope * inner_block_scope = NewScope(BLOCK_SCOPE);
640
742
  let eachVariable;
641
743
  let peek = this.peek();
642
744
  let startsWithLet = peek.isType(Token.LET);
643
745
  if (peek.isType(Token.VAR) || peek.isType(Token.CONST)
644
746
  || (startsWithLet && this.isNextLetKeyword())) {
747
+ // The initializer contains declarations
748
+ // 'for' 'await' '(' ForDeclaration 'of' AssignmentExpression ')'
749
+ // Statement
750
+ // 'for' 'await' '(' 'var' ForBinding 'of' AssignmentExpression ')'
751
+ // Statement
645
752
  hasDeclarations = true;
646
753
  const initializer = this.parseVariableDeclarations(VariableDeclarationContext.ForStatement);
647
754
  if (initializer.getDeclarations().length != 1) {
@@ -650,6 +757,9 @@ export class JavaScriptInlineParser extends AbstractParser {
650
757
  eachVariable = initializer;
651
758
  }
652
759
  else {
760
+ // The initializer does not contain declarations.
761
+ // 'for' 'await' '(' LeftHandSideExpression 'of' AssignmentExpression ')'
762
+ // Statement
653
763
  if (startsWithLet) {
654
764
  throw new SyntaxError(this.errorMessage('The initializer does not contain declarations, For Of Let, "for-await-of"'));
655
765
  }
@@ -664,6 +774,9 @@ export class JavaScriptInlineParser extends AbstractParser {
664
774
  return new ForAwaitOfNode(eachVariable, iterable, body);
665
775
  }
666
776
  parseVariableDeclarations(varContext) {
777
+ // VariableDeclarations ::
778
+ // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
779
+ // var converted into ==> 'let' by parser
667
780
  let mode;
668
781
  const token = this.peek().token;
669
782
  switch (token) {
@@ -685,11 +798,17 @@ export class JavaScriptInlineParser extends AbstractParser {
685
798
  do {
686
799
  let name;
687
800
  let value;
801
+ // Check for an identifier first, so that we can elide the pattern in cases
802
+ // where there is no initializer (and so no proxy needs to be created).
688
803
  if (Token.isAnyIdentifier(this.peek().token)) {
689
804
  name = this.parseAndClassifyIdentifier(this.next());
690
805
  if (isStrict(this.languageMode) && this.isEvalOrArguments(name)) {
691
806
  throw new Error(this.errorMessage(`Strict Eval Arguments`));
692
807
  }
808
+ // if (this.peekInOrOf()) {
809
+ // // // Assignments need the variable expression for the assignment LHS, and
810
+ // // // for of/in will need it later, so create the expression now.
811
+ // }
693
812
  }
694
813
  else {
695
814
  name = this.parseBindingPattern(true);
@@ -700,15 +819,21 @@ export class JavaScriptInlineParser extends AbstractParser {
700
819
  this.restoreAcceptIN();
701
820
  }
702
821
  else if (!this.peekInOrOf()) {
822
+ // ES6 'const' and binding patterns require initializers.
703
823
  if (mode === 'const' && (name === undefined || value === undefined)) {
704
824
  throw new Error(this.errorMessage(`Declaration Missing Initializer`));
705
825
  }
826
+ // value = undefined;
706
827
  }
707
828
  variables.push(new VariableDeclarator(name, value));
708
829
  } while (this.check(Token.COMMA));
709
830
  return new VariableDeclarationNode(variables, mode);
710
831
  }
711
832
  parseBindingPattern(isPattern) {
833
+ // Pattern ::
834
+ // Identifier
835
+ // ArrayLiteral
836
+ // ObjectLiteral
712
837
  const token = this.peek().token;
713
838
  if (Token.isAnyIdentifier(token)) {
714
839
  const name = this.parseAndClassifyIdentifier(this.next());
@@ -728,6 +853,7 @@ export class JavaScriptInlineParser extends AbstractParser {
728
853
  }
729
854
  }
730
855
  parseAndClassifyIdentifier(next) {
856
+ // Updates made here must be reflected on ClassifyPropertyIdentifier.
731
857
  if (Token.isInRangeIdentifierAndAsync(next.token)) {
732
858
  const name = next.getValue();
733
859
  if (this.isArguments(name) && this.shouldBanArguments()) {
@@ -744,30 +870,48 @@ export class JavaScriptInlineParser extends AbstractParser {
744
870
  return next.getValue();
745
871
  }
746
872
  parseContinueStatement() {
873
+ // ContinueStatement ::
874
+ // 'continue' ';'
875
+ // Identifier? is not supported
747
876
  this.consume(Token.CONTINUE);
748
877
  let label;
749
878
  if (!this.scanner.hasLineTerminatorBeforeNext() &&
750
879
  !Token.isAutoSemicolon(this.peek().token)) {
880
+ // ECMA allows "eval" or "arguments" as labels even in strict mode.
751
881
  label = this.parseIdentifier();
752
882
  }
753
883
  this.expectSemicolon();
754
884
  return label ? new ContinueStatement(label) : ContinueStatement.CONTINUE_INSTANCE;
755
885
  }
756
886
  parseBreakStatement() {
887
+ // BreakStatement ::
888
+ // 'break' ';'
889
+ // Identifier? is not supported
757
890
  this.consume(Token.BREAK);
758
891
  let label;
759
892
  if (!this.scanner.hasLineTerminatorBeforeNext() &&
760
893
  !Token.isAutoSemicolon(this.peek().token)) {
894
+ // ECMA allows "eval" or "arguments" as labels even in strict mode.
761
895
  label = this.parseIdentifier();
762
896
  }
763
897
  this.expectSemicolon();
764
898
  return label ? new BreakStatement(label) : BreakStatement.BREAK_INSTANCE;
765
899
  }
766
900
  parseReturnStatement() {
901
+ // ReturnStatement ::
902
+ // 'return' [no line terminator] Expression? ';'
903
+ // Consume the return token. It is necessary to do that before
904
+ // reporting any errors on it, because of the way errors are
905
+ // reported (underlining).
767
906
  this.consume(Token.RETURN);
768
907
  const tokenExp = this.peek();
769
908
  let returnValue;
909
+ // ExpressionT return_value = impl() -> NullExpression();
770
910
  if (this.scanner.hasLineTerminatorBeforeNext() || Token.isAutoSemicolon(tokenExp.token)) {
911
+ // check if this scope is belong to 'constructor' method to return this at the end;
912
+ // if (this.isDerivedConstructor(this.functionKind)) {
913
+ // returnValue = ThisNode;
914
+ // }
771
915
  }
772
916
  else {
773
917
  returnValue = this.parseExpression();
@@ -776,6 +920,12 @@ export class JavaScriptInlineParser extends AbstractParser {
776
920
  return new ReturnStatement(returnValue);
777
921
  }
778
922
  parseExpressionOrLabelledStatement(allowFunction) {
923
+ // ExpressionStatement | LabelledStatement ::
924
+ // Expression ';'
925
+ // Identifier ':' Statement
926
+ //
927
+ // ExpressionStatement[Yield] :
928
+ // [lookahead notin {{, function, class, let [}] Expression[In, ?Yield] ;
779
929
  switch (this.peek().token) {
780
930
  case Token.FUNCTION:
781
931
  case Token.LBRACE:
@@ -784,6 +934,9 @@ export class JavaScriptInlineParser extends AbstractParser {
784
934
  throw new Error(this.errorMessage(`Unexpected Token ${this.next().getValue().toString()}`));
785
935
  case Token.LET: {
786
936
  const nextNext = this.peekAhead();
937
+ // "let" followed by either "[", "{" or an identifier means a lexical
938
+ // declaration, which should not appear here.
939
+ // However, ASI may insert a line break before an identifier or a brace.
787
940
  if (nextNext.isNotType(Token.LBRACK) &&
788
941
  ((nextNext.isNotType(Token.LBRACE) && nextNext.isNotType(Token.IDENTIFIER)))) {
789
942
  break;
@@ -797,7 +950,13 @@ export class JavaScriptInlineParser extends AbstractParser {
797
950
  this.setAcceptIN(true);
798
951
  const expression = this.parseExpressionCoverGrammar();
799
952
  if (this.peek().isType(Token.COLON) && startsWithIdentifier && this.isIdentifier(expression)) {
953
+ // The whole expression was a single identifier, and not, e.g.,
954
+ // something starting with an identifier or a parenthesized identifier.
955
+ // Remove the "ghost" variable that turned out to be a label from the top
956
+ // scope. This way, we don't try to resolve it during the scope
957
+ // processing.
800
958
  this.consume(Token.COLON);
959
+ // ES#sec-labelled-function-declarations Labelled Function Declarations
801
960
  if (this.peek().isType(Token.FUNCTION)
802
961
  && isSloppy(this.languageMode)
803
962
  && allowFunction == AllowLabelledFunctionStatement.AllowLabelledFunctionStatement) {
@@ -810,6 +969,7 @@ export class JavaScriptInlineParser extends AbstractParser {
810
969
  return new LabeledStatement(expression, result);
811
970
  }
812
971
  this.restoreAcceptIN();
972
+ // Parsed expression statement, followed by semicolon.
813
973
  this.expectSemicolon();
814
974
  return expression;
815
975
  }
@@ -827,6 +987,12 @@ export class JavaScriptInlineParser extends AbstractParser {
827
987
  return this.parseHoistableDeclaration01(FunctionKind.NormalFunction, undefined, false);
828
988
  }
829
989
  parseAsyncFunctionLiteral() {
990
+ // AsyncFunctionLiteral ::
991
+ // async [no LineTerminator here] function ( FormalParameters[Await] )
992
+ // { AsyncFunctionBody }
993
+ //
994
+ // async [no LineTerminator here] function BindingIdentifier[Await]
995
+ // ( FormalParameters[Await] ) { AsyncFunctionBody }
830
996
  if (this.current().isNotType(Token.ASYNC)) {
831
997
  throw new SyntaxError(this.errorMessage('invalid token'));
832
998
  }
@@ -852,7 +1018,19 @@ export class JavaScriptInlineParser extends AbstractParser {
852
1018
  return this.parseHoistableDeclaration01(flags, names, defaultExport);
853
1019
  }
854
1020
  parseHoistableDeclaration01(flag, names, defaultExport) {
1021
+ // FunctionDeclaration ::
1022
+ // 'function' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
1023
+ // 'function' '(' FormalParameters ')' '{' FunctionBody '}'
1024
+ // GeneratorDeclaration ::
1025
+ // 'function' '*' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
1026
+ // 'function' '*' '(' FormalParameters ')' '{' FunctionBody '}'
1027
+ //
1028
+ // The anonymous forms are allowed iff [default_export] is true.
1029
+ //
1030
+ // 'function' and '*' (if present) have been consumed by the caller.
1031
+ // (FunctionType.ASYNC === flag || FunctionType.GENERATOR === flag);
855
1032
  if ((flag & ParseFunctionFlag.IsAsync) != 0 && this.check(Token.MUL)) {
1033
+ // Async generator
856
1034
  flag |= ParseFunctionFlag.IsGenerator;
857
1035
  }
858
1036
  let name;
@@ -910,6 +1088,8 @@ export class JavaScriptInlineParser extends AbstractParser {
910
1088
  return current.getValue();
911
1089
  }
912
1090
  parseFunctionLiteral(flag, functionSyntaxKind, name) {
1091
+ // Function ::
1092
+ // '(' FormalParameterList? ')' '{' FunctionBody '}'
913
1093
  this.setFunctionKind(flag);
914
1094
  const functionInfo = {};
915
1095
  this.expect(Token.LPAREN);
@@ -927,11 +1107,17 @@ export class JavaScriptInlineParser extends AbstractParser {
927
1107
  return new FunctionExpression(formals, bodyBlock, isAsyncFunction(flag), isGeneratorFunction(flag));
928
1108
  }
929
1109
  parseFunctionBody(kind, bodyType, functionSyntaxKind) {
1110
+ // Building the parameter initialization block declares the parameters.
1111
+ // TODO(verwaest): Rely on ArrowHeadParsingScope instead.
930
1112
  let innerBody;
931
1113
  if (bodyType == FunctionBodyType.EXPRESSION) {
932
1114
  innerBody = this.parseAssignmentExpression();
933
1115
  }
934
1116
  else {
1117
+ // DCHECK(accept_IN_);
1118
+ // DCHECK_EQ(FunctionBodyType:: kBlock, body_type);
1119
+ // If we are parsing the source as if it is wrapped in a function, the
1120
+ // source ends without a closing brace.
935
1121
  const closing_token = functionSyntaxKind == FunctionSyntaxKind.Wrapped ? Token.EOS : Token.RBRACE;
936
1122
  if (isAsyncGeneratorFunction(kind)) {
937
1123
  innerBody = this.parseAndRewriteAsyncGeneratorFunctionBody(kind);
@@ -959,6 +1145,8 @@ export class JavaScriptInlineParser extends AbstractParser {
959
1145
  return this.parseStatementList(Token.RBRACE);
960
1146
  }
961
1147
  parseStatementList(endToken) {
1148
+ // StatementList ::
1149
+ // (StatementListItem)* <end_token>
962
1150
  if (this.peek().test((token, value) => Token.STRING === token && 'use strict' === value.getValue())) {
963
1151
  this.languageMode = LanguageMode.Strict;
964
1152
  }
@@ -976,6 +1164,16 @@ export class JavaScriptInlineParser extends AbstractParser {
976
1164
  return list;
977
1165
  }
978
1166
  parseFormalParameterList(functionInfo) {
1167
+ // FormalParameters[Yield] :
1168
+ // [empty]
1169
+ // FunctionRestParameter[?Yield]
1170
+ // FormalParameterList[?Yield]
1171
+ // FormalParameterList[?Yield] ,
1172
+ // FormalParameterList[?Yield] , FunctionRestParameter[?Yield]
1173
+ //
1174
+ // FormalParameterList[Yield] :
1175
+ // FormalParameter[?Yield]
1176
+ // FormalParameterList[?Yield] , FormalParameter[?Yield]
979
1177
  const parameters = [];
980
1178
  if (this.peek().isNotType(Token.RPAREN)) {
981
1179
  while (true) {
@@ -990,6 +1188,7 @@ export class JavaScriptInlineParser extends AbstractParser {
990
1188
  if (!this.check(Token.COMMA))
991
1189
  break;
992
1190
  if (this.peek().isType(Token.RPAREN)) {
1191
+ // allow the trailing comma
993
1192
  break;
994
1193
  }
995
1194
  }
@@ -997,6 +1196,8 @@ export class JavaScriptInlineParser extends AbstractParser {
997
1196
  return parameters;
998
1197
  }
999
1198
  parseFormalParameter(functionInfo) {
1199
+ // FormalParameter[Yield,GeneratorParameter] :
1200
+ // BindingElement[?Yield, ?GeneratorParameter]
1000
1201
  functionInfo.rest = this.check(Token.ELLIPSIS);
1001
1202
  let pattern = this.parseBindingPattern(true);
1002
1203
  let initializer;
@@ -1015,6 +1216,9 @@ export class JavaScriptInlineParser extends AbstractParser {
1015
1216
  return initializer;
1016
1217
  }
1017
1218
  parseExpressionCoverGrammar() {
1219
+ // Expression ::
1220
+ // AssignmentExpression
1221
+ // Expression ',' AssignmentExpression
1018
1222
  const list = [];
1019
1223
  let expression;
1020
1224
  while (true) {
@@ -1026,6 +1230,7 @@ export class JavaScriptInlineParser extends AbstractParser {
1026
1230
  if (!this.check(Token.COMMA))
1027
1231
  break;
1028
1232
  if (this.peek().isType(Token.RPAREN) && this.peekAhead().isType(Token.ARROW)) {
1233
+ // a trailing comma is allowed at the end of an arrow parameter list
1029
1234
  break;
1030
1235
  }
1031
1236
  }
@@ -1042,6 +1247,9 @@ export class JavaScriptInlineParser extends AbstractParser {
1042
1247
  if (this.peek().isType(Token.COMMA)) {
1043
1248
  throw new Error(this.errorMessage(`Error A rest parameter or binding pattern may not have a trailing comma`));
1044
1249
  }
1250
+ // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only
1251
+ // as the formal parameters of'(x, y, ...z) => foo', and is not itself a
1252
+ // valid expression.
1045
1253
  if (this.peek().isNotType(Token.RPAREN) || this.peekAhead().isNotType(Token.ARROW)) {
1046
1254
  throw new Error(this.errorMessage(`Error Unexpected Token At ${this.position()}`));
1047
1255
  }
@@ -1060,6 +1268,18 @@ export class JavaScriptInlineParser extends AbstractParser {
1060
1268
  return new SequenceExpression(list);
1061
1269
  }
1062
1270
  parseMemberExpression() {
1271
+ // MemberExpression ::
1272
+ // (PrimaryExpression | FunctionLiteral | ClassLiteral)
1273
+ // ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)*
1274
+ //
1275
+ // CallExpression ::
1276
+ // (SuperCall | ImportCall)
1277
+ // ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)*
1278
+ //
1279
+ // The '[' Expression ']' and '.' Identifier parts are parsed by
1280
+ // ParseMemberExpressionContinuation, and everything preceeding it is merged
1281
+ // into ParsePrimaryExpression.
1282
+ // Parse the initial primary or function expression.
1063
1283
  const result = this.parsePrimaryExpression();
1064
1284
  return this.parseMemberExpressionContinuation(result);
1065
1285
  }
@@ -1073,15 +1293,31 @@ export class JavaScriptInlineParser extends AbstractParser {
1073
1293
  return new Param(expression);
1074
1294
  }
1075
1295
  parsePrimaryExpression() {
1296
+ // PrimaryExpression ::
1297
+ // 'this'
1298
+ // 'null'
1299
+ // 'true'
1300
+ // 'false'
1301
+ // Identifier
1302
+ // Number
1303
+ // String
1304
+ // ArrayLiteral
1305
+ // ObjectLiteral
1306
+ // RegExpLiteral
1307
+ // '(' Expression ')'
1308
+ // do Block
1309
+ // AsyncFunctionLiteral
1076
1310
  let token = this.peek();
1077
1311
  if (Token.isAnyIdentifier(token.token)) {
1078
1312
  this.consume(token.token);
1079
1313
  let kind = FunctionKind.NormalFunction;
1080
1314
  if (token.isType(Token.ASYNC) && !this.scanner.hasLineTerminatorBeforeNext()) {
1315
+ // async function ...
1081
1316
  if (this.peek().isType(Token.FUNCTION)) {
1082
1317
  return this.parseAsyncFunctionLiteral();
1083
1318
  }
1084
1319
  ;
1320
+ // async Identifier => ...
1085
1321
  if (Token.isAnyIdentifier(this.peek().token) && this.peekAhead().isType(Token.ARROW)) {
1086
1322
  token = this.next();
1087
1323
  kind = FunctionKind.AsyncFunction;
@@ -1114,6 +1350,9 @@ export class JavaScriptInlineParser extends AbstractParser {
1114
1350
  return ThisNode;
1115
1351
  case Token.DIV:
1116
1352
  case Token.DIV_ASSIGN:
1353
+ // case Token.REGEXP_LITERAL:
1354
+ // this.consume(Token.REGEXP_LITERAL);
1355
+ // return token.value!;
1117
1356
  return this.parseRegExpLiteral();
1118
1357
  case Token.FUNCTION:
1119
1358
  return this.parseFunctionExpression();
@@ -1129,6 +1368,8 @@ export class JavaScriptInlineParser extends AbstractParser {
1129
1368
  case Token.LPAREN: {
1130
1369
  this.consume(Token.LPAREN);
1131
1370
  if (this.check(Token.RPAREN)) {
1371
+ // ()=>x. The continuation that consumes the => is in
1372
+ // ParseAssignmentExpressionCoverGrammar.
1132
1373
  if (!this.peek().isType(Token.ARROW)) {
1133
1374
  throw new Error(this.errorMessage(`Unexpected Token: ${Token.RPAREN.getName()}`));
1134
1375
  }
@@ -1136,6 +1377,8 @@ export class JavaScriptInlineParser extends AbstractParser {
1136
1377
  this.markParenthesized(result);
1137
1378
  return result;
1138
1379
  }
1380
+ // Heuristically try to detect immediately called functions before
1381
+ // seeing the call parentheses.
1139
1382
  this.setAcceptIN(true);
1140
1383
  const expression = this.parseExpressionCoverGrammar();
1141
1384
  this.markParenthesized(expression);
@@ -1155,10 +1398,23 @@ export class JavaScriptInlineParser extends AbstractParser {
1155
1398
  throw new Error(this.errorMessage(`Unexpected Token: ${JSON.stringify(this.next())}`));
1156
1399
  }
1157
1400
  parseTemplateLiteral(tag) {
1401
+ // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal
1402
+ // text followed by a substitution expression), finalized by a single
1403
+ // TEMPLATE_TAIL.
1404
+ //
1405
+ // In terms of draft language, TEMPLATE_SPAN may be either the TemplateHead or
1406
+ // TemplateMiddle productions, while TEMPLATE_TAIL is either TemplateTail, or
1407
+ // NoSubstitutionTemplate.
1408
+ //
1409
+ // When parsing a TemplateLiteral, we must have scanned either an initial
1410
+ // TEMPLATE_SPAN, or a TEMPLATE_TAIL.
1158
1411
  let next = this.peek();
1159
1412
  if (!Token.isTemplate(next.token)) {
1160
1413
  throw new SyntaxError(this.errorMessage(`Unexpected Token: ${JSON.stringify(this.next())}`));
1161
1414
  }
1415
+ // If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate.
1416
+ // In this case we may simply consume the token and build a template with a
1417
+ // single TEMPLATE_SPAN and no expressions.
1162
1418
  if (next.isType(Token.TEMPLATE_TAIL)) {
1163
1419
  this.consume(Token.TEMPLATE_TAIL);
1164
1420
  const string = next.getValue().string;
@@ -1168,6 +1424,9 @@ export class JavaScriptInlineParser extends AbstractParser {
1168
1424
  const expressions = [];
1169
1425
  const strings = [];
1170
1426
  strings.push(next.getValue().string);
1427
+ // If we open with a TEMPLATE_SPAN, we must scan the subsequent expression,
1428
+ // and repeat if the following token is a TEMPLATE_SPAN as well (in this
1429
+ // case, representing a TemplateMiddle).
1171
1430
  do {
1172
1431
  this.setAcceptIN(true);
1173
1432
  const expression = this.parseExpressionCoverGrammar();
@@ -1177,6 +1436,8 @@ export class JavaScriptInlineParser extends AbstractParser {
1177
1436
  this.restoreAcceptIN();
1178
1437
  throw new SyntaxError(this.errorMessage('Unterminated Template Expr'));
1179
1438
  }
1439
+ // If we didn't die parsing that expression, our next token should be a
1440
+ // TEMPLATE_SPAN or TEMPLATE_TAIL.
1180
1441
  next = this.scanner.scanTemplateContinuation();
1181
1442
  strings.push(next.getValue().string);
1182
1443
  this.restoreAcceptIN();
@@ -1184,6 +1445,7 @@ export class JavaScriptInlineParser extends AbstractParser {
1184
1445
  if (next.isNotType(Token.TEMPLATE_TAIL)) {
1185
1446
  throw new SyntaxError(this.errorMessage(`Unexpected Token: ${JSON.stringify(next)}`));
1186
1447
  }
1448
+ // Once we've reached a TEMPLATE_TAIL, we can close the TemplateLiteral.
1187
1449
  return this.createTemplateLiteralExpressionNode(strings, expressions, tag);
1188
1450
  }
1189
1451
  createTemplateLiteralExpressionNode(strings, expressions, tag) {
@@ -1195,8 +1457,27 @@ export class JavaScriptInlineParser extends AbstractParser {
1195
1457
  }
1196
1458
  }
1197
1459
  parseMemberWithPresentNewPrefixesExpression() {
1460
+ // NewExpression ::
1461
+ // ('new')+ MemberExpression
1462
+ //
1463
+ // NewTarget ::
1464
+ // 'new' '.' 'target'
1465
+ // The grammar for new expressions is pretty warped. We can have several 'new'
1466
+ // keywords following each other, and then a MemberExpression. When we see '('
1467
+ // after the MemberExpression, it's associated with the rightmost unassociated
1468
+ // 'new' to create a NewExpression with arguments. However, a NewExpression
1469
+ // can also occur without arguments.
1470
+ // Examples of new expression:
1471
+ // new foo.bar().baz means (new (foo.bar)()).baz
1472
+ // new foo()() means (new foo())()
1473
+ // new new foo()() means (new (new foo())())
1474
+ // new new foo means new (new foo)
1475
+ // new new foo() means new (new foo())
1476
+ // new new foo().bar().baz means (new (new foo()).bar()).baz
1477
+ // new super.x means new (super.x)
1198
1478
  this.consume(Token.NEW);
1199
1479
  let result;
1480
+ // CheckStackOverflow();
1200
1481
  if (this.peek().isType(Token.IMPORT) && this.peekAhead().isType(Token.LPAREN)) {
1201
1482
  throw new SyntaxError(this.errorMessage(`Import Call Not New Expression`));
1202
1483
  }
@@ -1207,12 +1488,15 @@ export class JavaScriptInlineParser extends AbstractParser {
1207
1488
  else {
1208
1489
  result = this.parseMemberExpression();
1209
1490
  if (result === SuperIdentifier) {
1491
+ // new super() is never allowed
1210
1492
  throw new SyntaxError(this.errorMessage(`Unexpected Super, new super() is never allowed`));
1211
1493
  }
1212
1494
  }
1213
1495
  if (this.peek().isType(Token.LPAREN)) {
1496
+ // NewExpression with arguments.
1214
1497
  const args = this.parseArguments();
1215
1498
  result = new NewExpression(result, args);
1499
+ // The expression can still continue with . or [ after the arguments.
1216
1500
  return this.parseMemberExpressionContinuation(result);
1217
1501
  }
1218
1502
  if (this.peek().isType(Token.QUESTION_PERIOD)) {
@@ -1221,6 +1505,8 @@ export class JavaScriptInlineParser extends AbstractParser {
1221
1505
  return new NewExpression(result);
1222
1506
  }
1223
1507
  parseArguments(maybeArrow) {
1508
+ // Arguments ::
1509
+ // '(' (AssignmentExpression)*[','] ')'
1224
1510
  this.consume(Token.LPAREN);
1225
1511
  const args = [];
1226
1512
  while (this.peek().isNotType(Token.RPAREN)) {
@@ -1253,6 +1539,11 @@ export class JavaScriptInlineParser extends AbstractParser {
1253
1539
  return args;
1254
1540
  }
1255
1541
  parseAssignmentExpressionCoverGrammar() {
1542
+ // AssignmentExpression ::
1543
+ // ConditionalExpression
1544
+ // ArrowFunction
1545
+ // YieldExpression
1546
+ // LeftHandSideExpression AssignmentOperator AssignmentExpression
1256
1547
  if (this.peek().isType(Token.YIELD) && isGeneratorFunction(this.functionKind)) {
1257
1548
  return this.parseYieldExpression();
1258
1549
  }
@@ -1263,6 +1554,7 @@ export class JavaScriptInlineParser extends AbstractParser {
1263
1554
  return expression;
1264
1555
  }
1265
1556
  ;
1557
+ // Arrow functions.
1266
1558
  if (op === Token.ARROW) {
1267
1559
  if (!this.isIdentifier(expression) && !this.isParenthesized(expression)) {
1268
1560
  throw new Error(this.errorMessage(`Malformed Arrow Fun Param List`));
@@ -1301,9 +1593,11 @@ export class JavaScriptInlineParser extends AbstractParser {
1301
1593
  else if (this.isProperty(expression)) {
1302
1594
  }
1303
1595
  else if (this.isPattern(expression) && Token.isAssignment(op)) {
1596
+ // Destructuring assignment.
1304
1597
  expression = expression instanceof ObjectExpression
1305
1598
  ? new ObjectPattern(expression.getProperties())
1306
1599
  : new ArrayPattern(expression.getElements());
1600
+ // expression_scope() -> ValidateAsPattern(expression, lhs_beg_pos, end_position());
1307
1601
  }
1308
1602
  else {
1309
1603
  if (!this.isValidReferenceExpression(expression)) {
@@ -1314,7 +1608,9 @@ export class JavaScriptInlineParser extends AbstractParser {
1314
1608
  }
1315
1609
  }
1316
1610
  this.consume(op);
1611
+ // const opPosition = this.position();
1317
1612
  const right = this.parseAssignmentExpression();
1613
+ // Anonymous function name inference applies to =, ||=, &&=, and ??=.
1318
1614
  if (!Token.isAssignment(op)) {
1319
1615
  throw new Error(this.errorMessage(`Invalid Destructuring Target`));
1320
1616
  }
@@ -1352,6 +1648,8 @@ export class JavaScriptInlineParser extends AbstractParser {
1352
1648
  return this.scanner.currentToken().getValue();
1353
1649
  }
1354
1650
  parseArrayLiteral(isPattern) {
1651
+ // ArrayLiteral ::
1652
+ // '[' Expression? (',' Expression?)* ']'
1355
1653
  this.consume(Token.LBRACK);
1356
1654
  let first_spread_index = -1;
1357
1655
  const values = [];
@@ -1391,6 +1689,8 @@ export class JavaScriptInlineParser extends AbstractParser {
1391
1689
  return this.parseAssignmentExpressionCoverGrammar();
1392
1690
  }
1393
1691
  parseObjectLiteral(isPattern) {
1692
+ // ObjectLiteral ::
1693
+ // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}'
1394
1694
  this.consume(Token.LBRACE);
1395
1695
  const properties = [];
1396
1696
  while (!this.check(Token.RBRACE)) {
@@ -1425,6 +1725,12 @@ export class JavaScriptInlineParser extends AbstractParser {
1425
1725
  case PropertyKind.Assign:
1426
1726
  case PropertyKind.ShorthandOrClassField:
1427
1727
  case PropertyKind.Shorthand: {
1728
+ // PropertyDefinition
1729
+ // IdentifierReference
1730
+ // CoverInitializedName
1731
+ //
1732
+ // CoverInitializedName
1733
+ // IdentifierReference Initializer?
1428
1734
  const lhs = new Identifier(propInfo.name);
1429
1735
  if (!this.isAssignableIdentifier(lhs)) {
1430
1736
  throw new Error(this.errorMessage('Strict Eval Arguments'));
@@ -1443,6 +1749,9 @@ export class JavaScriptInlineParser extends AbstractParser {
1443
1749
  return new Property(nameExpression, value, 'init', false, propInfo.kind !== PropertyKind.Assign, propInfo.isComputedName);
1444
1750
  }
1445
1751
  case PropertyKind.Method: {
1752
+ // MethodDefinition
1753
+ // PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
1754
+ // '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
1446
1755
  const kind = this.methodKindFor(propInfo.isStatic, propInfo.funcFlag);
1447
1756
  const value = this.parseFunctionLiteral(kind, FunctionSyntaxKind.AccessorOrMethod, propInfo.name ? new Identifier(propInfo.name) : undefined);
1448
1757
  return new Property(nameExpression, value, 'init', true, false, propInfo.isComputedName);
@@ -1462,6 +1771,7 @@ export class JavaScriptInlineParser extends AbstractParser {
1462
1771
  parseProperty(propInfo) {
1463
1772
  let nextToken = this.peek();
1464
1773
  if (this.check(Token.ASYNC)) {
1774
+ // async
1465
1775
  nextToken = this.peek();
1466
1776
  if (nextToken.isNotType(Token.MUL)
1467
1777
  && propInfo.parsePropertyKindFromToken(nextToken.token)
@@ -1472,6 +1782,7 @@ export class JavaScriptInlineParser extends AbstractParser {
1472
1782
  propInfo.funcFlag = ParseFunctionFlag.IsAsync;
1473
1783
  }
1474
1784
  if (this.check(Token.MUL)) {
1785
+ // async*
1475
1786
  propInfo.kind = PropertyKind.Method;
1476
1787
  propInfo.funcFlag = ParseFunctionFlag.IsGenerator;
1477
1788
  }
@@ -1506,11 +1817,15 @@ export class JavaScriptInlineParser extends AbstractParser {
1506
1817
  case Token.STRING:
1507
1818
  case Token.NUMBER:
1508
1819
  case Token.BIGINT:
1820
+ // "12" -> 12
1821
+ // 12.3 -> "12.3"
1822
+ // 12.30 -> "12.3"
1509
1823
  this.consume(nextToken.token);
1510
1824
  propertyName = nextToken.getValue();
1511
1825
  propInfo.name = propertyName.getValue();
1512
1826
  break;
1513
1827
  case Token.LBRACK:
1828
+ // [Symbol.iterator]
1514
1829
  this.consume(Token.LBRACK);
1515
1830
  this.setAcceptIN(true);
1516
1831
  propertyName = this.parseAssignmentExpression();
@@ -1556,6 +1871,8 @@ export class JavaScriptInlineParser extends AbstractParser {
1556
1871
  if (!Token.isMember(this.peek().token)) {
1557
1872
  throw new Error(this.errorMessage(`Parsing member expression`));
1558
1873
  }
1874
+ // Parses this part of MemberExpression:
1875
+ // ('[' Expression ']' | '.' Identifier | TemplateLiteral)*
1559
1876
  do {
1560
1877
  switch (this.peek().token) {
1561
1878
  case Token.LBRACK: {
@@ -1589,12 +1906,23 @@ export class JavaScriptInlineParser extends AbstractParser {
1589
1906
  if (next.isType(Token.IDENTIFIER) || next.isType(Token.PRIVATE_NAME)) {
1590
1907
  return next.getValue();
1591
1908
  }
1909
+ // check keyword as identifier
1592
1910
  if (Token.isPropertyName(next.token) && next.isNotType(Token.EOS)) {
1593
1911
  return new Identifier(next.token.getName());
1594
1912
  }
1595
1913
  throw new SyntaxError(this.errorMessage(`Parsing property expression: Unexpected Token`));
1596
1914
  }
1597
1915
  parsePipelineExpression(expression) {
1916
+ // ConditionalExpression ::
1917
+ // LogicalExpression
1918
+ // expression '|>' function [':' expression [':'? expression] ] *
1919
+ // expression '|>' function '('[expression ','?]* ')'
1920
+ //
1921
+ // expression '|>' function ':' expression [':' expression | '?']*]
1922
+ // expression '|>' function '(' expression [',' expression | '?']* ')'
1923
+ //
1924
+ // [~Await]PipelineExpression[?In, ?Yield, ?Await] |> LogicalORExpression[?In, ?Yield, ?Await]
1925
+ // [+Await]PipelineExpression[? In, ? Yield, ? Await] |> [lookahead ∉ { await }]LogicalORExpression[? In, ? Yield, ? Await]
1598
1926
  let token;
1599
1927
  while (Token.isPipelineOperator(token = this.peek().token)) {
1600
1928
  this.consume(token);
@@ -1605,13 +1933,16 @@ export class JavaScriptInlineParser extends AbstractParser {
1605
1933
  parsePipelineBody(lhs) {
1606
1934
  let body;
1607
1935
  let token = this.peek();
1936
+ // parse function
1608
1937
  switch (token.token) {
1609
1938
  case Token.FUNCTION:
1610
1939
  body = this.parseFunctionExpression();
1611
1940
  break;
1612
1941
  case Token.ASYNC:
1613
- this.consume(Token.ASYNC);
1614
- body = this.parseAsyncFunctionLiteral();
1942
+ if (this.peekAhead().isType(Token.FUNCTION) && !this.scanner.hasLineTerminatorAfterNext()) {
1943
+ this.consume(Token.ASYNC);
1944
+ body = this.parseAsyncFunctionLiteral();
1945
+ }
1615
1946
  break;
1616
1947
  default:
1617
1948
  break;
@@ -1620,13 +1951,17 @@ export class JavaScriptInlineParser extends AbstractParser {
1620
1951
  return new PipelineExpression(lhs, body);
1621
1952
  }
1622
1953
  if (token.isType(Token.LPAREN)) {
1954
+ // parse arrow function
1955
+ // x |> ( y => y+1 )
1623
1956
  body = this.parsePrimaryExpression();
1624
1957
  return new PipelineExpression(lhs, body);
1625
1958
  }
1626
- const func = this.parseMemberExpression();
1959
+ // parse angular-like and f# and partial operator syntax
1960
+ const func = this.parseMemberExpression(); //this.parseLogicalExpression();
1627
1961
  let args = [];
1628
1962
  switch (this.peek().token) {
1629
1963
  case Token.COLON:
1964
+ // support angular pipeline syntax
1630
1965
  do {
1631
1966
  this.consume(Token.COLON);
1632
1967
  const isSpread = this.check(Token.ELLIPSIS);
@@ -1651,6 +1986,7 @@ export class JavaScriptInlineParser extends AbstractParser {
1651
1986
  } while (this.peek().isType(Token.COLON));
1652
1987
  break;
1653
1988
  case Token.LPAREN:
1989
+ // es2022 syntax, F# & partial operator
1654
1990
  this.consume(Token.LPAREN);
1655
1991
  let indexed = false;
1656
1992
  while (this.peek().isNotType(Token.RPAREN)) {
@@ -1677,7 +2013,9 @@ export class JavaScriptInlineParser extends AbstractParser {
1677
2013
  this.check(Token.COMMA);
1678
2014
  }
1679
2015
  this.expect(Token.RPAREN);
2016
+ // should be indexed, has partial operator
1680
2017
  if (!indexed) {
2018
+ // z |> method(x, y) === method(x, y)(z)
1681
2019
  body = new CallExpression(func, args);
1682
2020
  return new PipelineExpression(lhs, body);
1683
2021
  }
@@ -1688,14 +2026,24 @@ export class JavaScriptInlineParser extends AbstractParser {
1688
2026
  return new PipelineExpression(lhs, func, args);
1689
2027
  }
1690
2028
  parseConditionalExpression() {
2029
+ // ConditionalExpression ::
2030
+ // LogicalExpression
2031
+ // LogicalExpression '?' AssignmentExpression ':' AssignmentExpression
2032
+ //
1691
2033
  let expression = this.parseLogicalExpression();
1692
2034
  expression = this.parsePipelineExpression(expression);
1693
2035
  return this.peek().isType(Token.CONDITIONAL) ? this.parseConditionalContinuation(expression) : expression;
1694
2036
  }
1695
2037
  parseLogicalExpression() {
2038
+ // LogicalExpression ::
2039
+ // LogicalORExpression
2040
+ // CoalesceExpression
2041
+ // Both LogicalORExpression and CoalesceExpression start with BitwiseOR.
2042
+ // Parse for binary expressions >= 6 (BitwiseOR);
1696
2043
  let expression = this.parseBinaryExpression(6);
1697
2044
  const peek = this.peek();
1698
2045
  if (peek.isType(Token.AND) || peek.isType(Token.OR)) {
2046
+ // LogicalORExpression, pickup parsing where we left off.
1699
2047
  const precedence = Token.precedence(peek.token, this.acceptIN);
1700
2048
  expression = this.parseBinaryContinuation(expression, 4, precedence);
1701
2049
  }
@@ -1706,13 +2054,18 @@ export class JavaScriptInlineParser extends AbstractParser {
1706
2054
  }
1707
2055
  parseBinaryContinuation(x, prec, prec1) {
1708
2056
  do {
2057
+ // prec1 >= 4
1709
2058
  while (Token.precedence(this.peek().token, this.acceptIN) === prec1) {
1710
2059
  let y;
1711
2060
  let op = this.next();
1712
2061
  const is_right_associative = op.isType(Token.EXP);
1713
2062
  const next_prec = is_right_associative ? prec1 : prec1 + 1;
1714
2063
  y = this.parseBinaryExpression(next_prec);
2064
+ // For now we distinguish between comparisons and other binary
2065
+ // operations. (We could combine the two and get rid of this
2066
+ // code and AST node eventually.)
1715
2067
  if (Token.isCompare(op.token)) {
2068
+ // We have a comparison.
1716
2069
  let cmp = op.token;
1717
2070
  switch (op.token) {
1718
2071
  case Token.NE:
@@ -1725,6 +2078,7 @@ export class JavaScriptInlineParser extends AbstractParser {
1725
2078
  }
1726
2079
  x = shortcutNumericLiteralBinaryExpression(x, y, cmp);
1727
2080
  if (op.isNotType(cmp)) {
2081
+ // The comparison was negated - add a NOT.
1728
2082
  x = buildUnaryExpression(x, Token.NOT);
1729
2083
  }
1730
2084
  }
@@ -1736,7 +2090,10 @@ export class JavaScriptInlineParser extends AbstractParser {
1736
2090
  } while (prec1 >= prec);
1737
2091
  return x;
1738
2092
  }
2093
+ // Precedence >= 4
1739
2094
  parseBinaryExpression(precedence) {
2095
+ // "#foo in ShiftExpression" needs to be parsed separately, since private
2096
+ // identifiers are not valid PrimaryExpressions.
1740
2097
  if (this.peek().isType(Token.PRIVATE_NAME)) {
1741
2098
  const x = this.parsePropertyOrPrivatePropertyName();
1742
2099
  const precedence1 = Token.precedence(this.peek().token, this.acceptIN);
@@ -1753,6 +2110,18 @@ export class JavaScriptInlineParser extends AbstractParser {
1753
2110
  return x;
1754
2111
  }
1755
2112
  parseUnaryExpression() {
2113
+ // UnaryExpression ::
2114
+ // PostfixExpression
2115
+ // 'delete' UnaryExpression
2116
+ // 'void' UnaryExpression
2117
+ // 'typeof' UnaryExpression
2118
+ // '++' UnaryExpression
2119
+ // '--' UnaryExpression
2120
+ // '+' UnaryExpression
2121
+ // '-' UnaryExpression
2122
+ // '~' UnaryExpression
2123
+ // '!' UnaryExpression
2124
+ // [+Await] AwaitExpression[?Yield]
1756
2125
  const op = this.peek();
1757
2126
  if (Token.isUnaryOrCount(op.token)) {
1758
2127
  return this.parseUnaryOrPrefixExpression();
@@ -1768,6 +2137,7 @@ export class JavaScriptInlineParser extends AbstractParser {
1768
2137
  if (Token.isUnary(op.token)) {
1769
2138
  if (op.isType(Token.DELETE)) {
1770
2139
  if (this.isIdentifier(expression) && isStrict(this.languageMode)) {
2140
+ // "delete identifier" is a syntax error in strict mode.
1771
2141
  throw new Error(this.errorMessage(`"delete identifier" is a syntax error in strict mode`));
1772
2142
  }
1773
2143
  if (expression instanceof MemberExpression && expression.getProperty().toString().startsWith('#')) {
@@ -1779,11 +2149,14 @@ export class JavaScriptInlineParser extends AbstractParser {
1779
2149
  }
1780
2150
  }
1781
2151
  if (Token.isCount(op.token) || Token.isUnary(op.token)) {
2152
+ // Allow the parser to rewrite the expression.
1782
2153
  return buildUnaryExpression(expression, op.token);
1783
2154
  }
1784
2155
  throw new Error(this.errorMessage(`while rewrite unary operation`));
1785
2156
  }
1786
2157
  parsePostfixExpression() {
2158
+ // PostfixExpression ::
2159
+ // LeftHandSideExpression ('++' | '--')?
1787
2160
  const expression = this.parseLeftHandSideExpression();
1788
2161
  if (!Token.isCount(this.peek().token) || this.scanner.hasLineTerminatorBeforeNext()) {
1789
2162
  return expression;
@@ -1798,6 +2171,8 @@ export class JavaScriptInlineParser extends AbstractParser {
1798
2171
  return buildPostfixExpression(expression, op.token);
1799
2172
  }
1800
2173
  parseLeftHandSideExpression() {
2174
+ // LeftHandSideExpression ::
2175
+ // (NewExpression | MemberExpression) ...
1801
2176
  const result = this.parseMemberExpression();
1802
2177
  if (!Token.isPropertyOrCall(this.peek().token))
1803
2178
  return result;
@@ -1810,8 +2185,10 @@ export class JavaScriptInlineParser extends AbstractParser {
1810
2185
  && !this.scanner.hasLineTerminatorBeforeNext()) {
1811
2186
  const args = this.parseArguments(ParsingArrowHeadFlag.AsyncArrowFunction);
1812
2187
  if (this.peek().isType(Token.ARROW)) {
2188
+ // async () => ...
1813
2189
  if (!args.length)
1814
2190
  return new EmptyStatement;
2191
+ // async ( Arguments ) => ...
1815
2192
  return this.expressionListToExpression(args);
1816
2193
  }
1817
2194
  result = new CallExpression(result, args);
@@ -1822,6 +2199,7 @@ export class JavaScriptInlineParser extends AbstractParser {
1822
2199
  let isOptional = false;
1823
2200
  do {
1824
2201
  switch (this.peek().token) {
2202
+ // chain
1825
2203
  case Token.QUESTION_PERIOD: {
1826
2204
  if (isOptional) {
1827
2205
  throw new Error(this.errorMessage(`Failure Expression`));
@@ -1835,6 +2213,7 @@ export class JavaScriptInlineParser extends AbstractParser {
1835
2213
  result = new MemberExpression(result, key, false, isOptional);
1836
2214
  break;
1837
2215
  }
2216
+ /* Property */
1838
2217
  case Token.LBRACK: {
1839
2218
  this.consume(Token.LBRACK);
1840
2219
  this.setAcceptIN(true);
@@ -1844,6 +2223,7 @@ export class JavaScriptInlineParser extends AbstractParser {
1844
2223
  this.expect(Token.RBRACK);
1845
2224
  break;
1846
2225
  }
2226
+ /* Property */
1847
2227
  case Token.PERIOD: {
1848
2228
  if (isOptional) {
1849
2229
  throw new Error(this.errorMessage(`Unexpected Token:${this.position()}`));
@@ -1853,11 +2233,13 @@ export class JavaScriptInlineParser extends AbstractParser {
1853
2233
  result = new MemberExpression(result, key, false, isOptional);
1854
2234
  break;
1855
2235
  }
2236
+ /* Call */
1856
2237
  case Token.LPAREN: {
1857
2238
  const args = this.parseArguments();
1858
2239
  result = new CallExpression(result, args, isOptional);
1859
2240
  break;
1860
2241
  }
2242
+ /* bind call */
1861
2243
  case Token.BIND: {
1862
2244
  if (isOptional) {
1863
2245
  throw new Error(this.errorMessage(`Unexpected Token:${this.position()}`));
@@ -1867,6 +2249,7 @@ export class JavaScriptInlineParser extends AbstractParser {
1867
2249
  result = new BindExpression(result, key, false, isOptional);
1868
2250
  break;
1869
2251
  }
2252
+ /* chain bind call */
1870
2253
  case Token.QUESTION_BIND: {
1871
2254
  if (isOptional) {
1872
2255
  throw new Error(this.errorMessage(`Failure Expression`));
@@ -1879,9 +2262,11 @@ export class JavaScriptInlineParser extends AbstractParser {
1879
2262
  break;
1880
2263
  }
1881
2264
  default:
2265
+ // Template literals in/after an Optional Chain not supported:
1882
2266
  if (optionalChaining) {
1883
2267
  throw new Error(this.errorMessage(`Optional Chaining No Template support`));
1884
2268
  }
2269
+ /* Tagged Template */
1885
2270
  result = this.parseTemplateLiteral(result);
1886
2271
  break;
1887
2272
  }
@@ -1903,10 +2288,19 @@ export class JavaScriptInlineParser extends AbstractParser {
1903
2288
  return buildUnaryExpression(value, Token.AWAIT);
1904
2289
  }
1905
2290
  parseNullishExpression(expression) {
2291
+ // CoalesceExpression ::
2292
+ // CoalesceExpressionHead ?? BitwiseORExpression
2293
+ //
2294
+ // CoalesceExpressionHead ::
2295
+ // CoalesceExpression
2296
+ // BitwiseORExpression
2297
+ // We create a binary operation for the first nullish, otherwise collapse
2298
+ // into an nary expression.
1906
2299
  const list = [];
1907
2300
  list.push(expression);
1908
2301
  while (this.peek().isType(Token.NULLISH)) {
1909
2302
  this.consume(Token.NULLISH);
2303
+ // Parse BitwiseOR or higher.
1910
2304
  expression = this.parseBinaryExpression(6);
1911
2305
  list.push(expression);
1912
2306
  }
@@ -1925,8 +2319,10 @@ export class JavaScriptInlineParser extends AbstractParser {
1925
2319
  return new ConditionalExpression(expression, left, right);
1926
2320
  }
1927
2321
  parseYieldExpression() {
2322
+ // YieldExpression ::
2323
+ // 'yield' ([no line terminator] '*'? AssignmentExpression)?
1928
2324
  this.consume(Token.YIELD);
1929
- let delegating = false;
2325
+ let delegating = false; // yield*
1930
2326
  let expression;
1931
2327
  if (!this.scanner.hasLineTerminatorBeforeNext()) {
1932
2328
  if (this.check(Token.MUL)) {
@@ -1941,8 +2337,14 @@ export class JavaScriptInlineParser extends AbstractParser {
1941
2337
  case Token.COLON:
1942
2338
  case Token.COMMA:
1943
2339
  case Token.IN:
2340
+ // The above set of tokens is the complete set of tokens that can appear
2341
+ // after an AssignmentExpression, and none of them can start an
2342
+ // AssignmentExpression. This allows us to avoid looking for an RHS for
2343
+ // a regular yield, given only one look-ahead token.
1944
2344
  if (!delegating)
1945
2345
  break;
2346
+ // Delegating yields require an RHS; fall through.
2347
+ // V8_FALLTHROUGH;
1946
2348
  throw new Error(this.errorMessage(`Delegating yields require an RHS`));
1947
2349
  default:
1948
2350
  expression = this.parseAssignmentExpressionCoverGrammar();