diff --git a/docs/acorn.html b/docs/acorn.html index 9a8c3459e7..16abf53e11 100644 --- a/docs/acorn.html +++ b/docs/acorn.html @@ -28,9 +28,10 @@

Acorn is a tiny, fast JavaScript parser written in JavaScript.

-

Acorn was written by Marijn Haverbeke and released under an MIT -license. The Unicode regexps (for identifiers and whitespace) were -taken from Esprima by Ariya Hidayat.

+

Acorn was written by Marijn Haverbeke and various contributors and +released under an MIT license. The Unicode regexps (for identifiers +and whitespace) were taken from Esprima by +Ariya Hidayat.

Git repositories for Acorn are available at

http://marijnhaverbeke.nl/git/acorn
 https://github.com/marijnh/acorn.git
@@ -49,7 +50,7 @@ with a error-tolerant parser and an
 })(this, function(exports) {
   "use strict";
 
-  exports.version = "0.6.1";
+ exports.version = "0.7.1"; @@ -205,6 +206,25 @@ nodes.

+

A function can be passed as onToken option, which will +cause Acorn to call that function with object in the same +format as tokenize() returns. Note that you are not +allowed to call the parser from the callback—that will +corrupt its internal state.

+ + + +
    onToken: null,
+ + + + +
  • +
    + +
    + +

    A function can be passed as onComment option, which will cause Acorn to call that function with (block, text, start, end) parameters whenever a comment is skipped. block is a @@ -223,11 +243,11 @@ parser from the callback—that will corrupt its internal state.

  • -
  • +
  • - +

    Nodes have their start and end characters offsets recorded in start and end properties (directly on the node, rather than @@ -243,11 +263,11 @@ end] array with the same numbers, set the ranges option to

  • -
  • +
  • - +

    It is possible to parse multiple files into a single AST by passing the tree produced by parsing the first file as @@ -262,11 +282,11 @@ of an existing parse tree.

  • -
  • +
  • - +

    When locations is on, you can pass this to record the source file in every node’s loc object.

    @@ -278,11 +298,11 @@ file in every node’s loc object.

  • -
  • +
  • - +

    This value, if given, is stored in every node, whether locations is on or off.

    @@ -292,23 +312,51 @@ file in every node’s loc object.

        directSourceFile: null
       };
     
    +  var isArray = function (obj) {
    +    return Object.prototype.toString.call(obj) === "[object Array]";
    +  };
    +
       function setOptions(opts) {
         options = opts || {};
    -    for (var opt in defaultOptions) if (!Object.prototype.hasOwnProperty.call(options, opt))
    +    for (var opt in defaultOptions) if (!has(options, opt))
           options[opt] = defaultOptions[opt];
         sourceFile = options.sourceFile || null;
    -
    +    if (isArray(options.onToken)) {
    +      var tokens = options.onToken;
    +      options.onToken = function (token) {
    +        tokens.push(token);
    +      };
    +    }
    +    if (isArray(options.onComment)) {
    +      var comments = options.onComment;
    +      options.onComment = function (block, text, start, end, startLoc, endLoc) {
    +        var comment = {
    +          type: block ? 'Block' : 'Line',
    +          value: text,
    +          start: start,
    +          end: end
    +        };
    +        if (options.locations) {
    +          comment.loc = new SourceLocation();
    +          comment.loc.start = startLoc;
    +          comment.loc.end = endLoc;
    +        }
    +        if (options.ranges)
    +          comment.range = [start, end];
    +        comments.push(comment);
    +      };
    +    }
         isKeyword = options.ecmaVersion >= 6 ? isEcma6Keyword : isEcma5AndLessKeyword;
       }
  • -
  • +
  • - +

    The getLineInfo function is mostly useful when the locations option is off (for performance reasons) and you @@ -329,16 +377,47 @@ into.

    } else break; } return {line: line, column: offset - cur}; - };
    + }; + + function Token() { + this.type = tokType; + this.value = tokVal; + this.start = tokStart; + this.end = tokEnd; + if (options.locations) { + this.loc = new SourceLocation(); + this.loc.end = tokEndLoc;
  • -
  • +
  • - + +
    +

    TODO: remove in next major release

    + +
    + +
          this.startLoc = tokStartLoc;
    +      this.endLoc = tokEndLoc;
    +    }
    +    if (options.ranges)
    +      this.range = [tokStart, tokEnd];
    +  }
    +
    +  exports.Token = Token;
    + +
  • + + +
  • +
    + +
    +

    Acorn is organized as a tokenizer and a recursive-descent parser. The tokenize export provides an interface to the tokenizer. @@ -355,14 +434,10 @@ reset the internal state, and invalidate existing tokenizers.

    setOptions(opts); initTokenState(); - var t = {}; function getToken(forceRegexp) { lastEnd = tokEnd; readToken(forceRegexp); - t.start = tokStart; t.end = tokEnd; - t.startLoc = tokStartLoc; t.endLoc = tokEndLoc; - t.type = tokType; t.value = tokVal; - return t; + return new Token(); } getToken.jumpTo = function(pos, reAllowed) { tokPos = pos; @@ -384,11 +459,11 @@ reset the internal state, and invalidate existing tokenizers.

  • -
  • +
  • - +

    State is kept in (closure-)global variables. We already saw the options, input, and inputLen variables above.

    @@ -398,11 +473,11 @@ reset the internal state, and invalidate existing tokenizers.

  • -
  • +
  • - +

    The current position of the tokenizer in the input.

    @@ -414,11 +489,11 @@ reset the internal state, and invalidate existing tokenizers.

  • -
  • +
  • - +

    The start and end offsets of the current token.

    @@ -430,11 +505,11 @@ reset the internal state, and invalidate existing tokenizers.

  • -
  • +
  • - +

    When options.locations is true, these hold objects containing the tokens start and end line/column pairs.

    @@ -447,11 +522,11 @@ containing the tokens start and end line/column pairs.

  • -
  • +
  • - +

    The type and value of the current token. Token types are objects, named by variables against which they can be compared, and @@ -469,11 +544,11 @@ for operators, the operator name, and so on.

  • -
  • +
  • - +

    Internal state for the tokenizer. To distinguish between division operators and regular expressions, it remembers whether the last @@ -490,11 +565,11 @@ caveat.)

  • -
  • +
  • - +

    When options.locations is true, these are used to keep track of the current line, and know when a new line has been @@ -508,11 +583,11 @@ entered.

  • -
  • +
  • - +

    These store the position of the previous token, which is useful when finishing a node and assigning its end position.

    @@ -525,11 +600,11 @@ when finishing a node and assigning its end position.

  • -
  • +
  • - +

    This is the parser’s state. inFunction is used to reject return statements outside of functions, inGenerator to @@ -545,11 +620,11 @@ that break and continue have somewhere to jump to, and

  • -
  • +
  • - +

    This counter is used for checking that arrow expressions did not contain nested parentheses in argument list.

    @@ -562,11 +637,11 @@ not contain nested parentheses in argument list.

  • -
  • +
  • - +

    This is used by parser for detecting if it’s inside ES6 Template String. If it is, it should treat ‘$’ as prefix before @@ -575,16 +650,16 @@ Template String. If it is, it should treat ‘$’ as prefix before

    -  var inTemplate = false;
    + var inTemplate;
  • -
  • +
  • - +

    This function is used to raise exceptions on parse errors. It takes an offset integer (into the current input) to indicate @@ -606,11 +681,11 @@ message.

  • -
  • +
  • - +

    Reused empty array added for node fields that are always empty.

    @@ -622,42 +697,13 @@ message.

  • -
  • -
    - -
    - -
    -

    Token types

    - -
    - -
  • - - -
  • -
    - -
    - -
    -

    The assignment of fine-grained, information-carrying type objects -allows the tokenizer to store the information it has about a -token in a way that is very cheap for the parser to look up.

    - -
    - -
  • - -
  • -

    All token type variables start with an underscore, to make them -easy to recognize.

    +

    Token types

    @@ -670,6 +716,35 @@ easy to recognize.

    +

    The assignment of fine-grained, information-carrying type objects +allows the tokenizer to store the information it has about a +token in a way that is very cheap for the parser to look up.

    + + + +
  • + + +
  • +
    + +
    + +
    +

    All token type variables start with an underscore, to make them +easy to recognize.

    + +
    + +
  • + + +
  • +
    + +
    + +

    These are the general types. The type property is only used to make them recognizeable when debugging.

    @@ -682,11 +757,11 @@ make them recognizeable when debugging.

  • -
  • +
  • - +

    These are JSX-specific token types

    @@ -698,11 +773,11 @@ make them recognizeable when debugging.

  • -
  • +
  • - +

    Keyword tokens. The keyword property (also used in keyword-like operators) indicates that the token originated from an @@ -734,11 +809,11 @@ continue jumps to that label.

  • -
  • +
  • - +

    The keywords that denote values.

    @@ -751,11 +826,11 @@ continue jumps to that label.

  • -
  • +
  • - +

    Some keywords are treated as regular operators. in sometimes (when parsing for) needs to be tested against specifically, so @@ -769,11 +844,11 @@ we assign a variable name to it for quick comparing.

  • -
  • +
  • - +

    Map keyword names to token types.

    @@ -797,11 +872,11 @@ we assign a variable name to it for quick comparing.

  • -
  • +
  • - +

    Punctuation token types. Again, the type property is purely for debugging.

    @@ -818,11 +893,11 @@ we assign a variable name to it for quick comparing.

  • -
  • +
  • - +

    Operators. These carry several kinds of properties to help the parser use them properly (the presence of these properties is @@ -852,16 +927,16 @@ in AssignmentExpression nodes.

    var _relational = {binop: 7, beforeExpr: true}; var _bitShift = {binop: 8, beforeExpr: true}; var _plusMin = {binop: 9, prefix: true, beforeExpr: true}; - var _multiplyModulo = {binop: 10, beforeExpr: true};
    + var _modulo = {binop: 10, beforeExpr: true};
  • -
  • +
  • - +

    ‘*’ may be multiply or have special meaning in ES6

    @@ -872,11 +947,11 @@ in AssignmentExpression nodes.

  • -
  • +
  • - +

    ‘<’, ‘>’ may be relational or have special meaning in JSX

    @@ -887,11 +962,11 @@ in AssignmentExpression nodes.

  • -
  • +
  • - +

    Provide access to the token types for external users of the tokenizer.

    @@ -910,11 +985,11 @@ tokenizer.

  • -
  • +
  • - +

    This is a trick taken from Esprima. It turns out that, on non-Chrome browsers, to check whether a string is in a set, a @@ -948,11 +1023,11 @@ predicate from a space-separated string of words.

  • -
  • +
  • - +

    When there are more than three length categories, an outer switch first dispatches on the lengths, to save on comparisons.

    @@ -973,11 +1048,11 @@ switch first dispatches on the lengths, to save on comparisons.

  • -
  • +
  • - +

    Otherwise, simply generate a flat switch statement.

    @@ -993,11 +1068,11 @@ switch first dispatches on the lengths, to save on comparisons.

  • -
  • +
  • - +

    The ECMAScript 3 reserved word list.

    @@ -1009,11 +1084,11 @@ switch first dispatches on the lengths, to save on comparisons.

  • -
  • +
  • - +

    ECMAScript 5 reserved words.

    @@ -1025,11 +1100,11 @@ switch first dispatches on the lengths, to save on comparisons.

  • -
  • +
  • - +

    The additional reserved words in strict mode.

    @@ -1041,11 +1116,11 @@ switch first dispatches on the lengths, to save on comparisons.

  • -
  • +
  • - +

    The forbidden variable names in strict mode.

    @@ -1057,11 +1132,11 @@ switch first dispatches on the lengths, to save on comparisons.

  • -
  • +
  • - +

    And the keywords.

    @@ -1079,11 +1154,11 @@ switch first dispatches on the lengths, to save on comparisons.

  • -
  • +
  • - +

    Character categories

    @@ -1092,11 +1167,11 @@ switch first dispatches on the lengths, to save on comparisons.

  • -
  • +
  • - +

    Big ugly regular expressions that match characters in the whitespace, identifier, and identifier-start categories. These @@ -1116,11 +1191,11 @@ Generated by tools/generate-identifier-regex.js.

  • -
  • +
  • - +

    Whether a single character denotes a newline.

    @@ -1132,11 +1207,11 @@ Generated by tools/generate-identifier-regex.js.

  • -
  • +
  • - +

    Matches a whole line break (where CRLF is considered a single line break). Used to count lines.

    @@ -1149,11 +1224,11 @@ line break). Used to count lines.

  • -
  • +
  • - +

    Test whether a given character code starts an identifier.

    @@ -1171,11 +1246,11 @@ line break). Used to count lines.

  • -
  • +
  • - +

    Test whether a given character is part of an identifier.

    @@ -1195,11 +1270,11 @@ line break). Used to count lines.

  • -
  • +
  • - +

    Tokenizer

    @@ -1208,11 +1283,11 @@ line break). Used to count lines.

  • -
  • +
  • - +

    These are used when options.locations is on, for the tokStartLoc and tokEndLoc properties.

    @@ -1228,11 +1303,11 @@ line break). Used to count lines.

  • -
  • +
  • - +

    Reset the token state. Used at the start of a parse.

    @@ -1251,11 +1326,11 @@ line break). Used to count lines.

  • -
  • +
  • - +

    Called at the end of every token. Sets tokEnd, tokVal, and tokRegexpAllowed, and skips the space after the token, so that @@ -1264,15 +1339,18 @@ the next one’s tokStart will point at the right position.

    -  function finishToken(type, val) {
    +  function finishToken(type, val, shouldSkipSpace) {
         tokEnd = tokPos;
         if (options.locations) tokEndLoc = new Position;
         tokType = type;
    -    if (inTemplate || type !== _bquote && !(inXJSTag && type === _gt) && !(inXJSChild && tokType !== _braceL)) {
    +    if (shouldSkipSpace !== false && !(inXJSTag && type === _gt) && !(inXJSChild && tokType !== _braceL)) {
           skipSpace();
         }
         tokVal = val;
         tokRegexpAllowed = type.beforeExpr;
    +    if (options.onToken) {
    +      options.onToken(new Token());
    +  }
       }
     
       function skipBlockComment() {
    @@ -1293,27 +1371,27 @@ the next one’s tokStart will point at the right position.

    startLoc, options.locations && new Position); } - function skipLineComment() { + function skipLineComment(startSkip) { var start = tokPos; var startLoc = options.onComment && options.locations && new Position; - var ch = input.charCodeAt(tokPos+=2); + var ch = input.charCodeAt(tokPos+=startSkip); while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { ++tokPos; ch = input.charCodeAt(tokPos); } if (options.onComment) - options.onComment(false, input.slice(start + 2, tokPos), start, tokPos, + options.onComment(false, input.slice(start + startSkip, tokPos), start, tokPos, startLoc, options.locations && new Position); }
  • -
  • +
  • - +

    Called at the start of the parse and after every token. Skips whitespace and comments, and.

    @@ -1349,7 +1427,7 @@ whitespace and comments, and.

    if (next === 42) { // '*' skipBlockComment(); } else if (next === 47) { // '/' - skipLineComment(); + skipLineComment(2); } else break; } else if (ch === 160) { // '\xa0' ++tokPos; @@ -1364,11 +1442,11 @@ whitespace and comments, and.

  • -
  • +
  • - +

    Token reading

    @@ -1377,11 +1455,11 @@ whitespace and comments, and.

  • -
  • +
  • - +

    This is the function that is called to fetch the next token. It is somewhat obscure, because it works in character codes rather @@ -1417,7 +1495,7 @@ into it.

    function readToken_mult_modulo(code) { // '%*' var next = input.charCodeAt(tokPos + 1); if (next === 61) return finishOp(_assign, 2); - return finishOp(code === 42 ? _star : _multiplyModulo, 1); + return finishOp(code === 42 ? _star : _modulo, 1); } function readToken_pipe_amp(code) { // '|&' @@ -1442,18 +1520,17 @@ into it.

  • -
  • +
  • - +

    A --> line comment

    -
            tokPos += 3;
    -        skipLineComment();
    +            
            skipLineComment(3);
             skipSpace();
             return readToken();
           }
    @@ -1477,18 +1554,17 @@ into it.

  • -
  • +
  • - +

    <!--, an XML-style comment that should be interpreted as a line comment

    -
          tokPos += 4;
    -      skipLineComment();
    +            
          skipLineComment(4);
           skipSpace();
           return readToken();
         }
    @@ -1501,11 +1577,11 @@ into it.

  • -
  • +
  • - +

    ‘</‘, beginning of JSX closing element

    @@ -1525,48 +1601,7 @@ into it.

    return finishToken(_arrow); } return finishOp(code === 61 ? _eq : _prefix, 1); - } - - function getTokenFromCode(code) {
    - -
  • - - -
  • -
    - -
    - -
    -

    Special rules work inside ES6 template strings.

    - -
    - -
        if (inTemplate) {
    - -
  • - - -
  • -
    - -
    - -
    -

    ‘`’ and ‘${‘ have special meanings, but they should follow string (can be empty)

    - -
    - -
          if (tokType === _string) {
    -        if (code === 96) { // '`'
    -          ++tokPos;
    -          return finishToken(_bquote);
    -        }
    -        if (code === 36 && input.charCodeAt(tokPos + 1) === 123) { // '${'
    -          tokPos += 2;
    -          return finishToken(_dollarBraceL);
    -        }
    -      }
    + }
  • @@ -1577,14 +1612,12 @@ into it.

    -

    anything else is considered string literal

    +

    Get token inside ES6 template (special rules work there).

    -
          return readString();
    -    }
    -
    -    switch(code) {
    +
    +  function getTemplateToken(code) {
    @@ -1595,6 +1628,55 @@ into it.

    +

    ‘`’ and ‘${‘ have special meanings, but they should follow +string (can be empty)

    + + + +
          if (tokType === _string) {
    +        if (code === 96) { // '`'
    +          ++tokPos;
    +          return finishToken(_bquote);
    +      } else
    +        if (code === 36 && input.charCodeAt(tokPos + 1) === 123) { // '${'
    +          tokPos += 2;
    +          return finishToken(_dollarBraceL);
    +        }
    +      }
    +
    +    if (code === 125) { // '}'
    +      ++tokPos;
    +      return finishToken(_braceR, undefined, false);
    +    }
    + + + + +
  • +
    + +
    + +
    +

    anything else is considered string literal

    + +
    + +
        return readTmplString();
    +    }
    +
    +  function getTokenFromCode(code) {
    +    switch(code) {
    + +
  • + + +
  • +
    + +
    + +

    The interpretation of a dot depends on whether it is followed by a digit or another two dots.

    @@ -1606,11 +1688,11 @@ by a digit or another two dots.

  • -
  • +
  • - +

    Punctuation tokens.

    @@ -1630,7 +1712,7 @@ by a digit or another two dots.

    case 96: // '`' if (options.ecmaVersion >= 6) { ++tokPos; - return finishToken(_bquote); + return finishToken(_bquote, undefined, false); } case 48: // '0' @@ -1644,11 +1726,11 @@ by a digit or another two dots.

  • -
  • +
  • - +

    Anything else beginning with a digit is an integer, octal number, or float.

    @@ -1661,11 +1743,11 @@ number, or float.

  • -
  • +
  • - +

    Quotes produce strings.

    @@ -1677,11 +1759,11 @@ number, or float.

  • -
  • +
  • - +

    Operators are parsed inline in tiny state machines. ‘=’ (61) is often referred to. finishOp simply skips the amount of @@ -1731,11 +1813,11 @@ of the type given by its first argument.

  • -
  • +
  • - +

    JSX content - either simple text, start of or {expression}

    @@ -1743,23 +1825,26 @@ of the type given by its first argument.

        if (inXJSChild && tokType !== _braceL && code !== 60 && code !== 123 && code !== 125) {
           return readXJSText(['<', '{']);
    -    }
    + } + + + if (inTemplate) return getTemplateToken(code);
  • -
  • +
  • - +

    Identifier or keyword. ‘\uXXXX’ sequences are allowed in identifiers, so ‘\’ also dispatches to that.

    -
        if (!inTemplate && (isIdentifierStart(code) || code === 92 /* '\' */)) return readWord();
    +            
        if (isIdentifierStart(code) || code === 92 /* '\' */) return readWord();
     
         var tok = getTokenFromCode(code);
     
    @@ -1768,11 +1853,11 @@ identifiers, so ‘\’ also dispatches to that.

  • -
  • +
  • - +

    If we are here, we either found a non-ASCII identifier character, or something that’s entirely disallowed.

    @@ -1795,11 +1880,11 @@ character, or something that’s entirely disallowed.

  • -
  • +
  • - +

    Parse a regular expression. Some context-awareness is necessary, since a ‘/‘ inside a ‘[]’ set does not end the expression.

    @@ -1811,7 +1896,7 @@ since a ‘/‘ inside a ‘[]’ set does not end the expression.

    var content = "", escaped, inClass, start = tokPos; for (;;) { if (tokPos >= inputLen) raise(start, "Unterminated regular expression"); - var ch = input.charAt(tokPos); + var ch = nextChar(); if (newline.test(ch)) raise(start, "Unterminated regular expression"); if (!escaped) { if (ch === "[") inClass = true; @@ -1827,11 +1912,11 @@ since a ‘/‘ inside a ‘[]’ set does not end the expression.

  • -
  • +
  • - +

    Need to use readWord1 because ‘\uXXXX’ sequences are allowed here (don’t ask).

    @@ -1852,11 +1937,11 @@ here (don’t ask).

  • -
  • +
  • - +

    Read an integer in the given radix. Return null if zero digits were read, the integer value otherwise. When len is given, this @@ -1893,11 +1978,11 @@ will return null unless the integer has exactly len di

  • -
  • +
  • - +

    Read an integer, octal integer, or floating-point number.

    @@ -1932,11 +2017,11 @@ will return null unless the integer has exactly len di
  • -
  • +
  • - +

    Read a string value, interpreting backslash-escapes.

    @@ -1959,11 +2044,11 @@ will return null unless the integer has exactly len di
  • -
  • +
  • - +

    UTF-16 Encoding

    @@ -1978,52 +2063,39 @@ will return null unless the integer has exactly len di } function readString(quote) { - if (!inTemplate) tokPos++; + ++tokPos; var out = ""; for (;;) { if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant"); var ch = input.charCodeAt(tokPos); - if (inTemplate) { - if (ch === 96 || ch === 36 && input.charCodeAt(tokPos + 1) === 123) // '`', '${' - return finishToken(_string, out); - } else if (ch === quote) { + if (ch === quote) { ++tokPos; return finishToken(_string, out); } if (ch === 92) { // '\' - ch = input.charCodeAt(++tokPos); - var octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3)); - if (octal) octal = octal[0]; - while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1); - if (octal === "0") octal = null; - ++tokPos; - if (octal) { - if (strict) raise(tokPos - 2, "Octal literal in strict mode"); - out += String.fromCharCode(parseInt(octal, 8)); - tokPos += octal.length - 1; - } else { - switch (ch) { - case 110: out += "\n"; break; // 'n' -> '\n' - case 114: out += "\r"; break; // 'r' -> '\r' - case 120: out += String.fromCharCode(readHexChar(2)); break; // 'x' - case 117: out += readCodePoint(); break; // 'u' - case 85: out += String.fromCharCode(readHexChar(8)); break; // 'U' - case 116: out += "\t"; break; // 't' -> '\t' - case 98: out += "\b"; break; // 'b' -> '\b' - case 118: out += "\u000b"; break; // 'v' -> '\u000b' - case 102: out += "\f"; break; // 'f' -> '\f' - case 48: out += "\0"; break; // 0 -> '\0' - case 13: if (input.charCodeAt(tokPos) === 10) ++tokPos; // '\r\n' - case 10: // ' \n' - if (options.locations) { tokLineStart = tokPos; ++tokCurLine; } - break; - default: out += String.fromCharCode(ch); break; - } - } + out += readEscapedChar(); + } else { + ++tokPos; + if (newline.test(String.fromCharCode(ch))) { + raise(tokStart, "Unterminated string constant"); + } + out += String.fromCharCode(ch); // '\' + } + } + } + + function readTmplString() { + var out = ""; + for (;;) { + if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant"); + var ch = input.charCodeAt(tokPos); + if (ch === 96 || ch === 36 && input.charCodeAt(tokPos + 1) === 123) // '`', '${' + return finishToken(_string, out); + if (ch === 92) { // '\' + out += readEscapedChar(); } else { ++tokPos; if (newline.test(String.fromCharCode(ch))) { - if (inTemplate) { if (ch === 13 && input.charCodeAt(tokPos) === 10) { ++tokPos; ch = 10; @@ -2032,13 +2104,56 @@ will return null unless the integer has exactly len di ++tokCurLine; tokLineStart = tokPos; } - } else { - raise(tokStart, "Unterminated string constant"); } - } out += String.fromCharCode(ch); // '\' } } + }
    + +
  • + + +
  • +
    + +
    + +
    +

    Used to read escaped characters

    + +
    + +
    +  function readEscapedChar() {
    +    var ch = input.charCodeAt(++tokPos);
    +    var octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3));
    +    if (octal) octal = octal[0];
    +    while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1);
    +    if (octal === "0") octal = null;
    +    ++tokPos;
    +    if (octal) {
    +      if (strict) raise(tokPos - 2, "Octal literal in strict mode");
    +      tokPos += octal.length - 1;
    +      return String.fromCharCode(parseInt(octal, 8));
    +    } else {
    +      switch (ch) {
    +        case 110: return "\n"; // 'n' -> '\n'
    +        case 114: return "\r"; // 'r' -> '\r'
    +        case 120: return String.fromCharCode(readHexChar(2)); // 'x'
    +        case 117: return readCodePoint(); // 'u'
    +        case 85: return String.fromCharCode(readHexChar(8)); // 'U'
    +        case 116: return "\t"; // 't' -> '\t'
    +        case 98: return "\b"; // 'b' -> '\b'
    +        case 118: return "\u000b"; // 'v' -> '\u000b'
    +        case 102: return "\f"; // 'f' -> '\f'
    +        case 48: return "\0"; // 0 -> '\0'
    +        case 13: if (input.charCodeAt(tokPos) === 10) ++tokPos; // '\r\n'
    +        case 10: // ' \n'
    +          if (options.locations) { tokLineStart = tokPos; ++tokCurLine; }
    +          return "";
    +        default: return String.fromCharCode(ch);
    +      }
    +    }
       }
     
       var XHTMLEntities = {
    @@ -2303,7 +2418,8 @@ will return null unless the integer has exactly len di
         if (ch !== '&') raise(tokPos, "Entity must start with an ampersand");
         tokPos++;
         while (tokPos < inputLen && count++ < 10) {
    -      ch = input.charAt(tokPos++);
    +      ch = nextChar();
    +      tokPos++;
           if (ch === ';') {
             break;
           }
    @@ -2371,11 +2487,11 @@ will return null unless the integer has exactly len di
             
  • -
  • +
  • - +

    Used to read character escape sequences (‘\x’, ‘\u’, ‘\U’).

    @@ -2391,11 +2507,11 @@ will return null unless the integer has exactly len di
  • -
  • +
  • - +

    Used to signal to callers of readWord1 whether the word contained any escape sequences. This is needed because words with @@ -2409,11 +2525,11 @@ escape sequences must not be interpreted as keywords.

  • -
  • +
  • - +

    Read an identifier, and return it as a string. Sets containsEsc to whether the word contained a ‘\u’ escape.

    @@ -2429,7 +2545,7 @@ containeds an escape, as a micro-optimization.

    for (;;) { var ch = input.charCodeAt(tokPos); if (isIdentifierChar(ch) || (inXJSTag && ch === 45)) { - if (containsEsc) word += input.charAt(tokPos); + if (containsEsc) word += nextChar(); ++tokPos; } else if (ch === 92 && !inXJSTag) { // "\" if (!containsEsc) word = input.slice(start, tokPos); @@ -2454,11 +2570,11 @@ containeds an escape, as a micro-optimization.

  • -
  • +
  • - +

    Read an identifier or keyword token. Will check for reserved words when necessary.

    @@ -2477,11 +2593,11 @@ words when necessary.

  • -
  • +
  • - +

    Parser

    @@ -2490,11 +2606,11 @@ words when necessary.

  • -
  • +
  • - +

    A recursive descent parser operates by defining functions for all syntactic elements, and recursively calling those, each function @@ -2516,11 +2632,11 @@ precedence levels that JavaScript defines.

  • -
  • +
  • - +

    Parser utilities

    @@ -2529,11 +2645,11 @@ precedence levels that JavaScript defines.

  • -
  • +
  • - +

    Continue to the next token.

    @@ -2550,11 +2666,11 @@ precedence levels that JavaScript defines.

  • -
  • +
  • - +

    Enter strict mode. Re-reads the next token to please pedantic tests (“use strict”; 010; — should fail).

    @@ -2578,11 +2694,11 @@ tests (“use strict”; 010; — should fail).

  • -
  • +
  • - +

    Start an AST node, attaching a start offset.

    @@ -2617,11 +2733,11 @@ tests (“use strict”; 010; — should fail).

  • -
  • +
  • - +

    Start a node whose start offset information should be based on the start of another node. For example, a binary operator node is @@ -2646,11 +2762,11 @@ only started after its left-hand side has already been parsed.

  • -
  • +
  • - +

    Finish an AST node, adding type and end properties.

    @@ -2670,11 +2786,11 @@ only started after its left-hand side has already been parsed.

  • -
  • +
  • - +

    Test whether a statement node is the string literal "use strict".

    @@ -2689,11 +2805,11 @@ only started after its left-hand side has already been parsed.

  • -
  • +
  • - +

    Predicate that tests whether the next token is of the given type, and if yes, consumes it as a side effect.

    @@ -2713,11 +2829,11 @@ type, and if yes, consumes it as a side effect.

  • -
  • +
  • - +

    Test whether a semicolon can be inserted at the current position.

    @@ -2732,11 +2848,11 @@ type, and if yes, consumes it as a side effect.

  • -
  • +
  • - +

    Consume a semicolon, or, failing that, see if we are allowed to pretend that there is a semicolon at this position.

    @@ -2751,11 +2867,11 @@ pretend that there is a semicolon at this position.

  • -
  • +
  • - +

    Expect a token of a given type. If found, consume it, otherwise, raise an unexpected token error.

    @@ -2770,31 +2886,11 @@ raise an unexpected token error.

  • -
  • +
  • - -
    -

    Expect a char. If found, consume it, otherwise, -raise an unexpected token error.

    - -
    - -
    -  function expectChar(ch) {
    -    if (tokVal === ch) next();
    -    else unexpected();
    -  }
    - -
  • - - -
  • -
    - -
    - +

    Get following char.

    @@ -2808,11 +2904,11 @@ raise an unexpected token error.

  • -
  • +
  • - +

    Raise an unexpected token error.

    @@ -2826,29 +2922,29 @@ raise an unexpected token error.

  • -
  • +
  • - +
    -

    Creates an empty hash object.

    +

    Checks if hash object has a property.

    -  function hash() {
    -    return Object.create(null);
    +  function has(obj, propName) {
    +    return Object.prototype.hasOwnProperty.call(obj, propName);
       }
  • -
  • +
  • - +

    Convert existing expression atom to assignable pattern if possible.

    @@ -2898,11 +2994,11 @@ if possible.

  • -
  • +
  • - +

    Checks if node can be assignable spread argument.

    @@ -2917,11 +3013,11 @@ if possible.

  • -
  • +
  • - +

    Verify that argument names are not repeated, and it does not try to bind the words eval or arguments.

    @@ -2934,7 +3030,7 @@ try to bind the words eval or arguments.

    case "Identifier": if (isStrictReservedWord(param.name) || isStrictBadIdWord(param.name)) raise(param.start, "Defining '" + param.name + "' in strict mode"); - if (nameHash[param.name]) + if (has(nameHash, param.name)) raise(param.start, "Argument name clash in strict mode"); nameHash[param.name] = true; break; @@ -2954,11 +3050,11 @@ try to bind the words eval or arguments.

  • -
  • +
  • - +

    Check if property name clashes with already added. Object/class getters and setters are not allowed to clash — @@ -2969,20 +3065,25 @@ strict mode, init properties are also not allowed to be repeated.

       function checkPropClash(prop, propHash) {
    +    if (prop.computed) return;
         var key = prop.key, name;
         switch (key.type) {
           case "Identifier": name = key.name; break;
           case "Literal": name = String(key.value); break;
           default: return;
         }
    -    var kind = prop.kind || "init", other = propHash[name];
    -    if (other) {
    +    var kind = prop.kind || "init", other;
    +    if (has(propHash, name)) {
    +      other = propHash[name];
           var isGetSet = kind !== "init";
           if ((strict || isGetSet) && other[kind] || !(isGetSet ^ other.init))
             raise(key.start, "Redefinition of property");
         } else {
    -      other = propHash[name] = hash();
    -      other.init = other.get = other.set = false;
    +      other = propHash[name] = {
    +        init: false,
    +        get: false,
    +        set: false
    +      };
         }
         other[kind] = true;
       }
    @@ -2990,11 +3091,11 @@ strict mode, init properties are also not allowed to be repeated.

  • -
  • +
  • - +

    Verify that a node is an lval — something that can be assigned to.

    @@ -3038,11 +3139,11 @@ to.

  • -
  • +
  • - +

    Statement parsing

    @@ -3051,11 +3152,11 @@ to.

  • -
  • +
  • - +

    Parse a program. Initializes the parser, reads any number of statements, and wraps them in a Program node. Optionally takes a @@ -3088,11 +3189,11 @@ to its body instead of creating a new node.

  • -
  • +
  • - +

    Parse a single statement.

    If expecting a statement and finding a slash operator, parse a @@ -3112,11 +3213,11 @@ does not help.

  • -
  • +
  • - +

    Most types of statements are recognized by the keyword they start with. Many are trivial to parse, some require a bit of @@ -3148,11 +3249,11 @@ complexity.

  • -
  • +
  • - +

    If the statement does not start with a statement keyword or a brace, it’s an ExpressionStatement or LabeledStatement. We @@ -3183,11 +3284,11 @@ Identifier node, we switch to interpreting it as a label.

  • -
  • +
  • - +

    Verify that there is an actual destination to break or continue to.

    @@ -3225,11 +3326,11 @@ continue to.

  • -
  • +
  • - +

    Disambiguating between a for and a for/in or for/of loop is non-trivial. Basically, we have to parse the init var @@ -3286,11 +3387,11 @@ is a regular for loop.

  • -
  • +
  • - +

    In return (and break/continue), the keywords with optional arguments, we eagerly look for a semicolon or the @@ -3314,11 +3415,11 @@ possibility to insert one.

  • -
  • +
  • - +

    Statements under must be grouped (by label) in SwitchCase nodes. cur is used to keep the node that we are currently @@ -3432,11 +3533,11 @@ adding statements to.

  • -
  • +
  • - +

    Used for constructs like switch and if that insist on parentheses around their expression.

    @@ -3454,11 +3555,11 @@ parentheses around their expression.

  • -
  • +
  • - +

    Parse a semicolon-enclosed block of statements, handling "use strict" declarations when allowStrict is true (used for @@ -3487,11 +3588,11 @@ function bodies).

  • -
  • +
  • - +

    Parse a regular for loop. The disambiguation code in parseStatement will already have parsed the init statement or @@ -3515,11 +3616,11 @@ expression.

  • -
  • +
  • - +

    Parse a for/in and for/of loop, which are almost same from parser’s perspective.

    @@ -3541,11 +3642,11 @@ same from parser’s perspective.

  • -
  • +
  • - +

    Parse a list of variable declarations.

    @@ -3569,11 +3670,11 @@ same from parser’s perspective.

  • -
  • +
  • - +

    Expression parsing

    @@ -3582,11 +3683,11 @@ same from parser’s perspective.

  • -
  • +
  • - +

    These nest, from the most general expression type at the top to ‘atomic’, nondivisible expression types at the bottom. Most of @@ -3599,11 +3700,11 @@ the AST node that the inner parser gave them in another node.

  • -
  • +
  • - +

    Parse a full expression. The arguments are used to forbid comma sequences (in argument lists, array literals, or object literals) @@ -3626,11 +3727,11 @@ or the in operator (in for loops initalization expressions).

  • -
  • +
  • - +

    Parse an assignment expression. This includes applications of operators like +=.

    @@ -3655,11 +3756,11 @@ operators like +=.

  • -
  • +
  • - +

    Parse a ternary conditional (?:) operator.

    @@ -3682,11 +3783,11 @@ operators like +=.

  • -
  • +
  • - +

    Start the precedence parser.

    @@ -3700,11 +3801,11 @@ operators like +=.

  • -
  • +
  • - +

    Parse binary operators with the operator precedence parsing algorithm. left is the left-hand side of the operator. @@ -3735,11 +3836,11 @@ operator that has a lower precedence than the set it is parsing.

  • -
  • +
  • - +

    Parse unary operators, both prefix and postfix.

    @@ -3776,11 +3877,11 @@ operator that has a lower precedence than the set it is parsing.

  • -
  • +
  • - +

    Parse call, dot, and []-subscript expressions.

    @@ -3821,11 +3922,11 @@ operator that has a lower precedence than the set it is parsing.

  • -
  • +
  • - +

    Parse an atomic expression — either a single token that is an expression, an expression started by a keyword like function or @@ -3867,8 +3968,25 @@ or {}.

    return finishNode(node, "Literal"); case _parenL: - var node = startNode(), tokStartLoc1 = tokStartLoc, tokStart1 = tokStart, val, exprList; - next(); + var tokStartLoc1 = tokStartLoc, tokStart1 = tokStart, val, exprList; + next();
    + +
  • + + +
  • +
    + +
    + +
    +

    check whether this is generator comprehension or regular expression

    + +
    + +
          if (options.ecmaVersion >= 6 && tokType === _for) {
    +        val = parseComprehension(startNode(), true);
    +      } else {
           var oldParenL = ++metParenL;
           if (tokType !== _parenR) {
             val = parseExpression();
    @@ -3881,28 +3999,28 @@ or {}.

  • -
  • +
  • - +

    if ‘=>’ follows ‘(…)’, convert contents to arguments

          if (metParenL === oldParenL && eat(_arrow)) {
    -        val = parseArrowExpression(node, exprList);
    +          val = parseArrowExpression(startNode(), exprList);
           } else {
  • -
  • +
  • - +

    forbid ‘()’ before everything but ‘=>’

    @@ -3913,11 +4031,11 @@ or {}.

  • -
  • +
  • - +

    forbid ‘…’ in sequence expressions

    @@ -3929,6 +4047,7 @@ or {}.

    } } } + } val.start = tokStart1; val.end = lastEnd; if (options.locations) { @@ -3947,51 +4066,19 @@ or {}.

  • -
  • +
  • - +

    check whether this is array comprehension or regular array

          if (options.ecmaVersion >= 6 && tokType === _for) {
    -        node.blocks = [];
    -        while (tokType === _for) {
    -          var block = startNode();
    -          next();
    -          expect(_parenL);
    -          block.left = toAssignable(parseExprAtom());
    -          checkLVal(block.left, true);
    -          if (tokType !== _name || tokVal !== "of") unexpected();
    -          next();
    - -
  • - - -
  • -
    - -
    - -
    -

    of property is here for compatibility with Esprima’s AST -which also supports deprecated [for (… in …) expr]

    - -
    - -
              block.of = true;
    -          block.right = parseExpression();
    -          expect(_parenR);
    -          node.blocks.push(finishNode(block, "ComprehensionBlock"));
    +        return parseComprehension(node, false);
             }
    -        node.filter = eat(_if) ? parseParenExpression() : null;
    -        node.body = parseExpression();
    -        expect(_bracketR);
    -        return finishNode(node, "ComprehensionExpression");
    -      }
           node.elements = parseExprList(_bracketR, true, true);
           return finishNode(node, "ArrayExpression");
     
    @@ -4026,11 +4113,11 @@ which also supports deprecated [for (… in …) expr]

  • -
  • +
  • - +

    New’s precedence is slightly tricky. It must allow its argument to be a [] or dot subscript expression, but not a call — at @@ -4051,11 +4138,11 @@ least, not without wrapping it in parentheses. Thus, it uses the

  • -
  • +
  • - +

    Parse spread element ‘…expr’

    @@ -4072,11 +4159,11 @@ least, not without wrapping it in parentheses. Thus, it uses the

  • -
  • +
  • - +

    Parse template expression.

    @@ -4112,11 +4199,11 @@ least, not without wrapping it in parentheses. Thus, it uses the

  • -
  • +
  • - +

    Parse an object literal.

    @@ -4124,7 +4211,7 @@ least, not without wrapping it in parentheses. Thus, it uses the

       function parseObj() {
    -    var node = startNode(), first = true, propHash = hash();
    +    var node = startNode(), first = true, propHash = {};
         node.properties = [];
         next();
         while (!eat(_braceR)) {
    @@ -4133,7 +4220,7 @@ least, not without wrapping it in parentheses. Thus, it uses the

    if (options.allowTrailingCommas && eat(_braceR)) break; } else first = false; - var prop = startNode(), kind, isGenerator; + var prop = startNode(), isGenerator; if (options.ecmaVersion >= 6) { prop.method = false; prop.shorthand = false; @@ -4142,19 +4229,19 @@ least, not without wrapping it in parentheses. Thus, it uses the

    parsePropertyName(prop); if (eat(_colon)) { prop.value = parseExpression(true); - kind = prop.kind = "init"; + prop.kind = "init"; } else if (options.ecmaVersion >= 6 && tokType === _parenL) { - kind = prop.kind = "init"; + prop.kind = "init"; prop.method = true; prop.value = parseMethod(isGenerator); } else if (options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set")) { if (isGenerator) unexpected(); - kind = prop.kind = prop.key.name; + prop.kind = prop.key.name; parsePropertyName(prop); prop.value = parseMethod(false); } else if (options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { - kind = prop.kind = "init"; + prop.kind = "init"; prop.value = prop.key; prop.shorthand = true; } else unexpected(); @@ -4182,11 +4269,11 @@ least, not without wrapping it in parentheses. Thus, it uses the

  • -
  • +
  • - +

    Initialize empty function node.

    @@ -4206,11 +4293,11 @@ least, not without wrapping it in parentheses. Thus, it uses the

  • -
  • +
  • - +

    Parse a function declaration or literal (depending on the isStatement parameter).

    @@ -4234,11 +4321,11 @@ least, not without wrapping it in parentheses. Thus, it uses the

  • -
  • +
  • - +

    Parse object or class method.

    @@ -4263,11 +4350,11 @@ least, not without wrapping it in parentheses. Thus, it uses the

  • -
  • +
  • - +

    Parse arrow function expression with given parameters.

    @@ -4307,11 +4394,11 @@ least, not without wrapping it in parentheses. Thus, it uses the

  • -
  • +
  • - +

    Parse function parameters.

    @@ -4350,11 +4437,11 @@ least, not without wrapping it in parentheses. Thus, it uses the

  • -
  • +
  • - +

    Parse function body and check parameters.

    @@ -4372,11 +4459,11 @@ least, not without wrapping it in parentheses. Thus, it uses the

  • -
  • +
  • - +

    Start a new scope with regard to labels and the inFunction flag (restore them to their old value afterwards).

    @@ -4393,11 +4480,11 @@ flag (restore them to their old value afterwards).

  • -
  • +
  • - +

    If this is a strict mode function, verify that argument names are not repeated, and it does not try to bind the words eval @@ -4406,9 +4493,9 @@ or arguments.

        if (strict || !isExpression && node.body.body.length && isUseStrict(node.body.body[0])) {
    -      var nameHash = hash();
    +      var nameHash = {};
           if (node.id)
    -        checkFunctionParam(node.id, nameHash);
    +        checkFunctionParam(node.id, {});
           for (var i = 0; i < node.params.length; i++)
             checkFunctionParam(node.params[i], nameHash);
           if (node.rest)
    @@ -4419,11 +4506,11 @@ or arguments.

  • -
  • +
  • - +

    Parse a class declaration or literal (depending on the isStatement parameter).

    @@ -4435,28 +4522,29 @@ or arguments.

    next(); node.id = tokType === _name ? parseIdent() : isStatement ? unexpected() : null; node.superClass = eat(_extends) ? parseExpression() : null; - var classBody = startNode(), methodHash = hash(), staticMethodHash = hash(); + var classBody = startNode(), methodHash = {}, staticMethodHash = {}; classBody.body = []; expect(_braceL); while (!eat(_braceR)) { var method = startNode(); if (tokType === _name && tokVal === "static") { next(); - method.static = true; + method['static'] = true; } else { - method.static = false; + method['static'] = false; } var isGenerator = eat(_star); - method.key = parseIdent(true); - if ((method.key.name === "get" || method.key.name === "set") && tokType === _name) { + parsePropertyName(method); + if (tokType === _name && !method.computed && method.key.type === "Identifier" && + (method.key.name === "get" || method.key.name === "set")) { if (isGenerator) unexpected(); method.kind = method.key.name; - method.key = parseIdent(true); + parsePropertyName(method); } else { method.kind = ""; } method.value = parseMethod(isGenerator); - checkPropClash(method, method.static ? staticMethodHash : methodHash); + checkPropClash(method, method['static'] ? staticMethodHash : methodHash); classBody.body.push(finishNode(method, "MethodDefinition")); eat(_semi); } @@ -4467,11 +4555,11 @@ or arguments.

  • -
  • +
  • - +

    Parses a comma-separated list of expressions, and returns them as an array. close is the token type that ends the list, and @@ -4499,11 +4587,11 @@ for array literals).

  • -
  • +
  • - +

    Parse the next token as an identifier. If liberal is true (used when parsing properties), it will also convert keywords into @@ -4536,11 +4624,11 @@ identifiers.

  • -
  • +
  • - +

    Parses module export declaration.

    @@ -4553,11 +4641,11 @@ identifiers.

  • -
  • +
  • - +

    export var|const|let|function|class …;

    @@ -4565,7 +4653,7 @@ identifiers.

        if (tokType === _var || tokType === _const || tokType === _let || tokType === _function || tokType === _class) {
           node.declaration = parseStatement();
    -      node.default = false;
    +      node['default'] = false;
           node.specifiers = null;
           node.source = null;
         } else
    @@ -4573,11 +4661,11 @@ identifiers.

  • -
  • +
  • - +

    export default …;

    @@ -4585,7 +4673,7 @@ identifiers.

        if (eat(_default)) {
           node.declaration = parseExpression(true);
    -      node.default = true;
    +      node['default'] = true;
           node.specifiers = null;
           node.source = null;
           semicolon();
    @@ -4594,11 +4682,11 @@ identifiers.

  • -
  • +
  • - +

    export * from ‘…’ export { x, y as z } [from ‘…’]

    @@ -4607,7 +4695,7 @@ export { x, y as z } [from ‘…’]

          var isBatch = tokType === _star;
           node.declaration = null;
    -      node.default = false;
    +      node['default'] = false;
           node.specifiers = parseExportSpecifiers();
           if (tokType === _name && tokVal === "from") {
             next();
    @@ -4623,11 +4711,11 @@ export { x, y as z } [from ‘…’]

  • -
  • +
  • - +

    Parses a comma-separated list of module exports.

    @@ -4641,11 +4729,11 @@ export { x, y as z } [from ‘…’]

  • -
  • +
  • - +

    export * from ‘…’

    @@ -4659,11 +4747,11 @@ export { x, y as z } [from ‘…’]

  • -
  • +
  • - +

    export { x, y as z } [from ‘…’]

    @@ -4693,11 +4781,11 @@ export { x, y as z } [from ‘…’]

  • -
  • +
  • - +

    Parses import declaration.

    @@ -4710,11 +4798,11 @@ export { x, y as z } [from ‘…’]

  • -
  • +
  • - +

    import ‘…’;

    @@ -4733,18 +4821,18 @@ export { x, y as z } [from ‘…’]

  • -
  • +
  • - +

    only for backward compatibility with Esprima’s AST (it doesn’t support mixed default + named yet)

    -
          node.kind = node.specifiers[0].default ? "default" : "named";
    +            
          node.kind = node.specifiers[0]['default'] ? "default" : "named";
         }
         return finishNode(node, "ImportDeclaration");
       }
    @@ -4752,11 +4840,11 @@ export { x, y as z } [from ‘…’]

  • -
  • +
  • - +

    Parses a comma-separated list of module imports.

    @@ -4780,11 +4868,11 @@ export { x, y as z } [from ‘…’]

  • -
  • +
  • - +

    import defaultObj, { x, y as z } from ‘…’

    @@ -4794,7 +4882,7 @@ export { x, y as z } [from ‘…’]

    node.id = parseIdent(); checkLVal(node.id, true); node.name = null; - node.default = true; + node['default'] = true; nodes.push(finishNode(node, "ImportSpecifier")); if (!eat(_comma)) return nodes; } @@ -4814,7 +4902,7 @@ export { x, y as z } [from ‘…’]

    node.name = null; } checkLVal(node.name || node.id, true); - node.default = false; + node['default'] = false; nodes.push(finishNode(node, "ImportSpecifier")); } return nodes; @@ -4823,11 +4911,11 @@ export { x, y as z } [from ‘…’]

  • -
  • +
  • - +

    Parses yield expression inside generator.

    @@ -4837,19 +4925,75 @@ export { x, y as z } [from ‘…’]

    function parseYield() { var node = startNode(); next(); + if (eat(_semi) || canInsertSemicolon()) { + node.delegate = false; + node.argument = null; + } else { node.delegate = eat(_star); node.argument = parseExpression(true); + } return finishNode(node, "YieldExpression"); }
  • -
  • +
  • - + +
    +

    Parses array and generator comprehensions.

    + +
    + +
    +  function parseComprehension(node, isGenerator) {
    +    node.blocks = [];
    +    while (tokType === _for) {
    +      var block = startNode();
    +      next();
    +      expect(_parenL);
    +      block.left = toAssignable(parseExprAtom());
    +      checkLVal(block.left, true);
    +      if (tokType !== _name || tokVal !== "of") unexpected();
    +      next();
    + +
  • + + +
  • +
    + +
    + +
    +

    of property is here for compatibility with Esprima’s AST +which also supports deprecated [for (… in …) expr]

    + +
    + +
          block.of = true;
    +      block.right = parseExpression();
    +      expect(_parenR);
    +      node.blocks.push(finishNode(block, "ComprehensionBlock"));
    +    }
    +    node.filter = eat(_if) ? parseParenExpression() : null;
    +    node.body = parseExpression();
    +    expect(isGenerator ? _parenR : _bracketR);
    +    node.generator = isGenerator;
    +    return finishNode(node, "ComprehensionExpression");
    +  }
    + +
  • + + +
  • +
    + +
    +

    Transforms JSX element name to string.

    @@ -4874,11 +5018,11 @@ export { x, y as z } [from ‘…’]

  • -
  • +
  • - +

    Parse next token as JSX identifier

    @@ -4902,11 +5046,11 @@ export { x, y as z } [from ‘…’]

  • -
  • +
  • - +

    Parse namespaced identifier.

    @@ -4926,11 +5070,11 @@ export { x, y as z } [from ‘…’]

  • -
  • +
  • - +

    Parse JSX object.

    @@ -4953,11 +5097,11 @@ export { x, y as z } [from ‘…’]

  • -
  • +
  • - +

    Parses element name in any form - namespaced, object or single identifier.

    @@ -4981,11 +5125,11 @@ or single identifier.

  • -
  • +
  • - +

    Parses attribute name as optionally namespaced identifier.

    @@ -5003,11 +5147,11 @@ or single identifier.

  • -
  • +
  • - +

    Parses any type of JSX attribute value.

    @@ -5041,11 +5185,11 @@ or single identifier.

  • -
  • +
  • - +

    XJSEmptyExpression is unique type since it doesn’t actually parse anything, and so it should start at the end of last read token (left brace) and finish @@ -5075,11 +5219,11 @@ at the beginning of the next one (right brace).

  • -
  • +
  • - +

    Parses JSX expression enclosed into curly brackets.

    @@ -5104,11 +5248,11 @@ at the beginning of the next one (right brace).

  • -
  • +
  • - +

    Parses following JSX attribute name-value pair.

    @@ -5149,11 +5293,11 @@ at the beginning of the next one (right brace).

  • -
  • +
  • - +

    HTML empty attribute

    @@ -5172,11 +5316,11 @@ at the beginning of the next one (right brace).

  • -
  • +
  • - +

    Parses any type of JSX contents (expression, text or another tag).

    @@ -5199,11 +5343,11 @@ at the beginning of the next one (right brace).

  • -
  • +
  • - +

    Parses JSX open tag.

    @@ -5243,11 +5387,11 @@ at the beginning of the next one (right brace).

  • -
  • +
  • - +

    Parses JSX closing tag.

    @@ -5268,11 +5412,11 @@ at the beginning of the next one (right brace).

  • -
  • +
  • - +

    A valid token is expected after >, so parser needs to know whether to look for a standard JS token or an XJS text node

    @@ -5289,11 +5433,11 @@ whether to look for a standard JS token or an XJS text node

  • -
  • +
  • - +

    Parses entire JSX element, including it’s opening tag, attributes, contents and closing tag.

    @@ -5327,11 +5471,11 @@ attributes, contents and closing tag.

  • -
  • +
  • - +

    When (erroneously) writing two adjacent tags like

    var x = <div>one</div><div>two</div>;