From 283d47c038796f9924eeef3b30eadc10602da102 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 8 Jul 2014 17:44:55 +0300 Subject: [PATCH 001/198] Started porting JSX support from esprima-fb. Conflicts: acorn.js test/tests.js --- acorn.js | 151 +++++++++++++++++++++++++++++++++++++++++++++- test/tests-jsx.js | 53 ++++++++++++++++ test/tests.js | 1 + 3 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 test/tests-jsx.js diff --git a/acorn.js b/acorn.js index acf76f6a6c..c7c937c5e4 100644 --- a/acorn.js +++ b/acorn.js @@ -241,7 +241,7 @@ // that `break` and `continue` have somewhere to jump to, and // `strict` indicates whether strict mode is on. - var inFunction, inGenerator, labels, strict; + var inFunction, inGenerator, labels, strict, inXJSChild, inXJSTag; // This counter is used for checking that arrow expressions did // not contain nested parentheses in argument list. @@ -2015,6 +2015,11 @@ case _bquote: return parseTemplate(); + case _relational: + if (tokVal === '<') { + return parseXJSElement(); + } + default: unexpected(); } @@ -2526,4 +2531,148 @@ return finishNode(node, "ComprehensionExpression"); } + function getQualifiedXJSName(object) { + if (object.type === "XJSIdentifier") { + return object.name; + } + if (object.type === "XJSNamespacedName") { + return object.namespace.name + ':' + object.name.name; + } + if (object.type === "XJSMemberExpression") { + return ( + getQualifiedXJSName(object.object) + '.' + + getQualifiedXJSName(object.property) + ); + } + } + + function parseXJSIdentifier() { + var node = startNode(); + if (tokType === _name) { + node.name = tokVal; + } else { + unexpected(); + } + tokRegexpAllowed = false; + next(); + return finishNode(node, "XJSIdentifier"); + } + + function parseXJSElementName() { + return parseXJSIdentifier(); + } + + function parseXJSChild() { + /* + var token, marker; + if (tokVal === '{') { + token = parseXJSExpressionContainer(); + } else if (lookahead.type === Token.XJSText) { + marker = markerCreatePreserveWhitespace(); + token = markerApply(marker, delegate.createLiteral(lex())); + } else { + token = parseXJSElement(); + } + return token; + */ + return parseXJSElement(); + } + + function parseXJSClosingElement() { + var node = startNode(); + var origInXJSChild = inXJSChild; + var origInXJSTag = inXJSTag; + inXJSChild = false; + inXJSTag = true; + tokRegexpAllowed = false; + tokVal === '<' ? next() : unexpected(); + tokVal === '/' ? next() : unexpected(); + node.name = parseXJSElementName(); + // Because advance() (called by lex() called by expect()) expects there + // to be a valid token after >, it needs to know whether to look for a + // standard JS token or an XJS text node + inXJSChild = origInXJSChild; + inXJSTag = origInXJSTag; + tokVal === '>' ? next() : unexpected(); + return finishNode(node, "XJSClosingElement"); + } + + function parseXJSOpeningElement() { + var node = startNode(), attributes = node.attributes = []; + + var origInXJSChild = inXJSChild; + var origInXJSTag = inXJSTag; + inXJSChild = false; + inXJSTag = true; + + tokVal === '<' ? next() : unexpected(); + + node.name = parseXJSElementName(); + + /* + while (index < length && + lookahead.value !== '/' && + lookahead.value !== '>') { + attributes.push(parseXJSAttribute()); + } + */ + + inXJSTag = origInXJSTag; + + if (tokType === _slash) { + next(); + inXJSChild = origInXJSChild; + node.selfClosing = true; + } else { + inXJSChild = true; + node.selfClosing = false; + } + tokVal === '>' ? next() : unexpected(); + return finishNode(node, "XJSOpeningElement"); + } + + function parseXJSElement() { + var node = startNode(); + var children = []; + + var origInXJSChild = inXJSChild; + var origInXJSTag = inXJSTag; + var openingElement = parseXJSOpeningElement(); + + if (!openingElement.selfClosing) { + while (tokType !== _eof) { + inXJSChild = false; // Call lookahead2() with inXJSChild = false because one
two
; + // + // the default error message is a bit incomprehensible. Since it's + // rarely (never?) useful to write a less-than sign after an XJS + // element, we disallow it here in the parser in order to provide a + // better error message. (In the rare case that the less-than operator + // was intended, the left tag can be wrapped in parentheses.) + if (!origInXJSChild && tokVal === '<') { + raise(tokStart, "Adjacent XJS elements must be wrapped in an enclosing tag"); + } + + node.openingElement = openingElement; + node.closingElement = closingElement; + node.children = children; + return finishNode(node, "XJSElement"); + } + }); diff --git a/test/tests-jsx.js b/test/tests-jsx.js new file mode 100644 index 0000000000..77917f0eaf --- /dev/null +++ b/test/tests-jsx.js @@ -0,0 +1,53 @@ +// React JSX tests + +if (typeof exports != "undefined") { + var test = require("./driver.js").test; + var testFail = require("./driver.js").testFail; + var testAssert = require("./driver.js").testAssert; +} + +test('', { + type: 'Program', + body: [ + { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "a", + start: 1, + end: 2, + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + selfClosing: true, + attributes: [], + start: 0, + end: 5, + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + children: [], + start: 0, + end: 5, + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + start: 0, + end: 5, + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + } + ] +}, {locations: true}); \ No newline at end of file diff --git a/test/tests.js b/test/tests.js index 2259f75e59..5f058bd42e 100644 --- a/test/tests.js +++ b/test/tests.js @@ -6,6 +6,7 @@ if (typeof exports != "undefined") { var testFail = require("./driver.js").testFail; var testAssert = require("./driver.js").testAssert; var acorn = require(".."); + require("./tests-jsx.js"); } test("this\n", { From b4c5d1f2e952c2c10946cba978beb34d17be270d Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 8 Jul 2014 22:46:03 +0300 Subject: [PATCH 002/198] Added support for namespaces and member expressions in tag names. --- acorn.js | 88 ++++++++++++----- test/index.html | 1 + test/tests-jsx.js | 234 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 286 insertions(+), 37 deletions(-) diff --git a/acorn.js b/acorn.js index c7c937c5e4..1f1a3638d7 100644 --- a/acorn.js +++ b/acorn.js @@ -1248,6 +1248,20 @@ eat(type) || unexpected(); } + // 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. + + function nextChar() { + return input[tokPos]; + } + // Raise an unexpected token error. function unexpected(pos) { @@ -2547,35 +2561,67 @@ } function parseXJSIdentifier() { + var node = parseIdent(true); + node.type = "XJSIdentifier"; + return node; + } + + function parseXJSNamespacedName() { var node = startNode(); - if (tokType === _name) { - node.name = tokVal; - } else { - unexpected(); + + node.namespace = parseXJSIdentifier(); + expect(_colon); + node.name = parseXJSIdentifier(); + + return finishNode(node, "XJSNamespacedName"); + } + + function parseXJSMemberExpression() { + var node = parseXJSIdentifier(); + + while (eat(_dot)) { + var newNode = startNodeFrom(node); + newNode.object = node; + newNode.property = parseXJSIdentifier(); + node = finishNode(newNode, "XJSMemberExpression"); } - tokRegexpAllowed = false; - next(); - return finishNode(node, "XJSIdentifier"); + + return node; } function parseXJSElementName() { + switch (nextChar()) { + case ':': + return parseXJSNamespacedName(); + + case '.': + return parseXJSMemberExpression(); + + default: + return parseXJSIdentifier(); + } + } + + function parseXJSAttributeName() { + if (nextChar() === ':') { + return parseXJSNamespacedName(); + } + return parseXJSIdentifier(); } function parseXJSChild() { + var token; /* - var token, marker; if (tokVal === '{') { token = parseXJSExpressionContainer(); } else if (lookahead.type === Token.XJSText) { marker = markerCreatePreserveWhitespace(); token = markerApply(marker, delegate.createLiteral(lex())); - } else { + } else*/ { token = parseXJSElement(); } return token; - */ - return parseXJSElement(); } function parseXJSClosingElement() { @@ -2585,15 +2631,15 @@ inXJSChild = false; inXJSTag = true; tokRegexpAllowed = false; - tokVal === '<' ? next() : unexpected(); - tokVal === '/' ? next() : unexpected(); + expectChar('<'); + expectChar('/'); node.name = parseXJSElementName(); // Because advance() (called by lex() called by expect()) expects there // to be a valid token after >, it needs to know whether to look for a // standard JS token or an XJS text node inXJSChild = origInXJSChild; inXJSTag = origInXJSTag; - tokVal === '>' ? next() : unexpected(); + expectChar('>'); return finishNode(node, "XJSClosingElement"); } @@ -2605,17 +2651,13 @@ inXJSChild = false; inXJSTag = true; - tokVal === '<' ? next() : unexpected(); + expectChar('<'); node.name = parseXJSElementName(); - /* - while (index < length && - lookahead.value !== '/' && - lookahead.value !== '>') { - attributes.push(parseXJSAttribute()); + while (tokType !== _eof && tokVal !== '/' && tokVal !== '>') { + //attributes.push(parseXJSAttribute()); } - */ inXJSTag = origInXJSTag; @@ -2627,7 +2669,7 @@ inXJSChild = true; node.selfClosing = false; } - tokVal === '>' ? next() : unexpected(); + expectChar('>'); return finishNode(node, "XJSOpeningElement"); } @@ -2642,7 +2684,7 @@ if (!openingElement.selfClosing) { while (tokType !== _eof) { inXJSChild = false; // Call lookahead2() with inXJSChild = false because Acorn test suite + diff --git a/test/tests-jsx.js b/test/tests-jsx.js index 77917f0eaf..6f7eaf5eb0 100644 --- a/test/tests-jsx.js +++ b/test/tests-jsx.js @@ -6,10 +6,10 @@ if (typeof exports != "undefined") { var testAssert = require("./driver.js").testAssert; } -test('', { - type: 'Program', - body: [ - { +// Simply taken from esprima-fb/fbtest.js +var fbTestFixture = { + 'XJS': { + '': { type: "ExpressionStatement", expression: { type: "XJSElement", @@ -18,8 +18,7 @@ test('', { name: { type: "XJSIdentifier", name: "a", - start: 1, - end: 2, + range: [1, 2], loc: { start: { line: 1, column: 1 }, end: { line: 1, column: 2 } @@ -27,27 +26,234 @@ test('', { }, selfClosing: true, attributes: [], - start: 0, - end: 5, + range: [0, 5], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 5 } } }, children: [], - start: 0, - end: 5, + range: [0, 5], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 5 } } }, - start: 0, - end: 5, + range: [0, 5], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 5 } } + }, + '': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "a", + range: [ + 1, + 2 + ], + loc: { + start: { + line: 1, + column: 1 + }, + end: { + line: 1, + column: 2 + } + } + }, + selfClosing: true, + attributes: [], + range: [ + 0, + 5 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 2, + column: 2 + } + } + }, + children: [], + range: [ + 0, + 5 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 2, + column: 2 + } + } + }, + range: [ + 0, + 5 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 2, + column: 2 + } + } + }, + '<日本語>': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "日本語", + range: [ + 1, + 4 + ], + loc: { + start: { + line: 1, + column: 1 + }, + end: { + line: 1, + column: 4 + } + } + }, + selfClosing: false, + attributes: [], + range: [ + 0, + 5 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 5 + } + } + }, + closingElement: { + type: "XJSClosingElement", + name: { + type: "XJSIdentifier", + name: "日本語", + range: [ + 7, + 10 + ], + loc: { + start: { + line: 1, + column: 7 + }, + end: { + line: 1, + column: 10 + } + } + }, + range: [ + 5, + 11 + ], + loc: { + start: { + line: 1, + column: 5 + }, + end: { + line: 1, + column: 11 + } + } + }, + children: [], + range: [ + 0, + 11 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 11 + } + } + }, + range: [ + 0, + 11 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 11 + } + } } - ] -}, {locations: true}); \ No newline at end of file + } +}; + +// patching test data to match acorn-specific format instead of esprima-specific one +function esprima2acorn(ast, isTopLevel) { + if ('range' in ast) { + ast.start = ast.range[0]; + ast.end = ast.range[1]; + delete ast.range; + } + + for (var subPropName in ast) { + var subProp = ast[subPropName]; + if (typeof subProp === 'object' && subProp !== null) { + ast[subPropName] = esprima2acorn(subProp); + } + } + + if (isTopLevel) { + ast = { + type: 'Program', + body: [ast], + start: ast.start, + end: ast.end + }; + } + + return ast; +} + +for (var code in fbTestFixture.XJS) { + test(code, esprima2acorn(fbTestFixture.XJS[code], true), {locations: true}); +} \ No newline at end of file From 6091a0cf55ea19ed78c17b9cee9d21716943082a Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 9 Jul 2014 00:05:20 +0300 Subject: [PATCH 003/198] Added JSX-specific identifier parsing. Conflicts: acorn.js --- acorn.js | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/acorn.js b/acorn.js index 1f1a3638d7..130e6951df 100644 --- a/acorn.js +++ b/acorn.js @@ -287,6 +287,10 @@ var _num = {type: "num"}, _regexp = {type: "regexp"}, _string = {type: "string"}; var _name = {type: "name"}, _eof = {type: "eof"}; + // These are JSX-specific token types + + var _xjsName = {type: "xjsName"}, _xjsText = {type: "xjsText"}; + // Keyword tokens. The `keyword` property (also used in keyword-like // operators) indicates that the token originated from an // identifier-like word, which is used when parsing property names. @@ -388,7 +392,8 @@ parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon, dot: _dot, ellipsis: _ellipsis, question: _question, slash: _slash, eq: _eq, name: _name, eof: _eof, num: _num, regexp: _regexp, string: _string, - arrow: _arrow, bquote: _bquote, dollarBraceL: _dollarBraceL}; + arrow: _arrow, bquote: _bquote, dollarBraceL: _dollarBraceL, + xjsName: _xjsName, xjsText: _xjsText}; for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw]; // This is a trick taken from Esprima. It turns out that, on @@ -527,7 +532,7 @@ tokPos = tokLineStart = 0; tokRegexpAllowed = true; metParenL = 0; - inTemplate = false; + inTemplate = inXJSChild = inXJSTag = false; skipSpace(); } @@ -1071,10 +1076,10 @@ var word, first = true, start = tokPos; for (;;) { var ch = input.charCodeAt(tokPos); - if (isIdentifierChar(ch)) { + if (isIdentifierChar(ch) || (inXJSTag && ch === 45)) { if (containsEsc) word += input.charAt(tokPos); ++tokPos; - } else if (ch === 92) { // "\" + } else if (ch === 92 && !inXJSTag) { // "\" if (!containsEsc) word = input.slice(start, tokPos); containsEsc = true; if (input.charCodeAt(++tokPos) != 117) // "u" @@ -1099,7 +1104,7 @@ function readWord() { var word = readWord1(); - var type = _name; + var type = inXJSTag ? _xjsName : _name; if (!containsEsc && isKeyword(word)) type = keywordTypes[word]; return finishToken(type, word); @@ -2561,9 +2566,17 @@ } function parseXJSIdentifier() { - var node = parseIdent(true); - node.type = "XJSIdentifier"; - return node; + var node = startNode(); + if (tokType === _xjsName) { + node.name = tokVal; + } else if (tokType.keyword) { + node.name = tokType.keyword; + } else { + unexpected(); + } + tokRegexpAllowed = false; + next(); + return finishNode(node, "XJSIdentifier"); } function parseXJSNamespacedName() { From 22e8f7b90e10faa2201d5035cebfdaba9325ac6e Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 9 Jul 2014 14:58:15 +0300 Subject: [PATCH 004/198] Added basic attribute and element nesting support. --- acorn.js | 97 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 15 deletions(-) diff --git a/acorn.js b/acorn.js index 130e6951df..3169bb3884 100644 --- a/acorn.js +++ b/acorn.js @@ -2623,18 +2623,82 @@ return parseXJSIdentifier(); } - function parseXJSChild() { - var token; - /* - if (tokVal === '{') { - token = parseXJSExpressionContainer(); - } else if (lookahead.type === Token.XJSText) { - marker = markerCreatePreserveWhitespace(); - token = markerApply(marker, delegate.createLiteral(lex())); - } else*/ { - token = parseXJSElement(); + function parseXJSAttributeValue() { + var node; + if (tokType === _braceL) { + node = parseXJSExpressionContainer(); + if (node.expression.type === "XJSEmptyExpression") { + raise( + node.start, + 'XJS attributes must only be assigned a non-empty ' + + 'expression' + ); + } + } else if (tokVal === '<') { + node = parseXJSElement(); + } else if (tokType === _string) { + node = startNode(); + node.value = tokVal; + finishNode(node, "Literal"); + next(); + } else { + raise(tokStart, "XJS value should be either an expression or a quoted XJS text"); + } + return node; + } + + function parseXJSEmptyExpression() { + var node = startNode(); + if (tokType !== _braceR) { + unexpected(); + } + return finishNode(node, "XJSEmptyExpression"); + } + + function parseXJSExpressionContainer() { + var node = startNode(); + + var origInXJSChild = inXJSChild; + var origInXJSTag = inXJSTag; + inXJSChild = false; + inXJSTag = false; + + expect(_braceL); + + node.expression = tokType === _braceR ? parseXJSEmptyExpression() : parseExpression(); + + inXJSChild = origInXJSChild; + inXJSTag = origInXJSTag; + + expect(_braceR); + + return finishNode(node, "XJSExpressionContainer"); + } + + function parseXJSAttribute() { + var node = startNode(); + + node.name = parseXJSAttributeName(); + + // HTML empty attribute + if (tokVal === "=") { + next(); + node.value = parseXJSAttributeValue(); + } + + return finishNode(node, "XJSAttribute"); + } + + function parseXJSChild() { + if (tokVal === '{') { + return parseXJSExpressionContainer(); + } else if (tokType === _xjsText) { + var node = startNode(); + node.value = tokVal; + return finishNode(node, "Literal"); + } else { + return parseXJSElement(); } - return token; } function parseXJSClosingElement() { @@ -2645,7 +2709,7 @@ inXJSTag = true; tokRegexpAllowed = false; expectChar('<'); - expectChar('/'); + expect(_slash); node.name = parseXJSElementName(); // Because advance() (called by lex() called by expect()) expects there // to be a valid token after >, it needs to know whether to look for a @@ -2668,8 +2732,8 @@ node.name = parseXJSElementName(); - while (tokType !== _eof && tokVal !== '/' && tokVal !== '>') { - //attributes.push(parseXJSAttribute()); + while (tokType !== _eof && tokType !== _slash && tokVal !== '>') { + attributes.push(parseXJSAttribute()); } inXJSTag = origInXJSTag; @@ -2707,7 +2771,10 @@ inXJSTag = origInXJSTag; var closingElement = parseXJSClosingElement(); if (getQualifiedXJSName(closingElement.name) !== getQualifiedXJSName(openingElement.name)) { - raise(tokStart, "Expected corresponding XJS closing tag for '" + getQualifiedXJSName(openingElement.name) + "'"); + raise( + closingElement.start, + "Expected corresponding XJS closing tag for '" + getQualifiedXJSName(openingElement.name) + "'" + ); } } From 5d2ace2f58a71f93b99c94f84761c851834f559a Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 9 Jul 2014 20:06:19 +0300 Subject: [PATCH 005/198] Added JSX text and string literal parsing. --- acorn.js | 354 ++++++++- test/tests-jsx.js | 1857 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 2170 insertions(+), 41 deletions(-) diff --git a/acorn.js b/acorn.js index 3169bb3884..53798add98 100644 --- a/acorn.js +++ b/acorn.js @@ -789,7 +789,7 @@ // Quotes produce strings. case 34: case 39: // '"', "'" - return readString(code); + return inXJSTag ? readXJSStringLiteral() : readString(code); // Operators are parsed inline in tiny state machines. '=' (61) is // often referred to. `finishOp` simply skips the amount of @@ -830,6 +830,12 @@ if (options.locations) tokStartLoc = new Position; if (forceRegexp) return readRegexp(); if (tokPos >= inputLen) return finishToken(_eof); + if (inXJSChild) { + readXJSText(['<', '{']); + if (tokEnd > tokStart) { + return; + } + } var code = input.charCodeAt(tokPos); @@ -1051,6 +1057,331 @@ } } + var XHTMLEntities = { + quot: '\u0022', + amp: '&', + apos: '\u0027', + lt: '<', + gt: '>', + nbsp: '\u00A0', + iexcl: '\u00A1', + cent: '\u00A2', + pound: '\u00A3', + curren: '\u00A4', + yen: '\u00A5', + brvbar: '\u00A6', + sect: '\u00A7', + uml: '\u00A8', + copy: '\u00A9', + ordf: '\u00AA', + laquo: '\u00AB', + not: '\u00AC', + shy: '\u00AD', + reg: '\u00AE', + macr: '\u00AF', + deg: '\u00B0', + plusmn: '\u00B1', + sup2: '\u00B2', + sup3: '\u00B3', + acute: '\u00B4', + micro: '\u00B5', + para: '\u00B6', + middot: '\u00B7', + cedil: '\u00B8', + sup1: '\u00B9', + ordm: '\u00BA', + raquo: '\u00BB', + frac14: '\u00BC', + frac12: '\u00BD', + frac34: '\u00BE', + iquest: '\u00BF', + Agrave: '\u00C0', + Aacute: '\u00C1', + Acirc: '\u00C2', + Atilde: '\u00C3', + Auml: '\u00C4', + Aring: '\u00C5', + AElig: '\u00C6', + Ccedil: '\u00C7', + Egrave: '\u00C8', + Eacute: '\u00C9', + Ecirc: '\u00CA', + Euml: '\u00CB', + Igrave: '\u00CC', + Iacute: '\u00CD', + Icirc: '\u00CE', + Iuml: '\u00CF', + ETH: '\u00D0', + Ntilde: '\u00D1', + Ograve: '\u00D2', + Oacute: '\u00D3', + Ocirc: '\u00D4', + Otilde: '\u00D5', + Ouml: '\u00D6', + times: '\u00D7', + Oslash: '\u00D8', + Ugrave: '\u00D9', + Uacute: '\u00DA', + Ucirc: '\u00DB', + Uuml: '\u00DC', + Yacute: '\u00DD', + THORN: '\u00DE', + szlig: '\u00DF', + agrave: '\u00E0', + aacute: '\u00E1', + acirc: '\u00E2', + atilde: '\u00E3', + auml: '\u00E4', + aring: '\u00E5', + aelig: '\u00E6', + ccedil: '\u00E7', + egrave: '\u00E8', + eacute: '\u00E9', + ecirc: '\u00EA', + euml: '\u00EB', + igrave: '\u00EC', + iacute: '\u00ED', + icirc: '\u00EE', + iuml: '\u00EF', + eth: '\u00F0', + ntilde: '\u00F1', + ograve: '\u00F2', + oacute: '\u00F3', + ocirc: '\u00F4', + otilde: '\u00F5', + ouml: '\u00F6', + divide: '\u00F7', + oslash: '\u00F8', + ugrave: '\u00F9', + uacute: '\u00FA', + ucirc: '\u00FB', + uuml: '\u00FC', + yacute: '\u00FD', + thorn: '\u00FE', + yuml: '\u00FF', + OElig: '\u0152', + oelig: '\u0153', + Scaron: '\u0160', + scaron: '\u0161', + Yuml: '\u0178', + fnof: '\u0192', + circ: '\u02C6', + tilde: '\u02DC', + Alpha: '\u0391', + Beta: '\u0392', + Gamma: '\u0393', + Delta: '\u0394', + Epsilon: '\u0395', + Zeta: '\u0396', + Eta: '\u0397', + Theta: '\u0398', + Iota: '\u0399', + Kappa: '\u039A', + Lambda: '\u039B', + Mu: '\u039C', + Nu: '\u039D', + Xi: '\u039E', + Omicron: '\u039F', + Pi: '\u03A0', + Rho: '\u03A1', + Sigma: '\u03A3', + Tau: '\u03A4', + Upsilon: '\u03A5', + Phi: '\u03A6', + Chi: '\u03A7', + Psi: '\u03A8', + Omega: '\u03A9', + alpha: '\u03B1', + beta: '\u03B2', + gamma: '\u03B3', + delta: '\u03B4', + epsilon: '\u03B5', + zeta: '\u03B6', + eta: '\u03B7', + theta: '\u03B8', + iota: '\u03B9', + kappa: '\u03BA', + lambda: '\u03BB', + mu: '\u03BC', + nu: '\u03BD', + xi: '\u03BE', + omicron: '\u03BF', + pi: '\u03C0', + rho: '\u03C1', + sigmaf: '\u03C2', + sigma: '\u03C3', + tau: '\u03C4', + upsilon: '\u03C5', + phi: '\u03C6', + chi: '\u03C7', + psi: '\u03C8', + omega: '\u03C9', + thetasym: '\u03D1', + upsih: '\u03D2', + piv: '\u03D6', + ensp: '\u2002', + emsp: '\u2003', + thinsp: '\u2009', + zwnj: '\u200C', + zwj: '\u200D', + lrm: '\u200E', + rlm: '\u200F', + ndash: '\u2013', + mdash: '\u2014', + lsquo: '\u2018', + rsquo: '\u2019', + sbquo: '\u201A', + ldquo: '\u201C', + rdquo: '\u201D', + bdquo: '\u201E', + dagger: '\u2020', + Dagger: '\u2021', + bull: '\u2022', + hellip: '\u2026', + permil: '\u2030', + prime: '\u2032', + Prime: '\u2033', + lsaquo: '\u2039', + rsaquo: '\u203A', + oline: '\u203E', + frasl: '\u2044', + euro: '\u20AC', + image: '\u2111', + weierp: '\u2118', + real: '\u211C', + trade: '\u2122', + alefsym: '\u2135', + larr: '\u2190', + uarr: '\u2191', + rarr: '\u2192', + darr: '\u2193', + harr: '\u2194', + crarr: '\u21B5', + lArr: '\u21D0', + uArr: '\u21D1', + rArr: '\u21D2', + dArr: '\u21D3', + hArr: '\u21D4', + forall: '\u2200', + part: '\u2202', + exist: '\u2203', + empty: '\u2205', + nabla: '\u2207', + isin: '\u2208', + notin: '\u2209', + ni: '\u220B', + prod: '\u220F', + sum: '\u2211', + minus: '\u2212', + lowast: '\u2217', + radic: '\u221A', + prop: '\u221D', + infin: '\u221E', + ang: '\u2220', + and: '\u2227', + or: '\u2228', + cap: '\u2229', + cup: '\u222A', + 'int': '\u222B', + there4: '\u2234', + sim: '\u223C', + cong: '\u2245', + asymp: '\u2248', + ne: '\u2260', + equiv: '\u2261', + le: '\u2264', + ge: '\u2265', + sub: '\u2282', + sup: '\u2283', + nsub: '\u2284', + sube: '\u2286', + supe: '\u2287', + oplus: '\u2295', + otimes: '\u2297', + perp: '\u22A5', + sdot: '\u22C5', + lceil: '\u2308', + rceil: '\u2309', + lfloor: '\u230A', + rfloor: '\u230B', + lang: '\u2329', + rang: '\u232A', + loz: '\u25CA', + spades: '\u2660', + clubs: '\u2663', + hearts: '\u2665', + diams: '\u2666' + }; + + function readXJSEntity() { + var str = '', count = 0, entity; + var ch = nextChar(); + if (ch !== '&') raise(tokPos, "Entity must start with an ampersand"); + tokPos++; + while (tokPos < inputLen && count++ < 10) { + ch = input.charAt(tokPos++); + if (ch === ';') { + break; + } + str += ch; + } + + if (str[0] === '#' && str[1] === 'x') { + entity = String.fromCharCode(parseInt(str.substr(2), 16)); + } else if (str[0] === '#') { + entity = String.fromCharCode(parseInt(str.substr(1), 10)); + } else { + entity = XHTMLEntities[str]; + } + return entity; + } + + function readXJSText(stopChars) { + var str = ''; + while (tokPos < inputLen) { + var ch = nextChar(); + if (stopChars.indexOf(ch) !== -1) { + break; + } + if (ch === '&') { + str += readXJSEntity(); + } else { + ++tokPos; + if (ch === '\r' && nextChar() === '\n') { + str += ch; + ++tokPos; + ch = '\n'; + } + if (ch === '\n' && options.locations) { + tokLineStart = tokPos; + ++tokCurLine; + } + str += ch; + } + } + return finishToken(_xjsText, str); + } + + function readXJSStringLiteral() { + var quote = input.charCodeAt(tokPos); + + if (quote !== 34 && quote !== 39) { + raise("String literal must starts with a quote"); + } + + ++tokPos; + + readXJSText([String.fromCharCode(quote)]); + + if (quote !== input.charCodeAt(tokPos)) { + unexpected(); + } + + ++tokPos; + + return finishToken(tokType, tokVal); + } + // Used to read character escape sequences ('\x', '\u', '\U'). function readHexChar(len) { @@ -1264,7 +1595,7 @@ // Get following char. function nextChar() { - return input[tokPos]; + return input.charAt(tokPos); } // Raise an unexpected token error. @@ -2636,11 +2967,12 @@ } } else if (tokVal === '<') { node = parseXJSElement(); - } else if (tokType === _string) { + } else if (tokType === _xjsText) { node = startNode(); node.value = tokVal; - finishNode(node, "Literal"); + node.raw = input.slice(tokStart, tokEnd); next(); + finishNode(node, "Literal"); } else { raise(tokStart, "XJS value should be either an expression or a quoted XJS text"); } @@ -2690,11 +3022,13 @@ } function parseXJSChild() { - if (tokVal === '{') { + if (tokType === _braceL) { return parseXJSExpressionContainer(); } else if (tokType === _xjsText) { var node = startNode(); node.value = tokVal; + node.raw = input.slice(tokStart, tokEnd); + next(); return finishNode(node, "Literal"); } else { return parseXJSElement(); @@ -2755,20 +3089,14 @@ var children = []; var origInXJSChild = inXJSChild; - var origInXJSTag = inXJSTag; var openingElement = parseXJSOpeningElement(); if (!openingElement.selfClosing) { - while (tokType !== _eof) { - inXJSChild = false; // Call lookahead2() with inXJSChild = false because ': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSNamespacedName', + namespace: { + type: 'XJSIdentifier', + name: 'n', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + name: { + type: 'XJSIdentifier', + name: 'a', + range: [3, 4], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + range: [1, 4], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 4 } + } + }, + selfClosing: true, + attributes: [{ + type: 'XJSAttribute', + name: { + type: 'XJSNamespacedName', + namespace: { + type: 'XJSIdentifier', + name: 'n', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + name: { + type: 'XJSIdentifier', + name: 'v', + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + range: [5, 8], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 8 } + } + }, + range: [5, 8], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 8 } + } + }], + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + children: [], + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + ' {value} ': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + selfClosing: false, + attributes: [{ + type: 'XJSAttribute', + name: { + type: 'XJSNamespacedName', + namespace: { + type: 'XJSIdentifier', + name: 'n', + range: [3, 4], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + name: { + type: 'XJSIdentifier', + name: 'foo', + range: [5, 8], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 8 } + } + }, + range: [3, 8], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 8 } + } + }, + value: { + type: 'Literal', + value: 'bar', + raw: '"bar"', + range: [9, 14], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 14 } + } + }, + range: [3, 14], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 14 } + } + }], + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [38, 39], + loc: { + start: { line: 1, column: 38 }, + end: { line: 1, column: 39 } + } + }, + range: [36, 40], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 40 } + } + }, + children: [{ + type: 'Literal', + value: ' ', + raw: ' ', + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, { + type: 'XJSExpressionContainer', + expression: { + type: 'Identifier', + name: 'value', + range: [17, 22], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 22 } + } + }, + range: [16, 23], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 23 } + } + }, { + type: 'Literal', + value: ' ', + raw: ' ', + range: [23, 24], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 24 } + } + }, { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'b', + range: [25, 26], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 26 } + } + }, + selfClosing: false, + attributes: [], + range: [24, 27], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 27 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'b', + range: [34, 35], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 35 } + } + }, + range: [32, 36], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 36 } + } + }, + children: [{ + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'c', + range: [28, 29], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 29 } + } + }, + selfClosing: true, + attributes: [], + range: [27, 32], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 32 } + } + }, + children: [], + range: [27, 32], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 32 } + } + }], + range: [24, 36], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 36 } + } + }], + range: [0, 40], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 40 } + } + }, + range: [0, 40], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 40 } + } + }, + '': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "a", + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + selfClosing: true, + attributes: [ + { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "b", + range: [3, 4], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + value: { + type: "XJSExpressionContainer", + expression: { + type: "Literal", + value: " ", + raw: "\" \"", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + range: [5, 10], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 10 } + } + }, + range: [3, 10], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 10 } + } + }, + { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "c", + range: [11, 12], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + value: { + type: "Literal", + value: " ", + raw: "\" \"", + range: [13, 16], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 16 } + } + }, + range: [11, 16], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 16 } + } + }, + { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "d", + range: [17, 18], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }, + value: { + type: "Literal", + value: "&", + raw: "\"&\"", + range: [19, 26], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 26 } + } + }, + range: [17, 26], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 26 } + } + } + ], + range: [0, 29], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 29 } + } + }, + children: [], + range: [0, 29], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 29 } + } + }, + range: [0, 29], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 29 } + } + }, '': { type: "ExpressionStatement", expression: { @@ -223,37 +636,1425 @@ var fbTestFixture = { column: 11 } } + }, + + '\nbar\nbaz\r\n': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "AbC-def", + range: [ + 1, + 8 + ], + loc: { + start: { + line: 1, + column: 1 + }, + end: { + line: 1, + column: 8 + } + } + }, + selfClosing: false, + attributes: [ + { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "test", + range: [ + 11, + 15 + ], + loc: { + start: { + line: 2, + column: 2 + }, + end: { + line: 2, + column: 6 + } + } + }, + value: { + type: "Literal", + value: "&&", + raw: "\"&&\"", + range: [ + 16, + 31 + ], + loc: { + start: { + line: 2, + column: 7 + }, + end: { + line: 2, + column: 22 + } + } + }, + range: [ + 11, + 31 + ], + loc: { + start: { + line: 2, + column: 2 + }, + end: { + line: 2, + column: 22 + } + } + } + ], + range: [ + 0, + 32 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 2, + column: 23 + } + } + }, + closingElement: { + type: "XJSClosingElement", + name: { + type: "XJSIdentifier", + name: "AbC-def", + range: [ + 44, + 51 + ], + loc: { + start: { + line: 5, + column: 2 + }, + end: { + line: 5, + column: 9 + } + } + }, + range: [ + 42, + 52 + ], + loc: { + start: { + line: 5, + column: 0 + }, + end: { + line: 5, + column: 10 + } + } + }, + children: [ + { + type: "Literal", + value: "\nbar\nbaz\r\n", + raw: "\nbar\nbaz\r\n", + range: [ + 32, + 42 + ], + loc: { + start: { + line: 2, + column: 23 + }, + end: { + line: 5, + column: 0 + } + } + } + ], + range: [ + 0, + 52 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 5, + column: 10 + } + } + }, + range: [ + 0, + 52 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 5, + column: 10 + } + } + }, + + ' : } />': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "a", + range: [ + 1, + 2 + ], + loc: { + start: { + line: 1, + column: 1 + }, + end: { + line: 1, + column: 2 + } + } + }, + selfClosing: true, + attributes: [ + { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "b", + range: [ + 3, + 4 + ], + loc: { + start: { + line: 1, + column: 3 + }, + end: { + line: 1, + column: 4 + } + } + }, + value: { + type: "XJSExpressionContainer", + expression: { + type: "ConditionalExpression", + test: { + type: "Identifier", + name: "x", + range: [ + 6, + 7 + ], + loc: { + start: { + line: 1, + column: 6 + }, + end: { + line: 1, + column: 7 + } + } + }, + consequent: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "c", + range: [ + 11, + 12 + ], + loc: { + start: { + line: 1, + column: 11 + }, + end: { + line: 1, + column: 12 + } + } + }, + selfClosing: true, + attributes: [], + range: [ + 10, + 15 + ], + loc: { + start: { + line: 1, + column: 10 + }, + end: { + line: 1, + column: 15 + } + } + }, + children: [], + range: [ + 10, + 15 + ], + loc: { + start: { + line: 1, + column: 10 + }, + end: { + line: 1, + column: 15 + } + } + }, + alternate: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "d", + range: [ + 19, + 20 + ], + loc: { + start: { + line: 1, + column: 19 + }, + end: { + line: 1, + column: 20 + } + } + }, + selfClosing: true, + attributes: [], + range: [ + 18, + 23 + ], + loc: { + start: { + line: 1, + column: 18 + }, + end: { + line: 1, + column: 23 + } + } + }, + children: [], + range: [ + 18, + 23 + ], + loc: { + start: { + line: 1, + column: 18 + }, + end: { + line: 1, + column: 23 + } + } + }, + range: [ + 6, + 23 + ], + loc: { + start: { + line: 1, + column: 6 + }, + end: { + line: 1, + column: 23 + } + } + }, + range: [ + 5, + 24 + ], + loc: { + start: { + line: 1, + column: 5 + }, + end: { + line: 1, + column: 24 + } + } + }, + range: [ + 3, + 24 + ], + loc: { + start: { + line: 1, + column: 3 + }, + end: { + line: 1, + column: 24 + } + } + } + ], + range: [ + 0, + 27 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 27 + } + } + }, + children: [], + range: [ + 0, + 27 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 27 + } + } + }, + range: [ + 0, + 27 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 27 + } + } + }, + + '{}': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + selfClosing: false, + attributes: [], + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + range: [5, 9], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 9 } + } + }, + children: [{ + type: 'XJSExpressionContainer', + expression: { + type: 'XJSEmptyExpression', + range: [4, 4], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 4 } + } + }, + range: [3, 5], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 5 } + } + }], + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + '{/* this is a comment */}': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + selfClosing: false, + attributes: [], + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [30, 31], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 31 } + } + }, + range: [28, 32], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 32 } + } + }, + children: [{ + type: 'XJSExpressionContainer', + expression: { + type: 'XJSEmptyExpression', + range: [4, 27], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 27 } + } + }, + range: [3, 28], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 28 } + } + }], + range: [0, 32], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 32 } + } + }, + range: [0, 32], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 32 } + } + }, + + '
@test content
': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [1, 4], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 4 } + } + }, + selfClosing: false, + attributes: [], + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [20, 23], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 23 } + } + }, + range: [18, 24], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 24 } + } + }, + children: [{ + type: 'Literal', + value: '@test content', + raw: '@test content', + range: [5, 18], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 18 } + } + }], + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + }, + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + }, + + '

7x invalid-js-identifier
': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [ + 1, + 4 + ], + loc: { + start: { + line: 1, + column: 1 + }, + end: { + line: 1, + column: 4 + } + } + }, + selfClosing: false, + attributes: [], + range: [ + 0, + 5 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 5 + } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [ + 37, + 40 + ], + loc: { + start: { + line: 1, + column: 37 + }, + end: { + line: 1, + column: 40 + } + } + }, + range: [ + 35, + 41 + ], + loc: { + start: { + line: 1, + column: 35 + }, + end: { + line: 1, + column: 41 + } + } + }, + children: [{ + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'br', + range: [ + 6, + 8 + ], + loc: { + start: { + line: 1, + column: 6 + }, + end: { + line: 1, + column: 8 + } + } + }, + selfClosing: true, + attributes: [], + range: [ + 5, + 11 + ], + loc: { + start: { + line: 1, + column: 5 + }, + end: { + line: 1, + column: 11 + } + } + }, + children: [], + range: [ + 5, + 11 + ], + loc: { + start: { + line: 1, + column: 5 + }, + end: { + line: 1, + column: 11 + } + } + }, { + type: 'Literal', + value: '7x invalid-js-identifier', + raw: '7x invalid-js-identifier', + range: [ + 11, + 35 + ], + loc: { + start: { + line: 1, + column: 11 + }, + end: { + line: 1, + column: 35 + } + } + }], + range: [ + 0, + 41 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 41 + } + } + }, + range: [ + 0, + 41 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 41 + } + } + }, + + ' right=monkeys /> gorillas />': { + "type": "ExpressionStatement", + "expression": { + "type": "XJSElement", + "openingElement": { + "type": "XJSOpeningElement", + "name": { + "type": "XJSIdentifier", + "name": "LeftRight", + "range": [ + 1, + 10 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 10 + } + } + }, + "selfClosing": true, + "attributes": [ + { + "type": "XJSAttribute", + "name": { + "type": "XJSIdentifier", + "name": "left", + "range": [ + 11, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 15 + } + } + }, + "value": { + "type": "XJSElement", + "openingElement": { + "type": "XJSOpeningElement", + "name": { + "type": "XJSIdentifier", + "name": "a", + "range": [ + 17, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + "selfClosing": true, + "attributes": [], + "range": [ + 16, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 21 + } + } + }, + "children": [], + "range": [ + 16, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 21 + } + } + }, + "range": [ + 11, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 21 + } + } + }, + { + "type": "XJSAttribute", + "name": { + "type": "XJSIdentifier", + "name": "right", + "range": [ + 22, + 27 + ], + "loc": { + "start": { + "line": 1, + "column": 22 + }, + "end": { + "line": 1, + "column": 27 + } + } + }, + "value": { + "type": "XJSElement", + "openingElement": { + "type": "XJSOpeningElement", + "name": { + "type": "XJSIdentifier", + "name": "b", + "range": [ + 29, + 30 + ], + "loc": { + "start": { + "line": 1, + "column": 29 + }, + "end": { + "line": 1, + "column": 30 + } + } + }, + "selfClosing": false, + "attributes": [], + "range": [ + 28, + 31 + ], + "loc": { + "start": { + "line": 1, + "column": 28 + }, + "end": { + "line": 1, + "column": 31 + } + } + }, + "closingElement": { + "type": "XJSClosingElement", + "name": { + "type": "XJSIdentifier", + "name": "b", + "range": [ + 52, + 53 + ], + "loc": { + "start": { + "line": 1, + "column": 52 + }, + "end": { + "line": 1, + "column": 53 + } + } + }, + "range": [ + 50, + 54 + ], + "loc": { + "start": { + "line": 1, + "column": 50 + }, + "end": { + "line": 1, + "column": 54 + } + } + }, + "children": [ + { + "type": "Literal", + "value": "monkeys /> gorillas", + "raw": "monkeys /> gorillas", + "range": [ + 31, + 50 + ], + "loc": { + "start": { + "line": 1, + "column": 31 + }, + "end": { + "line": 1, + "column": 50 + } + } + } + ], + "range": [ + 28, + 54 + ], + "loc": { + "start": { + "line": 1, + "column": 28 + }, + "end": { + "line": 1, + "column": 54 + } + } + }, + "range": [ + 22, + 54 + ], + "loc": { + "start": { + "line": 1, + "column": 22 + }, + "end": { + "line": 1, + "column": 54 + } + } + } + ], + "range": [ + 0, + 57 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 57 + } + } + }, + "children": [], + "range": [ + 0, + 57 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 57 + } + } + }, + "range": [ + 0, + 57 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 57 + } + } + }, + + '': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSMemberExpression', + object: { + type: 'XJSIdentifier', + name: 'a', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + property: { + type: 'XJSIdentifier', + name: 'b', + range: [3, 4], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + range: [1, 4], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 4 } + } + }, + selfClosing: false, + attributes: [], + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSMemberExpression', + object: { + type: 'XJSIdentifier', + name: 'a', + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + property: { + type: 'XJSIdentifier', + name: 'b', + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + range: [7, 10], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 10 } + } + }, + range: [5, 11], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 11 } + } + }, + children: [], + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + + '': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSMemberExpression', + object: { + type: 'XJSMemberExpression', + object: { + type: 'XJSIdentifier', + name: 'a', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + property: { + type: 'XJSIdentifier', + name: 'b', + range: [3, 4], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + range: [1, 4], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 4 } + } + }, + property: { + type: 'XJSIdentifier', + name: 'c', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [1, 6], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 6 } + } + }, + selfClosing: false, + attributes: [], + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSMemberExpression', + object: { + type: 'XJSMemberExpression', + object: { + type: 'XJSIdentifier', + name: 'a', + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + property: { + type: 'XJSIdentifier', + name: 'b', + range: [11, 12], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + property: { + type: 'XJSIdentifier', + name: 'c', + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }, + range: [9, 14], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 14 } + } + }, + range: [7, 15], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 15 } + } + }, + children: [], + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + + // In order to more useful parse errors, we disallow following an + // XJSElement by a less-than symbol. In the rare case that the binary + // operator was intended, the tag can be wrapped in parentheses: + '(
) < x;': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '<', + left: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [2, 5], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 5 } + } + }, + selfClosing: true, + attributes: [], + range: [1, 8], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 8 } + } + }, + children: [], + range: [1, 8], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 8 } + } + }, + right: { + type: 'Identifier', + name: 'x', + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } } } }; -// patching test data to match acorn-specific format instead of esprima-specific one -function esprima2acorn(ast, isTopLevel) { - if ('range' in ast) { - ast.start = ast.range[0]; - ast.end = ast.range[1]; - delete ast.range; - } - - for (var subPropName in ast) { - var subProp = ast[subPropName]; - if (typeof subProp === 'object' && subProp !== null) { - ast[subPropName] = esprima2acorn(subProp); - } - } - - if (isTopLevel) { - ast = { - type: 'Program', - body: [ast], - start: ast.start, - end: ast.end - }; - } - - return ast; -} - for (var code in fbTestFixture.XJS) { - test(code, esprima2acorn(fbTestFixture.XJS[code], true), {locations: true}); + test(code, { + type: 'Program', + body: [fbTestFixture.XJS[code]] + }, {locations: true, ranges: true}); } \ No newline at end of file From 2c3740c159e21f88d81e818a755f9014c27720c8 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 9 Jul 2014 21:39:18 +0300 Subject: [PATCH 006/198] Fixed nesting elements in attributes. --- acorn.js | 1 + 1 file changed, 1 insertion(+) diff --git a/acorn.js b/acorn.js index 53798add98..87112da42d 100644 --- a/acorn.js +++ b/acorn.js @@ -3050,6 +3050,7 @@ // standard JS token or an XJS text node inXJSChild = origInXJSChild; inXJSTag = origInXJSTag; + tokRegexpAllowed = false; expectChar('>'); return finishNode(node, "XJSClosingElement"); } From 3253f5660281843ec922cb17908af31e77d0f032 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 10 Jul 2014 13:43:16 +0300 Subject: [PATCH 007/198] Fixed skipping spaces at the beginning of JSX contents. Conflicts: acorn.js --- acorn.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/acorn.js b/acorn.js index 87112da42d..7bed972444 100644 --- a/acorn.js +++ b/acorn.js @@ -544,7 +544,9 @@ tokEnd = tokPos; if (options.locations) tokEndLoc = new Position; tokType = type; - if (shouldSkipSpace !== false) skipSpace(); + if (shouldSkipSpace !== false && !(inXJSTag && val === '>')) { + skipSpace(); + } tokVal = val; tokRegexpAllowed = type.beforeExpr; if (options.onToken) { @@ -830,15 +832,15 @@ if (options.locations) tokStartLoc = new Position; if (forceRegexp) return readRegexp(); if (tokPos >= inputLen) return finishToken(_eof); - if (inXJSChild) { - readXJSText(['<', '{']); - if (tokEnd > tokStart) { - return; - } - } var code = input.charCodeAt(tokPos); + // JSX content - either simple text, start of or {expression} + if (inXJSChild && code !== 60 && code !== 123) { + return readXJSText(['<', '{']); + } + + if (inTemplate) return getTemplateToken(code); // Identifier or keyword. '\uXXXX' sequences are allowed in From f53f89a0aed7940ab414c7ac19f695df78960112 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 10 Jul 2014 17:44:46 +0300 Subject: [PATCH 008/198] Fixed test with parenthesis. --- test/tests-jsx.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/tests-jsx.js b/test/tests-jsx.js index 8817d10b97..a65f51b2b8 100644 --- a/test/tests-jsx.js +++ b/test/tests-jsx.js @@ -2022,10 +2022,10 @@ var fbTestFixture = { } }, children: [], - range: [1, 8], + range: [0, 9], loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 8 } + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } } }, right: { From 77e05c4edc8432741aa8f9562bad76874e3e7759 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 10 Jul 2014 18:28:07 +0300 Subject: [PATCH 009/198] Fixed XJSEmptyExpression location tracking. --- acorn.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/acorn.js b/acorn.js index 7bed972444..54f2867542 100644 --- a/acorn.js +++ b/acorn.js @@ -2982,11 +2982,27 @@ } function parseXJSEmptyExpression() { - var node = startNode(); if (tokType !== _braceR) { unexpected(); } - return finishNode(node, "XJSEmptyExpression"); + + /** + * 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 + * at the beginning of the next one (right brace). + */ + + var tmp; + + tmp = tokStart; + tokStart = lastEnd; + lastEnd = tmp; + + tmp = tokStartLoc; + tokStartLoc = lastEndLoc; + lastEndLoc = tmp; + + return finishNode(startNode(), "XJSEmptyExpression"); } function parseXJSExpressionContainer() { From 4ed5087bea4da1ce90fa31aeb0fc3ef99a4d3704 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 10 Jul 2014 18:29:44 +0300 Subject: [PATCH 010/198] Revert space counting after the opening tag in favor of better fix since this one introduces extra parsing error. Conflicts: acorn.js --- acorn.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/acorn.js b/acorn.js index 54f2867542..c8c6cc95ba 100644 --- a/acorn.js +++ b/acorn.js @@ -544,9 +544,7 @@ tokEnd = tokPos; if (options.locations) tokEndLoc = new Position; tokType = type; - if (shouldSkipSpace !== false && !(inXJSTag && val === '>')) { - skipSpace(); - } + if (shouldSkipSpace !== false) skipSpace(); tokVal = val; tokRegexpAllowed = type.beforeExpr; if (options.onToken) { From 292942c1d8152f8f04a8b7ebb103f681d6c09a54 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 10 Jul 2014 19:05:07 +0300 Subject: [PATCH 011/198] Small refactoring related to handling XJSText. Conflicts: acorn.js --- acorn.js | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/acorn.js b/acorn.js index c8c6cc95ba..8d3f86f05d 100644 --- a/acorn.js +++ b/acorn.js @@ -2281,7 +2281,7 @@ } return id; - case _num: case _string: case _regexp: + case _num: case _string: case _regexp: case _xjsText: var node = startNode(); node.value = tokVal; node.raw = input.slice(tokStart, tokEnd); @@ -2968,11 +2968,7 @@ } else if (tokVal === '<') { node = parseXJSElement(); } else if (tokType === _xjsText) { - node = startNode(); - node.value = tokVal; - node.raw = input.slice(tokStart, tokEnd); - next(); - finishNode(node, "Literal"); + node = parseExprAtom(); } else { raise(tokStart, "XJS value should be either an expression or a quoted XJS text"); } @@ -3038,16 +3034,15 @@ } function parseXJSChild() { - if (tokType === _braceL) { - return parseXJSExpressionContainer(); - } else if (tokType === _xjsText) { - var node = startNode(); - node.value = tokVal; - node.raw = input.slice(tokStart, tokEnd); - next(); - return finishNode(node, "Literal"); - } else { - return parseXJSElement(); + switch (tokType) { + case _braceL: + return parseXJSExpressionContainer(); + + case _xjsText: + return parseExprAtom(); + + default: + return parseXJSElement(); } } @@ -3089,8 +3084,7 @@ inXJSTag = origInXJSTag; - if (tokType === _slash) { - next(); + if (eat(_slash)) { inXJSChild = origInXJSChild; node.selfClosing = true; } else { From 7560ba4c940d1b3521c86769b59bc4d4c8b37f44 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 10 Jul 2014 22:45:47 +0300 Subject: [PATCH 012/198] Fixed in-tag spaces in hacky way (to be refactored). Conflicts: acorn.js --- acorn.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/acorn.js b/acorn.js index 8d3f86f05d..365dea3ac1 100644 --- a/acorn.js +++ b/acorn.js @@ -544,7 +544,9 @@ tokEnd = tokPos; if (options.locations) tokEndLoc = new Position; tokType = type; - if (shouldSkipSpace !== false) skipSpace(); + if (shouldSkipSpace !== false && !(inXJSTag && val === '>')) { + skipSpace(); + } tokVal = val; tokRegexpAllowed = type.beforeExpr; if (options.onToken) { @@ -3056,6 +3058,7 @@ expectChar('<'); expect(_slash); node.name = parseXJSElementName(); + skipSpace(); // Because advance() (called by lex() called by expect()) expects there // to be a valid token after >, it needs to know whether to look for a // standard JS token or an XJS text node @@ -3082,16 +3085,18 @@ attributes.push(parseXJSAttribute()); } - inXJSTag = origInXJSTag; + inXJSTag = false; if (eat(_slash)) { + inXJSTag = origInXJSTag; inXJSChild = origInXJSChild; node.selfClosing = true; + expectChar('>'); } else { inXJSChild = true; node.selfClosing = false; + expectChar('>'); } - expectChar('>'); return finishNode(node, "XJSOpeningElement"); } @@ -3103,8 +3108,8 @@ var openingElement = parseXJSOpeningElement(); if (!openingElement.selfClosing) { - inXJSChild = true; while (tokType !== _eof && !(tokVal === '<' && nextChar() === '/')) { + inXJSChild = true; children.push(parseXJSChild()); } inXJSChild = origInXJSChild; From daf9e82ab5113018c1f5b9512e15096387cc047c Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 11 Jul 2014 00:13:45 +0300 Subject: [PATCH 013/198] Final fixes for spaces. Conflicts: acorn.js --- acorn.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/acorn.js b/acorn.js index 365dea3ac1..2c5005fbe6 100644 --- a/acorn.js +++ b/acorn.js @@ -544,7 +544,7 @@ tokEnd = tokPos; if (options.locations) tokEndLoc = new Position; tokType = type; - if (shouldSkipSpace !== false && !(inXJSTag && val === '>')) { + if (shouldSkipSpace !== false && !(inXJSTag && val === '>') && !(inXJSChild && tokType !== _braceL)) { skipSpace(); } tokVal = val; @@ -836,7 +836,7 @@ var code = input.charCodeAt(tokPos); // JSX content - either simple text, start of or {expression} - if (inXJSChild && code !== 60 && code !== 123) { + if (inXJSChild && tokType !== _braceL && code !== 60 && code !== 123 && code !== 125) { return readXJSText(['<', '{']); } @@ -3004,16 +3004,13 @@ function parseXJSExpressionContainer() { var node = startNode(); - var origInXJSChild = inXJSChild; var origInXJSTag = inXJSTag; - inXJSChild = false; inXJSTag = false; expect(_braceL); node.expression = tokType === _braceR ? parseXJSEmptyExpression() : parseExpression(); - inXJSChild = origInXJSChild; inXJSTag = origInXJSTag; expect(_braceR); From 95a1231c6d250fb03cd5f8bbfc0bbf2a0bb74afa Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 11 Jul 2014 00:57:32 +0300 Subject: [PATCH 014/198] Metadata & docs updates. Conflicts: .gitignore README.md acorn.js index.html package.json --- .gitignore | 1 + README.md | 21 +- acorn.js | 86 +- docco.css | 192 -- docs/acorn.html | 4265 +++++++++++++++++++++++++ docs/docco.css | 506 +++ docs/public/fonts/aller-bold.eot | Bin 0 -> 29804 bytes docs/public/fonts/aller-bold.ttf | Bin 0 -> 66832 bytes docs/public/fonts/aller-bold.woff | Bin 0 -> 33244 bytes docs/public/fonts/aller-light.eot | Bin 0 -> 29509 bytes docs/public/fonts/aller-light.ttf | Bin 0 -> 68607 bytes docs/public/fonts/aller-light.woff | Bin 0 -> 33123 bytes docs/public/fonts/novecento-bold.eot | Bin 0 -> 18190 bytes docs/public/fonts/novecento-bold.ttf | Bin 0 -> 48132 bytes docs/public/fonts/novecento-bold.woff | Bin 0 -> 20576 bytes docs/public/stylesheets/normalize.css | 375 +++ index.html | 1967 ------------ package.json | 32 +- 18 files changed, 5238 insertions(+), 2207 deletions(-) delete mode 100644 docco.css create mode 100644 docs/acorn.html create mode 100644 docs/docco.css create mode 100644 docs/public/fonts/aller-bold.eot create mode 100644 docs/public/fonts/aller-bold.ttf create mode 100644 docs/public/fonts/aller-bold.woff create mode 100644 docs/public/fonts/aller-light.eot create mode 100644 docs/public/fonts/aller-light.ttf create mode 100644 docs/public/fonts/aller-light.woff create mode 100644 docs/public/fonts/novecento-bold.eot create mode 100644 docs/public/fonts/novecento-bold.ttf create mode 100644 docs/public/fonts/novecento-bold.woff create mode 100644 docs/public/stylesheets/normalize.css delete mode 100644 index.html diff --git a/.gitignore b/.gitignore index 7a9d2aa37c..341f1cfeda 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /node_modules +/.idea /.tern-port diff --git a/README.md b/README.md index 73750cff1d..b1d822faf0 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,19 @@ -# Acorn +# Acorn (JSX edition) -[![Build Status](https://travis-ci.org/marijnh/acorn.svg?branch=master)](https://travis-ci.org/marijnh/acorn) +This is modification of [Acorn][acorn] - a tiny, fast JavaScript parser, written completely in JavaScript. -A tiny, fast JavaScript parser, written completely in JavaScript. +It was forked to create experimental, alternative, faster [React.js JSX][jsx] parser since, according to +[benchmarks](http://marijnhaverbeke.nl/acorn/test/bench.html), Acorn is 5x faster than Esprima when parsing code +with location tracking (call it "source maps enabled mode"), and JSX extensions almost don't affect those numbers. + +This parser was created by integrating pieces of code from official parser, modified to match Acorn's parsing logic. + +Currently, it consumes all the ES5+JSX syntax that can be consumed by official [Esprima-based parser][esprima-fb]. +However, official parser can consume ES6 syntax as well, and is maintained by authors of React.js itself, so it's preferred to be used in real projects. + +[acorn]: http://marijnhaverbeke.nl/acorn/ +[esprima-fb]: https://github.com/facebook/esprima +[jsx]: http://facebook.github.io/react/docs/jsx-in-depth.html ## Installation @@ -11,13 +22,13 @@ The easiest way to install acorn is with [`npm`][npm]. [npm]: http://npmjs.org ```sh -npm install acorn +npm install acorn-jsx ``` Alternately, download the source. ```sh -git clone https://github.com/marijnh/acorn.git +git clone https://github.com/RReverser/acorn-jsx.git ``` ## Components diff --git a/acorn.js b/acorn.js index 2c5005fbe6..be448ca306 100644 --- a/acorn.js +++ b/acorn.js @@ -2883,6 +2883,8 @@ return finishNode(node, "ComprehensionExpression"); } + // Transforms JSX element name to string. + function getQualifiedXJSName(object) { if (object.type === "XJSIdentifier") { return object.name; @@ -2898,6 +2900,8 @@ } } + // Parse next token as JSX identifier + function parseXJSIdentifier() { var node = startNode(); if (tokType === _xjsName) { @@ -2912,6 +2916,8 @@ return finishNode(node, "XJSIdentifier"); } + // Parse namespaced identifier. + function parseXJSNamespacedName() { var node = startNode(); @@ -2922,6 +2928,8 @@ return finishNode(node, "XJSNamespacedName"); } + // Parse JSX object. + function parseXJSMemberExpression() { var node = parseXJSIdentifier(); @@ -2935,6 +2943,9 @@ return node; } + // Parses element name in any form - namespaced, object + // or single identifier. + function parseXJSElementName() { switch (nextChar()) { case ':': @@ -2948,6 +2959,8 @@ } } + // Parses attribute name as optionally namespaced identifier. + function parseXJSAttributeName() { if (nextChar() === ':') { return parseXJSNamespacedName(); @@ -2956,6 +2969,8 @@ return parseXJSIdentifier(); } + // Parses any type of JSX attribute value. + function parseXJSAttributeValue() { var node; if (tokType === _braceL) { @@ -2977,17 +2992,15 @@ return node; } + // 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 + // at the beginning of the next one (right brace). + function parseXJSEmptyExpression() { if (tokType !== _braceR) { unexpected(); } - /** - * 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 - * at the beginning of the next one (right brace). - */ - var tmp; tmp = tokStart; @@ -3001,6 +3014,8 @@ return finishNode(startNode(), "XJSEmptyExpression"); } + // Parses JSX expression enclosed into curly brackets. + function parseXJSExpressionContainer() { var node = startNode(); @@ -3018,6 +3033,8 @@ return finishNode(node, "XJSExpressionContainer"); } + // Parses following JSX attribute name-value pair. + function parseXJSAttribute() { var node = startNode(); @@ -3032,6 +3049,8 @@ return finishNode(node, "XJSAttribute"); } + // Parses any type of JSX contents (expression, text or another tag). + function parseXJSChild() { switch (tokType) { case _braceL: @@ -3045,26 +3064,7 @@ } } - function parseXJSClosingElement() { - var node = startNode(); - var origInXJSChild = inXJSChild; - var origInXJSTag = inXJSTag; - inXJSChild = false; - inXJSTag = true; - tokRegexpAllowed = false; - expectChar('<'); - expect(_slash); - node.name = parseXJSElementName(); - skipSpace(); - // Because advance() (called by lex() called by expect()) expects there - // to be a valid token after >, it needs to know whether to look for a - // standard JS token or an XJS text node - inXJSChild = origInXJSChild; - inXJSTag = origInXJSTag; - tokRegexpAllowed = false; - expectChar('>'); - return finishNode(node, "XJSClosingElement"); - } + // Parses JSX open tag. function parseXJSOpeningElement() { var node = startNode(), attributes = node.attributes = []; @@ -3084,19 +3084,43 @@ inXJSTag = false; - if (eat(_slash)) { + if (node.selfClosing = !!eat(_slash)) { inXJSTag = origInXJSTag; inXJSChild = origInXJSChild; - node.selfClosing = true; - expectChar('>'); } else { inXJSChild = true; - node.selfClosing = false; - expectChar('>'); } + + expectChar('>'); + return finishNode(node, "XJSOpeningElement"); } + // Parses JSX closing tag. + + function parseXJSClosingElement() { + var node = startNode(); + var origInXJSChild = inXJSChild; + var origInXJSTag = inXJSTag; + inXJSChild = false; + inXJSTag = true; + tokRegexpAllowed = false; + expectChar('<'); + expect(_slash); + node.name = parseXJSElementName(); + skipSpace(); + // A valid token is expected after >, so parser needs to know + // whether to look for a standard JS token or an XJS text node + inXJSChild = origInXJSChild; + inXJSTag = origInXJSTag; + tokRegexpAllowed = false; + expectChar('>'); + return finishNode(node, "XJSClosingElement"); + } + + // Parses entire JSX element, including it's opening tag, + // attributes, contents and closing tag. + function parseXJSElement() { var node = startNode(); var children = []; diff --git a/docco.css b/docco.css deleted file mode 100644 index 04cc7ecb8a..0000000000 --- a/docco.css +++ /dev/null @@ -1,192 +0,0 @@ -/*--------------------- Layout and Typography ----------------------------*/ -body { - font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; - font-size: 15px; - line-height: 22px; - color: #252519; - margin: 0; padding: 0; -} -a { - color: #261a3b; -} - a:visited { - color: #261a3b; - } -p { - margin: 0 0 15px 0; -} -h1, h2, h3, h4, h5, h6 { - margin: 0px 0 15px 0; -} - h1 { - margin-top: 40px; - } -hr { - border: 0 none; - border-top: 1px solid #e5e5ee; - height: 1px; - margin: 20px 0; -} -#container { - position: relative; -} -#background { - position: fixed; - top: 0; left: 525px; right: 0; bottom: 0; - background: #f5f5ff; - border-left: 1px solid #e5e5ee; - z-index: -1; -} -#jump_to, #jump_page { - background: white; - -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; - -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; - font: 10px Arial; - text-transform: uppercase; - cursor: pointer; - text-align: right; -} -#jump_to, #jump_wrapper { - position: fixed; - right: 0; top: 0; - padding: 5px 10px; -} - #jump_wrapper { - padding: 0; - display: none; - } - #jump_to:hover #jump_wrapper { - display: block; - } - #jump_page { - padding: 5px 0 3px; - margin: 0 0 25px 25px; - } - #jump_page .source { - display: block; - padding: 5px 10px; - text-decoration: none; - border-top: 1px solid #eee; - } - #jump_page .source:hover { - background: #f5f5ff; - } - #jump_page .source:first-child { - } -table td { - border: 0; - outline: 0; -} - td.docs, th.docs { - max-width: 450px; - min-width: 450px; - min-height: 5px; - padding: 10px 25px 1px 50px; - overflow-x: hidden; - vertical-align: top; - text-align: left; - } - .docs pre { - margin: 15px 0 15px; - padding-left: 15px; - } - .docs p tt, .docs p code { - background: #f8f8ff; - border: 1px solid #dedede; - font-size: 12px; - padding: 0 0.2em; - } - .pilwrap { - position: relative; - } - .pilcrow { - font: 12px Arial; - text-decoration: none; - color: #454545; - position: absolute; - top: 3px; left: -20px; - padding: 1px 2px; - opacity: 0; - -webkit-transition: opacity 0.2s linear; - } - td.docs:hover .pilcrow { - opacity: 1; - } - td.code, th.code { - padding: 14px 15px 16px 25px; - width: 100%; - vertical-align: top; - background: #f5f5ff; - border-left: 1px solid #e5e5ee; - } - pre, tt, code { - font-size: 12px; line-height: 18px; - font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; - margin: 0; padding: 0; - } - - -/*---------------------- Syntax Highlighting -----------------------------*/ -td.linenos { background-color: #f0f0f0; padding-right: 10px; } -span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } -body .hll { background-color: #ffffcc } -body .c { color: #408080; font-style: italic } /* Comment */ -body .err { border: 1px solid #FF0000 } /* Error */ -body .k { color: #954121 } /* Keyword */ -body .o { color: #666666 } /* Operator */ -body .cm { color: #408080; font-style: italic } /* Comment.Multiline */ -body .cp { color: #BC7A00 } /* Comment.Preproc */ -body .c1 { color: #408080; font-style: italic } /* Comment.Single */ -body .cs { color: #408080; font-style: italic } /* Comment.Special */ -body .gd { color: #A00000 } /* Generic.Deleted */ -body .ge { font-style: italic } /* Generic.Emph */ -body .gr { color: #FF0000 } /* Generic.Error */ -body .gh { color: #000080; font-weight: bold } /* Generic.Heading */ -body .gi { color: #00A000 } /* Generic.Inserted */ -body .go { color: #808080 } /* Generic.Output */ -body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ -body .gs { font-weight: bold } /* Generic.Strong */ -body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ -body .gt { color: #0040D0 } /* Generic.Traceback */ -body .kc { color: #954121 } /* Keyword.Constant */ -body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */ -body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */ -body .kp { color: #954121 } /* Keyword.Pseudo */ -body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */ -body .kt { color: #B00040 } /* Keyword.Type */ -body .m { color: #666666 } /* Literal.Number */ -body .s { color: #219161 } /* Literal.String */ -body .na { color: #7D9029 } /* Name.Attribute */ -body .nb { color: #954121 } /* Name.Builtin */ -body .nc { color: #0000FF; font-weight: bold } /* Name.Class */ -body .no { color: #880000 } /* Name.Constant */ -body .nd { color: #AA22FF } /* Name.Decorator */ -body .ni { color: #999999; font-weight: bold } /* Name.Entity */ -body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ -body .nf { color: #0000FF } /* Name.Function */ -body .nl { color: #A0A000 } /* Name.Label */ -body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ -body .nt { color: #954121; font-weight: bold } /* Name.Tag */ -body .nv { color: #19469D } /* Name.Variable */ -body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ -body .w { color: #bbbbbb } /* Text.Whitespace */ -body .mf { color: #666666 } /* Literal.Number.Float */ -body .mh { color: #666666 } /* Literal.Number.Hex */ -body .mi { color: #666666 } /* Literal.Number.Integer */ -body .mo { color: #666666 } /* Literal.Number.Oct */ -body .sb { color: #219161 } /* Literal.String.Backtick */ -body .sc { color: #219161 } /* Literal.String.Char */ -body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */ -body .s2 { color: #219161 } /* Literal.String.Double */ -body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ -body .sh { color: #219161 } /* Literal.String.Heredoc */ -body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ -body .sx { color: #954121 } /* Literal.String.Other */ -body .sr { color: #BB6688 } /* Literal.String.Regex */ -body .s1 { color: #219161 } /* Literal.String.Single */ -body .ss { color: #19469D } /* Literal.String.Symbol */ -body .bp { color: #954121 } /* Name.Builtin.Pseudo */ -body .vc { color: #19469D } /* Name.Variable.Class */ -body .vg { color: #19469D } /* Name.Variable.Global */ -body .vi { color: #19469D } /* Name.Variable.Instance */ -body .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/docs/acorn.html b/docs/acorn.html new file mode 100644 index 0000000000..9bfaf46a83 --- /dev/null +++ b/docs/acorn.html @@ -0,0 +1,4265 @@ + + + + + acorn.js + + + + + +
+
+ +
    + +
  • +
    +

    acorn.js

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

    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.

    +

    Git repositories for Acorn are available at

    +
    http://marijnhaverbeke.nl/git/acorn
    +https://github.com/marijnh/acorn.git
    +

    Please use the github bug tracker to report issues.

    +

    This file defines the main parser interface. The library also comes +with a error-tolerant parser and an +abstract syntax tree walker, defined in other files.

    + +
    + +
    +(function(root, mod) {
    +  if (typeof exports == "object" && typeof module == "object") return mod(exports); // CommonJS
    +  if (typeof define == "function" && define.amd) return define(["exports"], mod); // AMD
    +  mod(root.acorn || (root.acorn = {})); // Plain browser env
    +})(this, function(exports) {
    
    +  "use strict";
    +
    +  exports.version = "0.6.1";
    + +
  • + + +
  • +
    + +
    + +
    +

    The main exported interface (under self.acorn when in the +browser) is a parse function that takes a code string and +returns an abstract syntax tree as specified by Mozilla parser +API, with the caveat that the SpiderMonkey-specific syntax +(let, yield, inline XML, etc) is not recognized.

    + +
    + +
    +  var options, input, inputLen, sourceFile;
    +
    +  exports.parse = function(inpt, opts) {
    +    input = String(inpt); inputLen = input.length;
    +    setOptions(opts);
    +    initTokenState();
    +    return parseTopLevel(options.program);
    +  };
    + +
  • + + +
  • +
    + +
    + +
    +

    A second optional argument can be given to further configure +the parser process. These options are recognized:

    + +
    + +
    +  var defaultOptions = exports.defaultOptions = {
    + +
  • + + +
  • +
    + +
    + +
    +

    ecmaVersion indicates the ECMAScript version to parse. Must +be either 3, or 5, or 6. This influences support for strict +mode, the set of reserved words, support for getters and +setters and other features. ES6 support is only partial.

    + +
    + +
        ecmaVersion: 5,
    + +
  • + + +
  • +
    + +
    + +
    +

    Turn on strictSemicolons to prevent the parser from doing +automatic semicolon insertion.

    + +
    + +
        strictSemicolons: false,
    + +
  • + + +
  • +
    + +
    + +
    +

    When allowTrailingCommas is false, the parser will not allow +trailing commas in array and object literals.

    + +
    + +
        allowTrailingCommas: true,
    + +
  • + + +
  • +
    + +
    + +
    +

    By default, reserved words are not enforced. Enable +forbidReserved to enforce them. When this option has the +value “everywhere”, reserved words and keywords can also not be +used as property names.

    + +
    + +
        forbidReserved: false,
    + +
  • + + +
  • +
    + +
    + +
    +

    When enabled, a return at the top level is not considered an +error.

    + +
    + +
        allowReturnOutsideFunction: false,
    + +
  • + + +
  • +
    + +
    + +
    +

    When locations is on, loc properties holding objects with +start and end properties in {line, column} form (with +line being 1-based and column 0-based) will be attached to the +nodes.

    + +
    + +
        locations: false,
    + +
  • + + +
  • +
    + +
    + +
    +

    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 +boolean indicating whether this is a block (/* */) comment, +text is the content of the comment, and start and end are +character offsets that denote the start and end of the comment. +When the locations option is on, two more parameters are +passed, the full {line, column} locations of the start and +end of the comments. Note that you are not allowed to call the +parser from the callback—that will corrupt its internal state.

    + +
    + +
        onComment: null,
    + +
  • + + +
  • +
    + +
    + +
    +

    Nodes have their start and end characters offsets recorded in +start and end properties (directly on the node, rather than +the loc object, which holds line/column data. To also add a +semi-standardized range property holding a [start, +end] array with the same numbers, set the ranges option to +true.

    + +
    + +
        ranges: false,
    + +
  • + + +
  • +
    + +
    + +
    +

    It is possible to parse multiple files into a single AST by +passing the tree produced by parsing the first file as +program option in subsequent parses. This will add the +toplevel forms of the parsed file to the Program (top) node +of an existing parse tree.

    + +
    + +
        program: null,
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
        sourceFile: null,
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
        directSourceFile: null
    +  };
    +
    +  function setOptions(opts) {
    +    options = opts || {};
    +    for (var opt in defaultOptions) if (!Object.prototype.hasOwnProperty.call(options, opt))
    +      options[opt] = defaultOptions[opt];
    +    sourceFile = options.sourceFile || null;
    +
    +    isKeyword = options.ecmaVersion >= 6 ? isEcma6Keyword : isEcma5AndLessKeyword;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    The getLineInfo function is mostly useful when the +locations option is off (for performance reasons) and you +want to find the line/column position for a given character +offset. input should be the code string that the offset refers +into.

    + +
    + +
    +  var getLineInfo = exports.getLineInfo = function(input, offset) {
    +    for (var line = 1, cur = 0;;) {
    +      lineBreak.lastIndex = cur;
    +      var match = lineBreak.exec(input);
    +      if (match && match.index < offset) {
    +        ++line;
    +        cur = match.index + match[0].length;
    +      } else break;
    +    }
    +    return {line: line, column: offset - cur};
    +  };
    + +
  • + + +
  • +
    + +
    + +
    +

    Acorn is organized as a tokenizer and a recursive-descent parser. +The tokenize export provides an interface to the tokenizer. +Because the tokenizer is optimized for being efficiently used by +the Acorn parser itself, this interface is somewhat crude and not +very modular. Performing another parse or call to tokenize will +reset the internal state, and invalidate existing tokenizers.

    + +
    + +
    +  exports.tokenize = function(inpt, opts) {
    +    input = String(inpt); inputLen = input.length;
    +    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;
    +    }
    +    getToken.jumpTo = function(pos, reAllowed) {
    +      tokPos = pos;
    +      if (options.locations) {
    +        tokCurLine = 1;
    +        tokLineStart = lineBreak.lastIndex = 0;
    +        var match;
    +        while ((match = lineBreak.exec(input)) && match.index < pos) {
    +          ++tokCurLine;
    +          tokLineStart = match.index + match[0].length;
    +        }
    +      }
    +      tokRegexpAllowed = reAllowed;
    +      skipSpace();
    +    };
    +    return getToken;
    +  };
    + +
  • + + +
  • +
    + +
    + +
    +

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

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

    The current position of the tokenizer in the input.

    + +
    + +
    +  var tokPos;
    + +
  • + + +
  • +
    + +
    + +
    +

    The start and end offsets of the current token.

    + +
    + +
    +  var tokStart, tokEnd;
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  var tokStartLoc, tokEndLoc;
    + +
  • + + +
  • +
    + +
    + +
    +

    The type and value of the current token. Token types are objects, +named by variables against which they can be compared, and +holding properties that describe them (indicating, for example, +the precedence of an infix operator, and the original name of a +keyword token). The kind of value that’s held in tokVal depends +on the type of the token. For literals, it is the literal value, +for operators, the operator name, and so on.

    + +
    + +
    +  var tokType, tokVal;
    + +
  • + + +
  • +
    + +
    + +
    +

    Interal state for the tokenizer. To distinguish between division +operators and regular expressions, it remembers whether the last +token was one that is allowed to be followed by an expression. +(If it is, a slash is probably a regexp, if it isn’t it’s a +division operator. See the parseStatement function for a +caveat.)

    + +
    + +
    +  var tokRegexpAllowed;
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  var tokCurLine, tokLineStart;
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  var lastStart, lastEnd, lastEndLoc;
    + +
  • + + +
  • +
    + +
    + +
    +

    This is the parser’s state. inFunction is used to reject +return statements outside of functions, labels to verify that +break and continue have somewhere to jump to, and strict +indicates whether strict mode is on.

    + +
    + +
    +  var inFunction, labels, strict, inXJSChild, inXJSTag;
    + +
  • + + +
  • +
    + +
    + +
    +

    This function is used to raise exceptions on parse errors. It +takes an offset integer (into the current input) to indicate +the location of the error, attaches the position to the end +of the error message, and then raises a SyntaxError with that +message.

    + +
    + +
    +  function raise(pos, message) {
    +    var loc = getLineInfo(input, pos);
    +    message += " (" + loc.line + ":" + loc.column + ")";
    +    var err = new SyntaxError(message);
    +    err.pos = pos; err.loc = loc; err.raisedAt = tokPos;
    +    throw err;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  var empty = [];
    + +
  • + + +
  • +
    + +
    + +
    +

    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.

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

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

    + +
    + +
    +  var _num = {type: "num"}, _regexp = {type: "regexp"}, _string = {type: "string"};
    +  var _name = {type: "name"}, _eof = {type: "eof"};
    + +
  • + + +
  • +
    + +
    + +
    +

    These are JSX-specific token types

    + +
    + +
    +  var _xjsName = {type: "xjsName"}, _xjsText = {type: "xjsText"};
    + +
  • + + +
  • +
    + +
    + +
    +

    Keyword tokens. The keyword property (also used in keyword-like +operators) indicates that the token originated from an +identifier-like word, which is used when parsing property names.

    +

    The beforeExpr property is used to disambiguate between regular +expressions and divisions. It is set on all token types that can +be followed by an expression (thus, a slash after them would be a +regular expression).

    +

    isLoop marks a keyword as starting a loop, which is important +to know when parsing a label, in order to allow or disallow +continue jumps to that label.

    + +
    + +
    +  var _break = {keyword: "break"}, _case = {keyword: "case", beforeExpr: true}, _catch = {keyword: "catch"};
    +  var _continue = {keyword: "continue"}, _debugger = {keyword: "debugger"}, _default = {keyword: "default"};
    +  var _do = {keyword: "do", isLoop: true}, _else = {keyword: "else", beforeExpr: true};
    +  var _finally = {keyword: "finally"}, _for = {keyword: "for", isLoop: true}, _function = {keyword: "function"};
    +  var _if = {keyword: "if"}, _return = {keyword: "return", beforeExpr: true}, _switch = {keyword: "switch"};
    +  var _throw = {keyword: "throw", beforeExpr: true}, _try = {keyword: "try"}, _var = {keyword: "var"};
    +  var _let = {keyword: "let"}, _const = {keyword: "const"};
    +  var _while = {keyword: "while", isLoop: true}, _with = {keyword: "with"}, _new = {keyword: "new", beforeExpr: true};
    +  var _this = {keyword: "this"};
    + +
  • + + +
  • +
    + +
    + +
    +

    The keywords that denote values.

    + +
    + +
    +  var _null = {keyword: "null", atomValue: null}, _true = {keyword: "true", atomValue: true};
    +  var _false = {keyword: "false", atomValue: false};
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  var _in = {keyword: "in", binop: 7, beforeExpr: true};
    + +
  • + + +
  • +
    + +
    + +
    +

    Map keyword names to token types.

    + +
    + +
    +  var keywordTypes = {"break": _break, "case": _case, "catch": _catch,
    +                      "continue": _continue, "debugger": _debugger, "default": _default,
    +                      "do": _do, "else": _else, "finally": _finally, "for": _for,
    +                      "function": _function, "if": _if, "return": _return, "switch": _switch,
    +                      "throw": _throw, "try": _try, "var": _var, "let": _let, "const": _const,
    +                      "while": _while, "with": _with,
    +                      "null": _null, "true": _true, "false": _false, "new": _new, "in": _in,
    +                      "instanceof": {keyword: "instanceof", binop: 7, beforeExpr: true}, "this": _this,
    +                      "typeof": {keyword: "typeof", prefix: true, beforeExpr: true},
    +                      "void": {keyword: "void", prefix: true, beforeExpr: true},
    +                      "delete": {keyword: "delete", prefix: true, beforeExpr: true}};
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  var _bracketL = {type: "[", beforeExpr: true}, _bracketR = {type: "]"}, _braceL = {type: "{", beforeExpr: true};
    +  var _braceR = {type: "}"}, _parenL = {type: "(", beforeExpr: true}, _parenR = {type: ")"};
    +  var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true};
    +  var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _ellipsis = {type: "..."}, _question = {type: "?", beforeExpr: true};
    + +
  • + + +
  • +
    + +
    + +
    +

    Operators. These carry several kinds of properties to help the +parser use them properly (the presence of these properties is +what categorizes them as operators).

    +

    binop, when present, specifies that this operator is a binary +operator, and will refer to its precedence.

    +

    prefix and postfix mark the operator as a prefix or postfix +unary operator. isUpdate specifies that the node produced by +the operator should be of type UpdateExpression rather than +simply UnaryExpression (++ and --).

    +

    isAssign marks all of =, +=, -= etcetera, which act as +binary operators with a very low precedence, that should result +in AssignmentExpression nodes.

    + +
    + +
    +  var _slash = {binop: 10, beforeExpr: true}, _eq = {isAssign: true, beforeExpr: true};
    +  var _assign = {isAssign: true, beforeExpr: true};
    +  var _incDec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true};
    +  var _logicalOR = {binop: 1, beforeExpr: true};
    +  var _logicalAND = {binop: 2, beforeExpr: true};
    +  var _bitwiseOR = {binop: 3, beforeExpr: true};
    +  var _bitwiseXOR = {binop: 4, beforeExpr: true};
    +  var _bitwiseAND = {binop: 5, beforeExpr: true};
    +  var _equality = {binop: 6, beforeExpr: true};
    +  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};
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  exports.tokTypes = {bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR,
    +                      parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon,
    +                      dot: _dot, ellipsis: _ellipsis, question: _question, slash: _slash, eq: _eq,
    +                      name: _name, eof: _eof, num: _num, regexp: _regexp, string: _string,
    +                      xjsName: _xjsName, xjsText: _xjsText};
    +
    +  for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw];
    + +
  • + + +
  • +
    + +
    + +
    +

    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 +predicate containing a big ugly switch statement is faster than +a regular expression, and on Chrome the two are about on par. +This function uses eval (non-lexical) to produce such a +predicate from a space-separated string of words.

    +

    It starts by sorting the words by length.

    + +
    + +
    +  function makePredicate(words) {
    +    words = words.split(" ");
    +    var f = "", cats = [];
    +    out: for (var i = 0; i < words.length; ++i) {
    +      for (var j = 0; j < cats.length; ++j)
    +        if (cats[j][0].length == words[i].length) {
    +          cats[j].push(words[i]);
    +          continue out;
    +        }
    +      cats.push([words[i]]);
    +    }
    +    function compareTo(arr) {
    +      if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";";
    +      f += "switch(str){";
    +      for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":";
    +      f += "return true}return false;";
    +    }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +    if (cats.length > 3) {
    +      cats.sort(function(a, b) {return b.length - a.length;});
    +      f += "switch(str.length){";
    +      for (var i = 0; i < cats.length; ++i) {
    +        var cat = cats[i];
    +        f += "case " + cat[0].length + ":";
    +        compareTo(cat);
    +      }
    +      f += "}";
    + +
  • + + +
  • +
    + +
    + +
    +

    Otherwise, simply generate a flat switch statement.

    + +
    + +
    +    } else {
    +      compareTo(words);
    +    }
    +    return new Function("str", f);
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    The ECMAScript 3 reserved word list.

    + +
    + +
    +  var isReservedWord3 = makePredicate("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile");
    + +
  • + + +
  • +
    + +
    + +
    +

    ECMAScript 5 reserved words.

    + +
    + +
    +  var isReservedWord5 = makePredicate("class enum extends super const export import");
    + +
  • + + +
  • +
    + +
    + +
    +

    The additional reserved words in strict mode.

    + +
    + +
    +  var isStrictReservedWord = makePredicate("implements interface let package private protected public static yield");
    + +
  • + + +
  • +
    + +
    + +
    +

    The forbidden variable names in strict mode.

    + +
    + +
    +  var isStrictBadIdWord = makePredicate("eval arguments");
    + +
  • + + +
  • +
    + +
    + +
    +

    And the keywords.

    + +
    + +
    +  var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
    +
    +  var isEcma5AndLessKeyword = makePredicate(ecma5AndLessKeywords);
    +
    +  var isEcma6Keyword = makePredicate(ecma5AndLessKeywords + " let const");
    +
    +  var isKeyword = isEcma5AndLessKeyword;
    + +
  • + + +
  • +
    + +
    + +
    +

    Character categories

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

    Big ugly regular expressions that match characters in the +whitespace, identifier, and identifier-start categories. These +are only applied when a character is found to actually have a +code point above 128.

    + +
    + +
    +  var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
    +  var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
    +  var nonASCIIidentifierChars = "\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
    +  var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
    +  var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
    + +
  • + + +
  • +
    + +
    + +
    +

    Whether a single character denotes a newline.

    + +
    + +
    +  var newline = /[\n\r\u2028\u2029]/;
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  var lineBreak = /\r\n|[\n\r\u2028\u2029]/g;
    + +
  • + + +
  • +
    + +
    + +
    +

    Test whether a given character code starts an identifier.

    + +
    + +
    +  var isIdentifierStart = exports.isIdentifierStart = function(code) {
    +    if (code < 65) return code === 36;
    +    if (code < 91) return true;
    +    if (code < 97) return code === 95;
    +    if (code < 123)return true;
    +    return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));
    +  };
    + +
  • + + +
  • +
    + +
    + +
    +

    Test whether a given character is part of an identifier.

    + +
    + +
    +  var isIdentifierChar = exports.isIdentifierChar = function(code) {
    +    if (code < 48) return code === 36;
    +    if (code < 58) return true;
    +    if (code < 65) return false;
    +    if (code < 91) return true;
    +    if (code < 97) return code === 95;
    +    if (code < 123)return true;
    +    return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));
    +  };
    + +
  • + + +
  • +
    + +
    + +
    +

    Tokenizer

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

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

    + +
    + +
    +  function Position() {
    +    this.line = tokCurLine;
    +    this.column = tokPos - tokLineStart;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function initTokenState() {
    +    tokCurLine = 1;
    +    tokPos = tokLineStart = 0;
    +    tokRegexpAllowed = true;
    +    inXJSChild = inXJSTag = false;
    +    skipSpace();
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function finishToken(type, val) {
    +    tokEnd = tokPos;
    +    if (options.locations) tokEndLoc = new Position;
    +    tokType = type;
    +    if (!(inXJSTag && val === '>') && !(inXJSChild && tokType !== _braceL)) {
    +      skipSpace();
    +    }
    +    tokVal = val;
    +    tokRegexpAllowed = type.beforeExpr;
    +  }
    +
    +  function skipBlockComment() {
    +    var startLoc = options.onComment && options.locations && new Position;
    +    var start = tokPos, end = input.indexOf("*/", tokPos += 2);
    +    if (end === -1) raise(tokPos - 2, "Unterminated comment");
    +    tokPos = end + 2;
    +    if (options.locations) {
    +      lineBreak.lastIndex = start;
    +      var match;
    +      while ((match = lineBreak.exec(input)) && match.index < tokPos) {
    +        ++tokCurLine;
    +        tokLineStart = match.index + match[0].length;
    +      }
    +    }
    +    if (options.onComment)
    +      options.onComment(true, input.slice(start + 2, end), start, tokPos,
    +                        startLoc, options.locations && new Position);
    +  }
    +
    +  function skipLineComment() {
    +    var start = tokPos;
    +    var startLoc = options.onComment && options.locations && new Position;
    +    var ch = input.charCodeAt(tokPos+=2);
    +    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,
    +                        startLoc, options.locations && new Position);
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function skipSpace() {
    +    while (tokPos < inputLen) {
    +      var ch = input.charCodeAt(tokPos);
    +      if (ch === 32) { // ' '
    +        ++tokPos;
    +      } else if (ch === 13) {
    +        ++tokPos;
    +        var next = input.charCodeAt(tokPos);
    +        if (next === 10) {
    +          ++tokPos;
    +        }
    +        if (options.locations) {
    +          ++tokCurLine;
    +          tokLineStart = tokPos;
    +        }
    +      } else if (ch === 10 || ch === 8232 || ch === 8233) {
    +        ++tokPos;
    +        if (options.locations) {
    +          ++tokCurLine;
    +          tokLineStart = tokPos;
    +        }
    +      } else if (ch > 8 && ch < 14) {
    +        ++tokPos;
    +      } else if (ch === 47) { // '/'
    +        var next = input.charCodeAt(tokPos + 1);
    +        if (next === 42) { // '*'
    +          skipBlockComment();
    +        } else if (next === 47) { // '/'
    +          skipLineComment();
    +        } else break;
    +      } else if (ch === 160) { // '\xa0'
    +        ++tokPos;
    +      } else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
    +        ++tokPos;
    +      } else {
    +        break;
    +      }
    +    }
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Token reading

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

    This is the function that is called to fetch the next token. It +is somewhat obscure, because it works in character codes rather +than characters, and because operator parsing has been inlined +into it.

    +

    All in the name of speed.

    +

    The forceRegexp parameter is used in the one case where the +tokRegexpAllowed trick does not work. See parseStatement.

    + +
    + +
    +  function readToken_dot() {
    +    var next = input.charCodeAt(tokPos + 1);
    +    if (next >= 48 && next <= 57) return readNumber(true);
    +    var next2 = input.charCodeAt(tokPos + 2);
    +    if (options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
    +      tokPos += 3;
    +      return finishToken(_ellipsis);
    +    } else {
    +      ++tokPos;
    +      return finishToken(_dot);
    +    }
    +  }
    +
    +  function readToken_slash() { // '/'
    +    var next = input.charCodeAt(tokPos + 1);
    +    if (tokRegexpAllowed) {++tokPos; return readRegexp();}
    +    if (next === 61) return finishOp(_assign, 2);
    +    return finishOp(_slash, 1);
    +  }
    +
    +  function readToken_mult_modulo() { // '%*'
    +    var next = input.charCodeAt(tokPos + 1);
    +    if (next === 61) return finishOp(_assign, 2);
    +    return finishOp(_multiplyModulo, 1);
    +  }
    +
    +  function readToken_pipe_amp(code) { // '|&'
    +    var next = input.charCodeAt(tokPos + 1);
    +    if (next === code) return finishOp(code === 124 ? _logicalOR : _logicalAND, 2);
    +    if (next === 61) return finishOp(_assign, 2);
    +    return finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1);
    +  }
    +
    +  function readToken_caret() { // '^'
    +    var next = input.charCodeAt(tokPos + 1);
    +    if (next === 61) return finishOp(_assign, 2);
    +    return finishOp(_bitwiseXOR, 1);
    +  }
    +
    +  function readToken_plus_min(code) { // '+-'
    +    var next = input.charCodeAt(tokPos + 1);
    +    if (next === code) {
    +      if (next == 45 && input.charCodeAt(tokPos + 2) == 62 &&
    +          newline.test(input.slice(lastEnd, tokPos))) {
    + +
  • + + +
  • +
    + +
    + +
    +

    A --> line comment

    + +
    + +
            tokPos += 3;
    +        skipLineComment();
    +        skipSpace();
    +        return readToken();
    +      }
    +      return finishOp(_incDec, 2);
    +    }
    +    if (next === 61) return finishOp(_assign, 2);
    +    return finishOp(_plusMin, 1);
    +  }
    +
    +  function readToken_lt_gt(code) { // '<>'
    +    var next = input.charCodeAt(tokPos + 1);
    +    var size = 1;
    +    if (next === code) {
    +      size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2;
    +      if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1);
    +      return finishOp(_bitShift, size);
    +    }
    +    if (next == 33 && code == 60 && input.charCodeAt(tokPos + 2) == 45 &&
    +        input.charCodeAt(tokPos + 3) == 45) {
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
          tokPos += 4;
    +      skipLineComment();
    +      skipSpace();
    +      return readToken();
    +    }
    +    if (next === 61)
    +      size = input.charCodeAt(tokPos + 2) === 61 ? 3 : 2;
    +    return finishOp(_relational, size);
    +  }
    +
    +  function readToken_eq_excl(code) { // '=!'
    +    var next = input.charCodeAt(tokPos + 1);
    +    if (next === 61) return finishOp(_equality, input.charCodeAt(tokPos + 2) === 61 ? 3 : 2);
    +    return finishOp(code === 61 ? _eq : _prefix, 1);
    +  }
    +
    +  function getTokenFromCode(code) {
    +    switch(code) {
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
        case 46: // '.'
    +      return readToken_dot();
    + +
  • + + +
  • +
    + +
    + +
    +

    Punctuation tokens.

    + +
    + +
        case 40: ++tokPos; return finishToken(_parenL);
    +    case 41: ++tokPos; return finishToken(_parenR);
    +    case 59: ++tokPos; return finishToken(_semi);
    +    case 44: ++tokPos; return finishToken(_comma);
    +    case 91: ++tokPos; return finishToken(_bracketL);
    +    case 93: ++tokPos; return finishToken(_bracketR);
    +    case 123: ++tokPos; return finishToken(_braceL);
    +    case 125: ++tokPos; return finishToken(_braceR);
    +    case 58: ++tokPos; return finishToken(_colon);
    +    case 63: ++tokPos; return finishToken(_question);
    + +
  • + + +
  • +
    + +
    + +
    +

    ‘0x’ is a hexadecimal number.

    + +
    + +
        case 48: // '0'
    +      var next = input.charCodeAt(tokPos + 1);
    +      if (next === 120 || next === 88) return readHexNumber();
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
        case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
    +      return readNumber(false);
    + +
  • + + +
  • +
    + +
    + +
    +

    Quotes produce strings.

    + +
    + +
        case 34: case 39: // '"', "'"
    +      return inXJSTag ? readXJSStringLiteral() : readString(code);
    + +
  • + + +
  • +
    + +
    + +
    +

    Operators are parsed inline in tiny state machines. ‘=’ (61) is +often referred to. finishOp simply skips the amount of +characters it is given as second argument, and returns a token +of the type given by its first argument.

    + +
    + +
    +    case 47: // '/'
    +      return readToken_slash();
    +
    +    case 37: case 42: // '%*'
    +      return readToken_mult_modulo();
    +
    +    case 124: case 38: // '|&'
    +      return readToken_pipe_amp(code);
    +
    +    case 94: // '^'
    +      return readToken_caret();
    +
    +    case 43: case 45: // '+-'
    +      return readToken_plus_min(code);
    +
    +    case 60: case 62: // '<>'
    +      return readToken_lt_gt(code);
    +
    +    case 61: case 33: // '=!'
    +      return readToken_eq_excl(code);
    +
    +    case 126: // '~'
    +      return finishOp(_prefix, 1);
    +    }
    +
    +    return false;
    +  }
    +
    +  function readToken(forceRegexp) {
    +    if (!forceRegexp) tokStart = tokPos;
    +    else tokPos = tokStart + 1;
    +    if (options.locations) tokStartLoc = new Position;
    +    if (forceRegexp) return readRegexp();
    +    if (tokPos >= inputLen) return finishToken(_eof);
    +
    +    var code = input.charCodeAt(tokPos);
    + +
  • + + +
  • +
    + +
    + +
    +

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

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

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

    + +
    + +
        if (isIdentifierStart(code) || code === 92 /* '\' */) return readWord();
    +
    +    var tok = getTokenFromCode(code);
    +
    +    if (tok === false) {
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
          var ch = String.fromCharCode(code);
    +      if (ch === "\\" || nonASCIIidentifierStart.test(ch)) return readWord();
    +      raise(tokPos, "Unexpected character '" + ch + "'");
    +    }
    +    return tok;
    +  }
    +
    +  function finishOp(type, size) {
    +    var str = input.slice(tokPos, tokPos + size);
    +    tokPos += size;
    +    finishToken(type, str);
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function readRegexp() {
    +    var content = "", escaped, inClass, start = tokPos;
    +    for (;;) {
    +      if (tokPos >= inputLen) raise(start, "Unterminated regular expression");
    +      var ch = input.charAt(tokPos);
    +      if (newline.test(ch)) raise(start, "Unterminated regular expression");
    +      if (!escaped) {
    +        if (ch === "[") inClass = true;
    +        else if (ch === "]" && inClass) inClass = false;
    +        else if (ch === "/" && !inClass) break;
    +        escaped = ch === "\\";
    +      } else escaped = false;
    +      ++tokPos;
    +    }
    +    var content = input.slice(start, tokPos);
    +    ++tokPos;
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
        var mods = readWord1();
    +    if (mods && !/^[gmsiy]*$/.test(mods)) raise(start, "Invalid regular expression flag");
    +    try {
    +      var value = new RegExp(content, mods);
    +    } catch (e) {
    +      if (e instanceof SyntaxError) raise(start, "Error parsing regular expression: " + e.message);
    +      raise(e);
    +    }
    +    return finishToken(_regexp, value);
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function readInt(radix, len) {
    +    var start = tokPos, total = 0;
    +    for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {
    +      var code = input.charCodeAt(tokPos), val;
    +      if (code >= 97) val = code - 97 + 10; // a
    +      else if (code >= 65) val = code - 65 + 10; // A
    +      else if (code >= 48 && code <= 57) val = code - 48; // 0-9
    +      else val = Infinity;
    +      if (val >= radix) break;
    +      ++tokPos;
    +      total = total * radix + val;
    +    }
    +    if (tokPos === start || len != null && tokPos - start !== len) return null;
    +
    +    return total;
    +  }
    +
    +  function readHexNumber() {
    +    tokPos += 2; // 0x
    +    var val = readInt(16);
    +    if (val == null) raise(tokStart + 2, "Expected hexadecimal number");
    +    if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number");
    +    return finishToken(_num, val);
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function readNumber(startsWithDot) {
    +    var start = tokPos, isFloat = false, octal = input.charCodeAt(tokPos) === 48;
    +    if (!startsWithDot && readInt(10) === null) raise(start, "Invalid number");
    +    if (input.charCodeAt(tokPos) === 46) {
    +      ++tokPos;
    +      readInt(10);
    +      isFloat = true;
    +    }
    +    var next = input.charCodeAt(tokPos);
    +    if (next === 69 || next === 101) { // 'eE'
    +      next = input.charCodeAt(++tokPos);
    +      if (next === 43 || next === 45) ++tokPos; // '+-'
    +      if (readInt(10) === null) raise(start, "Invalid number");
    +      isFloat = true;
    +    }
    +    if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number");
    +
    +    var str = input.slice(start, tokPos), val;
    +    if (isFloat) val = parseFloat(str);
    +    else if (!octal || str.length === 1) val = parseInt(str, 10);
    +    else if (/[89]/.test(str) || strict) raise(start, "Invalid number");
    +    else val = parseInt(str, 8);
    +    return finishToken(_num, val);
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Read a string value, interpreting backslash-escapes.

    + +
    + +
    +  function readString(quote) {
    +    tokPos++;
    +    var out = "";
    +    for (;;) {
    +      if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant");
    +      var ch = input.charCodeAt(tokPos);
    +      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 += String.fromCharCode(readHexChar(4)); 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;
    +          }
    +        }
    +      } else {
    +        if (ch === 13 || ch === 10 || ch === 8232 || ch === 8233) raise(tokStart, "Unterminated string constant");
    +        out += String.fromCharCode(ch); // '\'
    +        ++tokPos;
    +      }
    +    }
    +  }
    +
    +  var XHTMLEntities = {
    +    quot: '\u0022',
    +    amp: '&',
    +    apos: '\u0027',
    +    lt: '<',
    +    gt: '>',
    +    nbsp: '\u00A0',
    +    iexcl: '\u00A1',
    +    cent: '\u00A2',
    +    pound: '\u00A3',
    +    curren: '\u00A4',
    +    yen: '\u00A5',
    +    brvbar: '\u00A6',
    +    sect: '\u00A7',
    +    uml: '\u00A8',
    +    copy: '\u00A9',
    +    ordf: '\u00AA',
    +    laquo: '\u00AB',
    +    not: '\u00AC',
    +    shy: '\u00AD',
    +    reg: '\u00AE',
    +    macr: '\u00AF',
    +    deg: '\u00B0',
    +    plusmn: '\u00B1',
    +    sup2: '\u00B2',
    +    sup3: '\u00B3',
    +    acute: '\u00B4',
    +    micro: '\u00B5',
    +    para: '\u00B6',
    +    middot: '\u00B7',
    +    cedil: '\u00B8',
    +    sup1: '\u00B9',
    +    ordm: '\u00BA',
    +    raquo: '\u00BB',
    +    frac14: '\u00BC',
    +    frac12: '\u00BD',
    +    frac34: '\u00BE',
    +    iquest: '\u00BF',
    +    Agrave: '\u00C0',
    +    Aacute: '\u00C1',
    +    Acirc: '\u00C2',
    +    Atilde: '\u00C3',
    +    Auml: '\u00C4',
    +    Aring: '\u00C5',
    +    AElig: '\u00C6',
    +    Ccedil: '\u00C7',
    +    Egrave: '\u00C8',
    +    Eacute: '\u00C9',
    +    Ecirc: '\u00CA',
    +    Euml: '\u00CB',
    +    Igrave: '\u00CC',
    +    Iacute: '\u00CD',
    +    Icirc: '\u00CE',
    +    Iuml: '\u00CF',
    +    ETH: '\u00D0',
    +    Ntilde: '\u00D1',
    +    Ograve: '\u00D2',
    +    Oacute: '\u00D3',
    +    Ocirc: '\u00D4',
    +    Otilde: '\u00D5',
    +    Ouml: '\u00D6',
    +    times: '\u00D7',
    +    Oslash: '\u00D8',
    +    Ugrave: '\u00D9',
    +    Uacute: '\u00DA',
    +    Ucirc: '\u00DB',
    +    Uuml: '\u00DC',
    +    Yacute: '\u00DD',
    +    THORN: '\u00DE',
    +    szlig: '\u00DF',
    +    agrave: '\u00E0',
    +    aacute: '\u00E1',
    +    acirc: '\u00E2',
    +    atilde: '\u00E3',
    +    auml: '\u00E4',
    +    aring: '\u00E5',
    +    aelig: '\u00E6',
    +    ccedil: '\u00E7',
    +    egrave: '\u00E8',
    +    eacute: '\u00E9',
    +    ecirc: '\u00EA',
    +    euml: '\u00EB',
    +    igrave: '\u00EC',
    +    iacute: '\u00ED',
    +    icirc: '\u00EE',
    +    iuml: '\u00EF',
    +    eth: '\u00F0',
    +    ntilde: '\u00F1',
    +    ograve: '\u00F2',
    +    oacute: '\u00F3',
    +    ocirc: '\u00F4',
    +    otilde: '\u00F5',
    +    ouml: '\u00F6',
    +    divide: '\u00F7',
    +    oslash: '\u00F8',
    +    ugrave: '\u00F9',
    +    uacute: '\u00FA',
    +    ucirc: '\u00FB',
    +    uuml: '\u00FC',
    +    yacute: '\u00FD',
    +    thorn: '\u00FE',
    +    yuml: '\u00FF',
    +    OElig: '\u0152',
    +    oelig: '\u0153',
    +    Scaron: '\u0160',
    +    scaron: '\u0161',
    +    Yuml: '\u0178',
    +    fnof: '\u0192',
    +    circ: '\u02C6',
    +    tilde: '\u02DC',
    +    Alpha: '\u0391',
    +    Beta: '\u0392',
    +    Gamma: '\u0393',
    +    Delta: '\u0394',
    +    Epsilon: '\u0395',
    +    Zeta: '\u0396',
    +    Eta: '\u0397',
    +    Theta: '\u0398',
    +    Iota: '\u0399',
    +    Kappa: '\u039A',
    +    Lambda: '\u039B',
    +    Mu: '\u039C',
    +    Nu: '\u039D',
    +    Xi: '\u039E',
    +    Omicron: '\u039F',
    +    Pi: '\u03A0',
    +    Rho: '\u03A1',
    +    Sigma: '\u03A3',
    +    Tau: '\u03A4',
    +    Upsilon: '\u03A5',
    +    Phi: '\u03A6',
    +    Chi: '\u03A7',
    +    Psi: '\u03A8',
    +    Omega: '\u03A9',
    +    alpha: '\u03B1',
    +    beta: '\u03B2',
    +    gamma: '\u03B3',
    +    delta: '\u03B4',
    +    epsilon: '\u03B5',
    +    zeta: '\u03B6',
    +    eta: '\u03B7',
    +    theta: '\u03B8',
    +    iota: '\u03B9',
    +    kappa: '\u03BA',
    +    lambda: '\u03BB',
    +    mu: '\u03BC',
    +    nu: '\u03BD',
    +    xi: '\u03BE',
    +    omicron: '\u03BF',
    +    pi: '\u03C0',
    +    rho: '\u03C1',
    +    sigmaf: '\u03C2',
    +    sigma: '\u03C3',
    +    tau: '\u03C4',
    +    upsilon: '\u03C5',
    +    phi: '\u03C6',
    +    chi: '\u03C7',
    +    psi: '\u03C8',
    +    omega: '\u03C9',
    +    thetasym: '\u03D1',
    +    upsih: '\u03D2',
    +    piv: '\u03D6',
    +    ensp: '\u2002',
    +    emsp: '\u2003',
    +    thinsp: '\u2009',
    +    zwnj: '\u200C',
    +    zwj: '\u200D',
    +    lrm: '\u200E',
    +    rlm: '\u200F',
    +    ndash: '\u2013',
    +    mdash: '\u2014',
    +    lsquo: '\u2018',
    +    rsquo: '\u2019',
    +    sbquo: '\u201A',
    +    ldquo: '\u201C',
    +    rdquo: '\u201D',
    +    bdquo: '\u201E',
    +    dagger: '\u2020',
    +    Dagger: '\u2021',
    +    bull: '\u2022',
    +    hellip: '\u2026',
    +    permil: '\u2030',
    +    prime: '\u2032',
    +    Prime: '\u2033',
    +    lsaquo: '\u2039',
    +    rsaquo: '\u203A',
    +    oline: '\u203E',
    +    frasl: '\u2044',
    +    euro: '\u20AC',
    +    image: '\u2111',
    +    weierp: '\u2118',
    +    real: '\u211C',
    +    trade: '\u2122',
    +    alefsym: '\u2135',
    +    larr: '\u2190',
    +    uarr: '\u2191',
    +    rarr: '\u2192',
    +    darr: '\u2193',
    +    harr: '\u2194',
    +    crarr: '\u21B5',
    +    lArr: '\u21D0',
    +    uArr: '\u21D1',
    +    rArr: '\u21D2',
    +    dArr: '\u21D3',
    +    hArr: '\u21D4',
    +    forall: '\u2200',
    +    part: '\u2202',
    +    exist: '\u2203',
    +    empty: '\u2205',
    +    nabla: '\u2207',
    +    isin: '\u2208',
    +    notin: '\u2209',
    +    ni: '\u220B',
    +    prod: '\u220F',
    +    sum: '\u2211',
    +    minus: '\u2212',
    +    lowast: '\u2217',
    +    radic: '\u221A',
    +    prop: '\u221D',
    +    infin: '\u221E',
    +    ang: '\u2220',
    +    and: '\u2227',
    +    or: '\u2228',
    +    cap: '\u2229',
    +    cup: '\u222A',
    +    'int': '\u222B',
    +    there4: '\u2234',
    +    sim: '\u223C',
    +    cong: '\u2245',
    +    asymp: '\u2248',
    +    ne: '\u2260',
    +    equiv: '\u2261',
    +    le: '\u2264',
    +    ge: '\u2265',
    +    sub: '\u2282',
    +    sup: '\u2283',
    +    nsub: '\u2284',
    +    sube: '\u2286',
    +    supe: '\u2287',
    +    oplus: '\u2295',
    +    otimes: '\u2297',
    +    perp: '\u22A5',
    +    sdot: '\u22C5',
    +    lceil: '\u2308',
    +    rceil: '\u2309',
    +    lfloor: '\u230A',
    +    rfloor: '\u230B',
    +    lang: '\u2329',
    +    rang: '\u232A',
    +    loz: '\u25CA',
    +    spades: '\u2660',
    +    clubs: '\u2663',
    +    hearts: '\u2665',
    +    diams: '\u2666'
    +  };
    +
    +  function readXJSEntity() {
    +    var str = '', count = 0, entity;
    +    var ch = nextChar();
    +    if (ch !== '&') raise(tokPos, "Entity must start with an ampersand");
    +    tokPos++;
    +    while (tokPos < inputLen && count++ < 10) {
    +      ch = input.charAt(tokPos++);
    +      if (ch === ';') {
    +        break;
    +      }
    +      str += ch;
    +    }
    +
    +    if (str[0] === '#' && str[1] === 'x') {
    +      entity = String.fromCharCode(parseInt(str.substr(2), 16));
    +    } else if (str[0] === '#') {
    +      entity = String.fromCharCode(parseInt(str.substr(1), 10));
    +    } else {
    +      entity = XHTMLEntities[str];
    +    }
    +    return entity;
    +  }
    +
    +  function readXJSText(stopChars) {
    +    var str = '';
    +    while (tokPos < inputLen) {
    +      var ch = nextChar();
    +      if (stopChars.indexOf(ch) !== -1) {
    +        break;
    +      }
    +      if (ch === '&') {
    +        str += readXJSEntity();
    +      } else {
    +        ++tokPos;
    +        if (ch === '\r' && nextChar() === '\n') {
    +          str += ch;
    +          ++tokPos;
    +          ch = '\n';
    +        }
    +        if (ch === '\n' && options.locations) {
    +          tokLineStart = tokPos;
    +          ++tokCurLine;
    +        }
    +        str += ch;
    +      }
    +    }
    +    return finishToken(_xjsText, str);
    +  }
    +
    +  function readXJSStringLiteral() {
    +    var quote = input.charCodeAt(tokPos);
    +
    +    if (quote !== 34 && quote !== 39) {
    +      raise("String literal must starts with a quote");
    +    }
    +
    +    ++tokPos;
    +
    +    readXJSText([String.fromCharCode(quote)]);
    +
    +    if (quote !== input.charCodeAt(tokPos)) {
    +      unexpected();
    +    }
    +
    +    ++tokPos;
    +
    +    return finishToken(tokType, tokVal);
    +  }
    +
    +
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function readHexChar(len) {
    +    var n = readInt(16, len);
    +    if (n === null) raise(tokStart, "Bad character escape sequence");
    +    return n;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  var containsEsc;
    + +
  • + + +
  • +
    + +
    + +
    +

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

    +

    Only builds up the word character-by-character when it actually +containeds an escape, as a micro-optimization.

    + +
    + +
    +  function readWord1() {
    +    containsEsc = false;
    +    var word, first = true, start = tokPos;
    +    for (;;) {
    +      var ch = input.charCodeAt(tokPos);
    +      if (isIdentifierChar(ch) || (inXJSTag && ch === 45)) {
    +        if (containsEsc) word += input.charAt(tokPos);
    +        ++tokPos;
    +      } else if (ch === 92 && !inXJSTag) { // "\"
    +        if (!containsEsc) word = input.slice(start, tokPos);
    +        containsEsc = true;
    +        if (input.charCodeAt(++tokPos) != 117) // "u"
    +          raise(tokPos, "Expecting Unicode escape sequence \\uXXXX");
    +        ++tokPos;
    +        var esc = readHexChar(4);
    +        var escStr = String.fromCharCode(esc);
    +        if (!escStr) raise(tokPos - 1, "Invalid Unicode escape");
    +        if (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc)))
    +          raise(tokPos - 4, "Invalid Unicode escape");
    +        word += escStr;
    +      } else {
    +        break;
    +      }
    +      first = false;
    +    }
    +    return containsEsc ? word : input.slice(start, tokPos);
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function readWord() {
    +    var word = readWord1();
    +    var type = inXJSTag ? _xjsName : _name;
    +    if (!containsEsc && isKeyword(word))
    +      type = keywordTypes[word];
    +    return finishToken(type, word);
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parser

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

    A recursive descent parser operates by defining functions for all +syntactic elements, and recursively calling those, each function +advancing the input stream and returning an AST node. Precedence +of constructs (for example, the fact that !x[1] means !(x[1]) +instead of (!x)[1] is handled by the fact that the parser +function that parses unary prefix operators is called first, and +in turn calls the function that parses [] subscripts — that +way, it’ll receive the node for x[1] already parsed, and wraps +that in the unary operator node.

    +

    Acorn uses an operator precedence parser to handle binary +operator precedence, because it is much more compact than using +the technique outlined above, which uses different, nesting +functions to specify precedence, for all of the ten binary +precedence levels that JavaScript defines.

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

    Parser utilities

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

    Continue to the next token.

    + +
    + +
    +  function next() {
    +    lastStart = tokStart;
    +    lastEnd = tokEnd;
    +    lastEndLoc = tokEndLoc;
    +    readToken();
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function setStrict(strct) {
    +    strict = strct;
    +    tokPos = tokStart;
    +    if (options.locations) {
    +      while (tokPos < tokLineStart) {
    +        tokLineStart = input.lastIndexOf("\n", tokLineStart - 2) + 1;
    +        --tokCurLine;
    +      }
    +    }
    +    skipSpace();
    +    readToken();
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Start an AST node, attaching a start offset.

    + +
    + +
    +  function Node() {
    +    this.type = null;
    +    this.start = tokStart;
    +    this.end = null;
    +  }
    +  
    +  exports.Node = Node;
    +
    +  function SourceLocation() {
    +    this.start = tokStartLoc;
    +    this.end = null;
    +    if (sourceFile !== null) this.source = sourceFile;
    +  }
    +
    +  function startNode() {
    +    var node = new Node();
    +    if (options.locations)
    +      node.loc = new SourceLocation();
    +    if (options.directSourceFile)
    +      node.sourceFile = options.directSourceFile;
    +    if (options.ranges)
    +      node.range = [tokStart, 0];
    +    return node;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function startNodeFrom(other) {
    +    var node = new Node();
    +    node.start = other.start;
    +    if (options.locations) {
    +      node.loc = new SourceLocation();
    +      node.loc.start = other.loc.start;
    +    }
    +    if (options.ranges)
    +      node.range = [other.range[0], 0];
    +
    +    return node;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Finish an AST node, adding type and end properties.

    + +
    + +
    +  function finishNode(node, type) {
    +    node.type = type;
    +    node.end = lastEnd;
    +    if (options.locations)
    +      node.loc.end = lastEndLoc;
    +    if (options.ranges)
    +      node.range[1] = lastEnd;
    +    return node;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function isUseStrict(stmt) {
    +    return options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" &&
    +      stmt.expression.type === "Literal" && stmt.expression.value === "use strict";
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function eat(type) {
    +    if (tokType === type) {
    +      next();
    +      return true;
    +    }
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function canInsertSemicolon() {
    +    return !options.strictSemicolons &&
    +      (tokType === _eof || tokType === _braceR || newline.test(input.slice(lastEnd, tokStart)));
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function semicolon() {
    +    if (!eat(_semi) && !canInsertSemicolon()) unexpected();
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function expect(type) {
    +    if (tokType === type) next();
    +    else unexpected();
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    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.

    + +
    + +
    +  function nextChar() {
    +    return input.charAt(tokPos);
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Raise an unexpected token error.

    + +
    + +
    +  function unexpected() {
    +    raise(tokStart, "Unexpected token");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function checkLVal(expr) {
    +    if (expr.type !== "Identifier" && expr.type !== "MemberExpression")
    +      raise(expr.start, "Assigning to rvalue");
    +    if (strict && expr.type === "Identifier" && isStrictBadIdWord(expr.name))
    +      raise(expr.start, "Assigning to " + expr.name + " in strict mode");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Statement parsing

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

    Parse a program. Initializes the parser, reads any number of +statements, and wraps them in a Program node. Optionally takes a +program argument. If present, the statements will be appended +to its body instead of creating a new node.

    + +
    + +
    +  function parseTopLevel(program) {
    +    lastStart = lastEnd = tokPos;
    +    if (options.locations) lastEndLoc = new Position;
    +    inFunction = strict = null;
    +    labels = [];
    +    readToken();
    +
    +    var node = program || startNode(), first = true;
    +    if (!program) node.body = [];
    +    while (tokType !== _eof) {
    +      var stmt = parseStatement();
    +      node.body.push(stmt);
    +      if (first && isUseStrict(stmt)) setStrict(true);
    +      first = false;
    +    }
    +    return finishNode(node, "Program");
    +  }
    +
    +  var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"};
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse a single statement.

    +

    If expecting a statement and finding a slash operator, parse a +regular expression literal. This is to handle cases like +if (foo) /blah/.exec(foo);, where looking at the previous token +does not help.

    + +
    + +
    +  function parseStatement() {
    +    if (tokType === _slash || tokType === _assign && tokVal == "/=")
    +      readToken(true);
    +
    +    var starttype = tokType, node = startNode();
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +    switch (starttype) {
    +    case _break: case _continue: return parseBreakContinueStatement(node, starttype.keyword);
    +    case _debugger: return parseDebuggerStatement(node);
    +    case _do: return parseDoStatement(node);
    +    case _for: return parseForStatement(node);
    +    case _function: return parseFunctionStatement(node);
    +    case _if: return parseIfStatement(node);
    +    case _return: return parseReturnStatement(node);
    +    case _switch: return parseSwitchStatement(node);
    +    case _throw: return parseThrowStatement(node);
    +    case _try: return parseTryStatement(node);
    +    case _var: case _let: case _const: return parseVarStatement(node, starttype.keyword);
    +    case _while: return parseWhileStatement(node);
    +    case _with: return parseWithStatement(node);
    +    case _braceL: return parseBlock(); // no point creating a function for this
    +    case _semi: return parseEmptyStatement(node);
    + +
  • + + +
  • +
    + +
    + +
    +

    If the statement does not start with a statement keyword or a +brace, it’s an ExpressionStatement or LabeledStatement. We +simply start parsing an expression, and afterwards, if the +next token is a colon and the expression was a simple +Identifier node, we switch to interpreting it as a label.

    + +
    + +
        default:
    +      var maybeName = tokVal, expr = parseExpression();
    +      if (starttype === _name && expr.type === "Identifier" && eat(_colon))
    +        return parseLabeledStatement(node, maybeName, expr);
    +      else return parseExpressionStatement(node, expr);
    +    }
    +  }
    +  
    +  function parseBreakContinueStatement(node, keyword) {
    +    var isBreak = keyword == "break";
    +    next();
    +    if (eat(_semi) || canInsertSemicolon()) node.label = null;
    +    else if (tokType !== _name) unexpected();
    +    else {
    +      node.label = parseIdent();
    +      semicolon();
    +    }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
        for (var i = 0; i < labels.length; ++i) {
    +      var lab = labels[i];
    +      if (node.label == null || lab.name === node.label.name) {
    +        if (lab.kind != null && (isBreak || lab.kind === "loop")) break;
    +        if (node.label && isBreak) break;
    +      }
    +    }
    +    if (i === labels.length) raise(node.start, "Unsyntactic " + keyword);
    +    return finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement");
    +  }
    +  
    +  function parseDebuggerStatement(node) {
    +    next();
    +    semicolon();
    +    return finishNode(node, "DebuggerStatement");
    +  }
    +  
    +  function parseDoStatement(node) {
    +    next();
    +    labels.push(loopLabel);
    +    node.body = parseStatement();
    +    labels.pop();
    +    expect(_while);
    +    node.test = parseParenExpression();
    +    semicolon();
    +    return finishNode(node, "DoWhileStatement");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Disambiguating between a for and a for/in loop is +non-trivial. Basically, we have to parse the init var +statement or expression, disallowing the in operator (see +the second parameter to parseExpression), and then check +whether the next token is in. When there is no init part +(semicolon immediately after the opening parenthesis), it is +a regular for loop.

    + +
    + +
      
    +  function parseForStatement(node) {
    +    next();
    +    labels.push(loopLabel);
    +    expect(_parenL);
    +    if (tokType === _semi) return parseFor(node, null);
    +    if (tokType === _var || tokType === _let) {
    +      var init = startNode(), varKind = tokType.keyword;
    +      next();
    +      parseVar(init, true, varKind);
    +      finishNode(init, "VariableDeclaration");
    +      if (init.declarations.length === 1 && eat(_in))
    +        return parseForIn(node, init);
    +      return parseFor(node, init);
    +    }
    +    var init = parseExpression(false, true);
    +    if (eat(_in)) {checkLVal(init); return parseForIn(node, init);}
    +    return parseFor(node, init);
    +  }
    +  
    +  function parseFunctionStatement(node) {
    +    next();
    +    return parseFunction(node, true);
    +  }
    +  
    +  function parseIfStatement(node) {
    +    next();
    +    node.test = parseParenExpression();
    +    node.consequent = parseStatement();
    +    node.alternate = eat(_else) ? parseStatement() : null;
    +    return finishNode(node, "IfStatement");
    +  }
    +  
    +  function parseReturnStatement(node) {
    +    if (!inFunction && !options.allowReturnOutsideFunction)
    +      raise(tokStart, "'return' outside of function");
    +    next();
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +    if (eat(_semi) || canInsertSemicolon()) node.argument = null;
    +    else { node.argument = parseExpression(); semicolon(); }
    +    return finishNode(node, "ReturnStatement");
    +  }
    +  
    +  function parseSwitchStatement(node) {
    +    next();
    +    node.discriminant = parseParenExpression();
    +    node.cases = [];
    +    expect(_braceL);
    +    labels.push(switchLabel);
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +    for (var cur, sawDefault; tokType != _braceR;) {
    +      if (tokType === _case || tokType === _default) {
    +        var isCase = tokType === _case;
    +        if (cur) finishNode(cur, "SwitchCase");
    +        node.cases.push(cur = startNode());
    +        cur.consequent = [];
    +        next();
    +        if (isCase) cur.test = parseExpression();
    +        else {
    +          if (sawDefault) raise(lastStart, "Multiple default clauses"); sawDefault = true;
    +          cur.test = null;
    +        }
    +        expect(_colon);
    +      } else {
    +        if (!cur) unexpected();
    +        cur.consequent.push(parseStatement());
    +      }
    +    }
    +    if (cur) finishNode(cur, "SwitchCase");
    +    next(); // Closing brace
    +    labels.pop();
    +    return finishNode(node, "SwitchStatement");
    +  }
    +  
    +  function parseThrowStatement(node) {
    +    next();
    +    if (newline.test(input.slice(lastEnd, tokStart)))
    +      raise(lastEnd, "Illegal newline after throw");
    +    node.argument = parseExpression();
    +    semicolon();
    +    return finishNode(node, "ThrowStatement");next();
    +    if (newline.test(input.slice(lastEnd, tokStart)))
    +      raise(lastEnd, "Illegal newline after throw");
    +    node.argument = parseExpression();
    +    semicolon();
    +    return finishNode(node, "ThrowStatement");
    +  }
    +  
    +  function parseTryStatement(node) {
    +    next();
    +    node.block = parseBlock();
    +    node.handler = null;
    +    if (tokType === _catch) {
    +      var clause = startNode();
    +      next();
    +      expect(_parenL);
    +      clause.param = parseIdent();
    +      if (strict && isStrictBadIdWord(clause.param.name))
    +        raise(clause.param.start, "Binding " + clause.param.name + " in strict mode");
    +      expect(_parenR);
    +      clause.guard = null;
    +      clause.body = parseBlock();
    +      node.handler = finishNode(clause, "CatchClause");
    +    }
    +    node.guardedHandlers = empty;
    +    node.finalizer = eat(_finally) ? parseBlock() : null;
    +    if (!node.handler && !node.finalizer)
    +      raise(node.start, "Missing catch or finally clause");
    +    return finishNode(node, "TryStatement");
    +  }
    +  
    +  function parseVarStatement(node, kind) {
    +    next();
    +    parseVar(node, false, kind);
    +    semicolon();
    +    return finishNode(node, "VariableDeclaration");
    +  }
    +  
    +  function parseWhileStatement(node) {
    +    next();
    +    node.test = parseParenExpression();
    +    labels.push(loopLabel);
    +    node.body = parseStatement();
    +    labels.pop();
    +    return finishNode(node, "WhileStatement");
    +  }
    +  
    +  function parseWithStatement(node) {
    +    if (strict) raise(tokStart, "'with' in strict mode");
    +    next();
    +    node.object = parseParenExpression();
    +    node.body = parseStatement();
    +    return finishNode(node, "WithStatement");
    +  }
    +  
    +  function parseEmptyStatement(node) {
    +    next();
    +    return finishNode(node, "EmptyStatement");
    +  }
    +  
    +  function parseLabeledStatement(node, maybeName, expr) {
    +    for (var i = 0; i < labels.length; ++i)
    +      if (labels[i].name === maybeName) raise(expr.start, "Label '" + maybeName + "' is already declared");
    +    var kind = tokType.isLoop ? "loop" : tokType === _switch ? "switch" : null;
    +    labels.push({name: maybeName, kind: kind});
    +    node.body = parseStatement();
    +    labels.pop();
    +    node.label = expr;
    +    return finishNode(node, "LabeledStatement");
    +  }
    +  
    +  function parseExpressionStatement(node, expr) {
    +    node.expression = expr;
    +    semicolon();
    +    return finishNode(node, "ExpressionStatement");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function parseParenExpression() {
    +    expect(_parenL);
    +    var val = parseExpression();
    +    expect(_parenR);
    +    return val;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function parseBlock(allowStrict) {
    +    var node = startNode(), first = true, strict = false, oldStrict;
    +    node.body = [];
    +    expect(_braceL);
    +    while (!eat(_braceR)) {
    +      var stmt = parseStatement();
    +      node.body.push(stmt);
    +      if (first && allowStrict && isUseStrict(stmt)) {
    +        oldStrict = strict;
    +        setStrict(strict = true);
    +      }
    +      first = false;
    +    }
    +    if (strict && !oldStrict) setStrict(false);
    +    return finishNode(node, "BlockStatement");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse a regular for loop. The disambiguation code in +parseStatement will already have parsed the init statement or +expression.

    + +
    + +
    +  function parseFor(node, init) {
    +    node.init = init;
    +    expect(_semi);
    +    node.test = tokType === _semi ? null : parseExpression();
    +    expect(_semi);
    +    node.update = tokType === _parenR ? null : parseExpression();
    +    expect(_parenR);
    +    node.body = parseStatement();
    +    labels.pop();
    +    return finishNode(node, "ForStatement");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse a for/in loop.

    + +
    + +
    +  function parseForIn(node, init) {
    +    node.left = init;
    +    node.right = parseExpression();
    +    expect(_parenR);
    +    node.body = parseStatement();
    +    labels.pop();
    +    return finishNode(node, "ForInStatement");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse a list of variable declarations.

    + +
    + +
    +  function parseVar(node, noIn, kind) {
    +    node.declarations = [];
    +    node.kind = kind;
    +    for (;;) {
    +      var decl = startNode();
    +      decl.id = parseIdent();
    +      if (strict && isStrictBadIdWord(decl.id.name))
    +        raise(decl.id.start, "Binding " + decl.id.name + " in strict mode");
    +      decl.init = eat(_eq) ? parseExpression(true, noIn) : (kind === _const.keyword ? unexpected() : null);
    +      node.declarations.push(finishNode(decl, "VariableDeclarator"));
    +      if (!eat(_comma)) break;
    +    }
    +    return node;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Expression parsing

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

    These nest, from the most general expression type at the top to +‘atomic’, nondivisible expression types at the bottom. Most of +the functions will simply let the function(s) below them parse, +and, if the syntactic construct they handle is present, wrap +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) +or the in operator (in for loops initalization expressions).

    + +
    + +
    +  function parseExpression(noComma, noIn) {
    +    var expr = parseMaybeAssign(noIn);
    +    if (!noComma && tokType === _comma) {
    +      var node = startNodeFrom(expr);
    +      node.expressions = [expr];
    +      while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn));
    +      return finishNode(node, "SequenceExpression");
    +    }
    +    return expr;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function parseMaybeAssign(noIn) {
    +    var left = parseMaybeConditional(noIn);
    +    if (tokType.isAssign) {
    +      var node = startNodeFrom(left);
    +      node.operator = tokVal;
    +      node.left = left;
    +      next();
    +      node.right = parseMaybeAssign(noIn);
    +      checkLVal(left);
    +      return finishNode(node, "AssignmentExpression");
    +    }
    +    return left;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse a ternary conditional (?:) operator.

    + +
    + +
    +  function parseMaybeConditional(noIn) {
    +    var expr = parseExprOps(noIn);
    +    if (eat(_question)) {
    +      var node = startNodeFrom(expr);
    +      node.test = expr;
    +      node.consequent = parseExpression(true);
    +      expect(_colon);
    +      node.alternate = parseExpression(true, noIn);
    +      return finishNode(node, "ConditionalExpression");
    +    }
    +    return expr;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Start the precedence parser.

    + +
    + +
    +  function parseExprOps(noIn) {
    +    return parseExprOp(parseMaybeUnary(), -1, noIn);
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse binary operators with the operator precedence parsing +algorithm. left is the left-hand side of the operator. +minPrec provides context that allows the function to stop and +defer further parser to one of its callers when it encounters an +operator that has a lower precedence than the set it is parsing.

    + +
    + +
    +  function parseExprOp(left, minPrec, noIn) {
    +    var prec = tokType.binop;
    +    if (prec != null && (!noIn || tokType !== _in)) {
    +      if (prec > minPrec) {
    +        var node = startNodeFrom(left);
    +        node.left = left;
    +        node.operator = tokVal;
    +        var op = tokType;
    +        next();
    +        node.right = parseExprOp(parseMaybeUnary(), prec, noIn);
    +        var exprNode = finishNode(node, (op === _logicalOR || op === _logicalAND) ? "LogicalExpression" : "BinaryExpression");
    +        return parseExprOp(exprNode, minPrec, noIn);
    +      }
    +    }
    +    return left;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse unary operators, both prefix and postfix.

    + +
    + +
    +  function parseMaybeUnary() {
    +    if (tokType.prefix) {
    +      var node = startNode(), update = tokType.isUpdate;
    +      node.operator = tokVal;
    +      node.prefix = true;
    +      tokRegexpAllowed = true;
    +      next();
    +      node.argument = parseMaybeUnary();
    +      if (update) checkLVal(node.argument);
    +      else if (strict && node.operator === "delete" &&
    +               node.argument.type === "Identifier")
    +        raise(node.start, "Deleting local variable in strict mode");
    +      return finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
    +    }
    +    var expr = parseExprSubscripts();
    +    while (tokType.postfix && !canInsertSemicolon()) {
    +      var node = startNodeFrom(expr);
    +      node.operator = tokVal;
    +      node.prefix = false;
    +      node.argument = expr;
    +      checkLVal(expr);
    +      next();
    +      expr = finishNode(node, "UpdateExpression");
    +    }
    +    return expr;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function parseExprSubscripts() {
    +    return parseSubscripts(parseExprAtom());
    +  }
    +
    +  function parseSubscripts(base, noCalls) {
    +    if (eat(_dot)) {
    +      var node = startNodeFrom(base);
    +      node.object = base;
    +      node.property = parseIdent(true);
    +      node.computed = false;
    +      return parseSubscripts(finishNode(node, "MemberExpression"), noCalls);
    +    } else if (eat(_bracketL)) {
    +      var node = startNodeFrom(base);
    +      node.object = base;
    +      node.property = parseExpression();
    +      node.computed = true;
    +      expect(_bracketR);
    +      return parseSubscripts(finishNode(node, "MemberExpression"), noCalls);
    +    } else if (!noCalls && eat(_parenL)) {
    +      var node = startNodeFrom(base);
    +      node.callee = base;
    +      node.arguments = parseExprList(_parenR, false);
    +      return parseSubscripts(finishNode(node, "CallExpression"), noCalls);
    +    } else return base;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse an atomic expression — either a single token that is an +expression, an expression started by a keyword like function or +new, or an expression wrapped in punctuation like (), [], +or {}.

    + +
    + +
    +  function parseExprAtom() {
    +    switch (tokType) {
    +    case _this:
    +      var node = startNode();
    +      next();
    +      return finishNode(node, "ThisExpression");
    +    case _name:
    +      return parseIdent();
    +    case _num: case _string: case _regexp: case _xjsText:
    +      var node = startNode();
    +      node.value = tokVal;
    +      node.raw = input.slice(tokStart, tokEnd);
    +      next();
    +      return finishNode(node, "Literal");
    +
    +    case _null: case _true: case _false:
    +      var node = startNode();
    +      node.value = tokType.atomValue;
    +      node.raw = tokType.keyword;
    +      next();
    +      return finishNode(node, "Literal");
    +
    +    case _parenL:
    +      var tokStartLoc1 = tokStartLoc, tokStart1 = tokStart;
    +      next();
    +      var val = parseExpression();
    +      val.start = tokStart1;
    +      val.end = tokEnd;
    +      if (options.locations) {
    +        val.loc.start = tokStartLoc1;
    +        val.loc.end = tokEndLoc;
    +      }
    +      if (options.ranges)
    +        val.range = [tokStart1, tokEnd];
    +      expect(_parenR);
    +      return val;
    +
    +    case _bracketL:
    +      var node = startNode();
    +      next();
    +      node.elements = parseExprList(_bracketR, true, true);
    +      return finishNode(node, "ArrayExpression");
    +
    +    case _braceL:
    +      return parseObj();
    +
    +    case _function:
    +      var node = startNode();
    +      next();
    +      return parseFunction(node, false);
    +
    +    case _new:
    +      return parseNew();
    +
    +    case _relational:
    +      if (tokVal === '<') {
    +        return parseXJSElement();
    +      }
    +
    +    default:
    +      unexpected();
    +    }
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function parseNew() {
    +    var node = startNode();
    +    next();
    +    node.callee = parseSubscripts(parseExprAtom(), true);
    +    if (eat(_parenL)) node.arguments = parseExprList(_parenR, false);
    +    else node.arguments = empty;
    +    return finishNode(node, "NewExpression");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse an object literal.

    + +
    + +
    +  function parseObj() {
    +    var node = startNode(), first = true, sawGetSet = false;
    +    node.properties = [];
    +    next();
    +    while (!eat(_braceR)) {
    +      if (!first) {
    +        expect(_comma);
    +        if (options.allowTrailingCommas && eat(_braceR)) break;
    +      } else first = false;
    +
    +      var prop = {key: parsePropertyName()}, isGetSet = false, kind;
    +      if (eat(_colon)) {
    +        prop.value = parseExpression(true);
    +        kind = prop.kind = "init";
    +      } else if (options.ecmaVersion >= 5 && prop.key.type === "Identifier" &&
    +                 (prop.key.name === "get" || prop.key.name === "set")) {
    +        isGetSet = sawGetSet = true;
    +        kind = prop.kind = prop.key.name;
    +        prop.key = parsePropertyName();
    +        if (tokType !== _parenL) unexpected();
    +        prop.value = parseFunction(startNode(), false);
    +      } else unexpected();
    + +
  • + + +
  • +
    + +
    + +
    +

    getters and setters are not allowed to clash — either with +each other or with an init property — and in strict mode, +init properties are also not allowed to be repeated.

    + +
    + +
    +      if (prop.key.type === "Identifier" && (strict || sawGetSet)) {
    +        for (var i = 0; i < node.properties.length; ++i) {
    +          var other = node.properties[i];
    +          if (other.key.name === prop.key.name) {
    +            var conflict = kind == other.kind || isGetSet && other.kind === "init" ||
    +              kind === "init" && (other.kind === "get" || other.kind === "set");
    +            if (conflict && !strict && kind === "init" && other.kind === "init") conflict = false;
    +            if (conflict) raise(prop.key.start, "Redefinition of property");
    +          }
    +        }
    +      }
    +      node.properties.push(prop);
    +    }
    +    return finishNode(node, "ObjectExpression");
    +  }
    +
    +  function parsePropertyName() {
    +    if (tokType === _num || tokType === _string) return parseExprAtom();
    +    return parseIdent(true);
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function parseFunction(node, isStatement) {
    +    if (tokType === _name) node.id = parseIdent();
    +    else if (isStatement) unexpected();
    +    else node.id = null;
    +    node.params = [];
    +    node.rest = null;
    +    expect(_parenL);
    +    for (;;) {
    +      if (eat(_parenR)) {
    +        break;
    +      } else if (options.ecmaVersion >= 6 && eat(_ellipsis)) {
    +        node.rest = parseIdent();
    +        expect(_parenR);
    +        break;
    +      } else {
    +        node.params.push(parseIdent());
    +        if (!eat(_comma)) {
    +          expect(_parenR);
    +          break;
    +        }
    +      }
    +    }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
        var oldInFunc = inFunction, oldLabels = labels;
    +    inFunction = true; labels = [];
    +    node.body = parseBlock(true);
    +    inFunction = oldInFunc; labels = oldLabels;
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
        if (strict || node.body.body.length && isUseStrict(node.body.body[0])) {
    + +
  • + + +
  • +
    + +
    + +
    +

    Negative indices are used to reuse loop body for node.rest and node.id

    + +
    + +
          for (var i = -2, id; i < node.params.length; ++i) {
    +        if (i >= 0) {
    +          id = node.params[i];
    +        } else if (i == -2) {
    +          if (node.rest) id = node.rest;
    +          else continue;
    +        } else {
    +          if (node.id) id = node.id;
    +          else continue;
    +        }
    +        if (isStrictReservedWord(id.name) || isStrictBadIdWord(id.name))
    +          raise(id.start, "Defining '" + id.name + "' in strict mode");
    +        if (i >= 0) for (var j = 0; j < i; ++j) if (id.name === node.params[j].name)
    +          raise(id.start, "Argument name clash in strict mode");
    +      }
    +    }
    +
    +    return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parses a comma-separated list of expressions, and returns them as +an array. close is the token type that ends the list, and +allowEmpty can be turned on to allow subsequent commas with +nothing in between them to be parsed as null (which is needed +for array literals).

    + +
    + +
    +  function parseExprList(close, allowTrailingComma, allowEmpty) {
    +    var elts = [], first = true;
    +    while (!eat(close)) {
    +      if (!first) {
    +        expect(_comma);
    +        if (allowTrailingComma && options.allowTrailingCommas && eat(close)) break;
    +      } else first = false;
    +
    +      if (allowEmpty && tokType === _comma) elts.push(null);
    +      else elts.push(parseExpression(true));
    +    }
    +    return elts;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function parseIdent(liberal) {
    +    var node = startNode();
    +    if (liberal && options.forbidReserved == "everywhere") liberal = false;
    +    if (tokType === _name) {
    +      if (!liberal &&
    +          (options.forbidReserved &&
    +           (options.ecmaVersion === 3 ? isReservedWord3 : isReservedWord5)(tokVal) ||
    +           strict && isStrictReservedWord(tokVal)) &&
    +          input.slice(tokStart, tokEnd).indexOf("\\") == -1)
    +        raise(tokStart, "The keyword '" + tokVal + "' is reserved");
    +      node.name = tokVal;
    +    } else if (liberal && tokType.keyword) {
    +      node.name = tokType.keyword;
    +    } else {
    +      unexpected();
    +    }
    +    tokRegexpAllowed = false;
    +    next();
    +    return finishNode(node, "Identifier");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Transforms JSX element name to string.

    + +
    + +
    +  function getQualifiedXJSName(object) {
    +    if (object.type === "XJSIdentifier") {
    +      return object.name;
    +    }
    +    if (object.type === "XJSNamespacedName") {
    +      return object.namespace.name + ':' + object.name.name;
    +    }
    +    if (object.type === "XJSMemberExpression") {
    +      return (
    +        getQualifiedXJSName(object.object) + '.' +
    +        getQualifiedXJSName(object.property)
    +      );
    +    }
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse next token as JSX identifier

    + +
    + +
    +  function parseXJSIdentifier() {
    +    var node = startNode();
    +    if (tokType === _xjsName) {
    +      node.name = tokVal;
    +    } else if (tokType.keyword) {
    +      node.name = tokType.keyword;
    +    } else {
    +      unexpected();
    +    }
    +    tokRegexpAllowed = false;
    +    next();
    +    return finishNode(node, "XJSIdentifier");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse namespaced identifier.

    + +
    + +
    +  function parseXJSNamespacedName() {
    +    var node = startNode();
    +
    +    node.namespace = parseXJSIdentifier();
    +    expect(_colon);
    +    node.name = parseXJSIdentifier();
    +
    +    return finishNode(node, "XJSNamespacedName");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse JSX object.

    + +
    + +
    +  function parseXJSMemberExpression() {
    +    var node = parseXJSIdentifier();
    +
    +    while (eat(_dot)) {
    +      var newNode = startNodeFrom(node);
    +      newNode.object = node;
    +      newNode.property = parseXJSIdentifier();
    +      node = finishNode(newNode, "XJSMemberExpression");
    +    }
    +
    +    return node;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function parseXJSElementName() {
    +    switch (nextChar()) {
    +      case ':':
    +        return parseXJSNamespacedName();
    +
    +      case '.':
    +        return parseXJSMemberExpression();
    +
    +      default:
    +        return parseXJSIdentifier();
    +    }
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parses attribute name as optionally namespaced identifier.

    + +
    + +
    +  function parseXJSAttributeName() {
    +    if (nextChar() === ':') {
    +      return parseXJSNamespacedName();
    +    }
    +
    +    return parseXJSIdentifier();
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parses any type of JSX attribute value.

    + +
    + +
    +  function parseXJSAttributeValue() {
    +    var node;
    +    if (tokType === _braceL) {
    +      node = parseXJSExpressionContainer();
    +      if (node.expression.type === "XJSEmptyExpression") {
    +        raise(
    +          node.start,
    +            'XJS attributes must only be assigned a non-empty ' +
    +            'expression'
    +        );
    +      }
    +    } else if (tokVal === '<') {
    +      node = parseXJSElement();
    +    } else if (tokType === _xjsText) {
    +      node = parseExprAtom();
    +    } else {
    +      raise(tokStart, "XJS value should be either an expression or a quoted XJS text");
    +    }
    +    return node;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    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 +at the beginning of the next one (right brace).

    + +
    + +
    +  function parseXJSEmptyExpression() {
    +    if (tokType !== _braceR) {
    +      unexpected();
    +    }
    +
    +    var tmp;
    +
    +    tmp = tokStart;
    +    tokStart = lastEnd;
    +    lastEnd = tmp;
    +
    +    tmp = tokStartLoc;
    +    tokStartLoc = lastEndLoc;
    +    lastEndLoc = tmp;
    +
    +    return finishNode(startNode(), "XJSEmptyExpression");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parses JSX expression enclosed into curly brackets.

    + +
    + +
    +  function parseXJSExpressionContainer() {
    +    var node = startNode();
    +
    +    var origInXJSTag = inXJSTag;
    +    inXJSTag = false;
    +
    +    expect(_braceL);
    +
    +    node.expression = tokType === _braceR ? parseXJSEmptyExpression() : parseExpression();
    +
    +    inXJSTag = origInXJSTag;
    +
    +    expect(_braceR);
    +
    +    return finishNode(node, "XJSExpressionContainer");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parses following JSX attribute name-value pair.

    + +
    + +
    +  function parseXJSAttribute() {
    +    var node = startNode();
    +
    +    node.name = parseXJSAttributeName();
    + +
  • + + +
  • +
    + +
    + +
    +

    HTML empty attribute

    + +
    + +
        if (tokVal === "=") {
    +      next();
    +      node.value = parseXJSAttributeValue();
    +    }
    +
    +    return finishNode(node, "XJSAttribute");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function parseXJSChild() {
    +    switch (tokType) {
    +      case _braceL:
    +        return parseXJSExpressionContainer();
    +
    +      case _xjsText:
    +        return parseExprAtom();
    +
    +      default:
    +        return parseXJSElement();
    +    }
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parses JSX open tag.

    + +
    + +
    +  function parseXJSOpeningElement() {
    +    var node = startNode(), attributes = node.attributes = [];
    +
    +    var origInXJSChild = inXJSChild;
    +    var origInXJSTag = inXJSTag;
    +    inXJSChild = false;
    +    inXJSTag = true;
    +
    +    expectChar('<');
    +
    +    node.name = parseXJSElementName();
    +
    +    while (tokType !== _eof && tokType !== _slash && tokVal !== '>') {
    +      attributes.push(parseXJSAttribute());
    +    }
    +
    +    inXJSTag = false;
    +
    +    if (node.selfClosing = !!eat(_slash)) {
    +      inXJSTag = origInXJSTag;
    +      inXJSChild = origInXJSChild;
    +    } else {
    +      inXJSChild = true;
    +    }
    +
    +    expectChar('>');
    +
    +    return finishNode(node, "XJSOpeningElement");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parses JSX closing tag.

    + +
    + +
    +  function parseXJSClosingElement() {
    +    var node = startNode();
    +    var origInXJSChild = inXJSChild;
    +    var origInXJSTag = inXJSTag;
    +    inXJSChild = false;
    +    inXJSTag = true;
    +    tokRegexpAllowed = false;
    +    expectChar('<');
    +    expect(_slash);
    +    node.name = parseXJSElementName();
    +    skipSpace();
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
        inXJSChild = origInXJSChild;
    +    inXJSTag = origInXJSTag;
    +    tokRegexpAllowed = false;
    +    expectChar('>');
    +    return finishNode(node, "XJSClosingElement");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function parseXJSElement() {
    +    var node = startNode();
    +    var children = [];
    +
    +    var origInXJSChild = inXJSChild;
    +    var openingElement = parseXJSOpeningElement();
    +
    +    if (!openingElement.selfClosing) {
    +      while (tokType !== _eof && !(tokVal === '<' && nextChar() === '/')) {
    +        inXJSChild = true;
    +        children.push(parseXJSChild());
    +      }
    +      inXJSChild = origInXJSChild;
    +      var closingElement = parseXJSClosingElement();
    +      if (getQualifiedXJSName(closingElement.name) !== getQualifiedXJSName(openingElement.name)) {
    +        raise(
    +          closingElement.start,
    +          "Expected corresponding XJS closing tag for '" + getQualifiedXJSName(openingElement.name) + "'"
    +        );
    +      }
    +    }
    + +
  • + + +
  • +
    + +
    + +
    +

    When (erroneously) writing two adjacent tags like

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

    the default error message is a bit incomprehensible. Since it’s +rarely (never?) useful to write a less-than sign after an XJS +element, we disallow it here in the parser in order to provide a +better error message. (In the rare case that the less-than operator +was intended, the left tag can be wrapped in parentheses.)

    + +
    + +
        if (!origInXJSChild && tokVal === '<') {
    +      raise(tokStart, "Adjacent XJS elements must be wrapped in an enclosing tag");
    +    }
    +
    +    node.openingElement = openingElement;
    +    node.closingElement = closingElement;
    +    node.children = children;
    +    return finishNode(node, "XJSElement");
    +  }
    +
    +});
    + +
  • + +
+
+ + diff --git a/docs/docco.css b/docs/docco.css new file mode 100644 index 0000000000..a2899ac878 --- /dev/null +++ b/docs/docco.css @@ -0,0 +1,506 @@ +/*--------------------- Typography ----------------------------*/ + +@font-face { + font-family: 'aller-light'; + src: url('public/fonts/aller-light.eot'); + src: url('public/fonts/aller-light.eot?#iefix') format('embedded-opentype'), + url('public/fonts/aller-light.woff') format('woff'), + url('public/fonts/aller-light.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'aller-bold'; + src: url('public/fonts/aller-bold.eot'); + src: url('public/fonts/aller-bold.eot?#iefix') format('embedded-opentype'), + url('public/fonts/aller-bold.woff') format('woff'), + url('public/fonts/aller-bold.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'novecento-bold'; + src: url('public/fonts/novecento-bold.eot'); + src: url('public/fonts/novecento-bold.eot?#iefix') format('embedded-opentype'), + url('public/fonts/novecento-bold.woff') format('woff'), + url('public/fonts/novecento-bold.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +/*--------------------- Layout ----------------------------*/ +html { height: 100%; } +body { + font-family: "aller-light"; + font-size: 14px; + line-height: 18px; + color: #30404f; + margin: 0; padding: 0; + height:100%; +} +#container { min-height: 100%; } + +a { + color: #000; +} + +b, strong { + font-weight: normal; + font-family: "aller-bold"; +} + +p { + margin: 15px 0 0px; +} + .annotation ul, .annotation ol { + margin: 25px 0; + } + .annotation ul li, .annotation ol li { + font-size: 14px; + line-height: 18px; + margin: 10px 0; + } + +h1, h2, h3, h4, h5, h6 { + color: #112233; + line-height: 1em; + font-weight: normal; + font-family: "novecento-bold"; + text-transform: uppercase; + margin: 30px 0 15px 0; +} + +h1 { + margin-top: 40px; +} + +hr { + border: 0; + background: 1px #ddd; + height: 1px; + margin: 20px 0; +} + +pre, tt, code { + font-size: 12px; line-height: 16px; + font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; + margin: 0; padding: 0; +} + .annotation pre { + display: block; + margin: 0; + padding: 7px 10px; + background: #fcfcfc; + -moz-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); + -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); + box-shadow: inset 0 0 10px rgba(0,0,0,0.1); + overflow-x: auto; + } + .annotation pre code { + border: 0; + padding: 0; + background: transparent; + } + + +blockquote { + border-left: 5px solid #ccc; + margin: 0; + padding: 1px 0 1px 1em; +} + .sections blockquote p { + font-family: Menlo, Consolas, Monaco, monospace; + font-size: 12px; line-height: 16px; + color: #999; + margin: 10px 0 0; + white-space: pre-wrap; + } + +ul.sections { + list-style: none; + padding:0 0 5px 0;; + margin:0; +} + +/* + Force border-box so that % widths fit the parent + container without overlap because of margin/padding. + + More Info : http://www.quirksmode.org/css/box.html +*/ +ul.sections > li > div { + -moz-box-sizing: border-box; /* firefox */ + -ms-box-sizing: border-box; /* ie */ + -webkit-box-sizing: border-box; /* webkit */ + -khtml-box-sizing: border-box; /* konqueror */ + box-sizing: border-box; /* css3 */ +} + + +/*---------------------- Jump Page -----------------------------*/ +#jump_to, #jump_page { + margin: 0; + background: white; + -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; + -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; + font: 16px Arial; + cursor: pointer; + text-align: right; + list-style: none; +} + +#jump_to a { + text-decoration: none; +} + +#jump_to a.large { + display: none; +} +#jump_to a.small { + font-size: 22px; + font-weight: bold; + color: #676767; +} + +#jump_to, #jump_wrapper { + position: fixed; + right: 0; top: 0; + padding: 10px 15px; + margin:0; +} + +#jump_wrapper { + display: none; + padding:0; +} + +#jump_to:hover #jump_wrapper { + display: block; +} + +#jump_page { + padding: 5px 0 3px; + margin: 0 0 25px 25px; +} + +#jump_page .source { + display: block; + padding: 15px; + text-decoration: none; + border-top: 1px solid #eee; +} + +#jump_page .source:hover { + background: #f5f5ff; +} + +#jump_page .source:first-child { +} + +/*---------------------- Low resolutions (> 320px) ---------------------*/ +@media only screen and (min-width: 320px) { + .pilwrap { display: none; } + + ul.sections > li > div { + display: block; + padding:5px 10px 0 10px; + } + + ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { + padding-left: 30px; + } + + ul.sections > li > div.content { + overflow-x:auto; + -webkit-box-shadow: inset 0 0 5px #e5e5ee; + box-shadow: inset 0 0 5px #e5e5ee; + border: 1px solid #dedede; + margin:5px 10px 5px 10px; + padding-bottom: 5px; + } + + ul.sections > li > div.annotation pre { + margin: 7px 0 7px; + padding-left: 15px; + } + + ul.sections > li > div.annotation p tt, .annotation code { + background: #f8f8ff; + border: 1px solid #dedede; + font-size: 12px; + padding: 0 0.2em; + } +} + +/*---------------------- (> 481px) ---------------------*/ +@media only screen and (min-width: 481px) { + #container { + position: relative; + } + body { + background-color: #F5F5FF; + font-size: 15px; + line-height: 21px; + } + pre, tt, code { + line-height: 18px; + } + p, ul, ol { + margin: 0 0 15px; + } + + + #jump_to { + padding: 5px 10px; + } + #jump_wrapper { + padding: 0; + } + #jump_to, #jump_page { + font: 10px Arial; + text-transform: uppercase; + } + #jump_page .source { + padding: 5px 10px; + } + #jump_to a.large { + display: inline-block; + } + #jump_to a.small { + display: none; + } + + + + #background { + position: absolute; + top: 0; bottom: 0; + width: 350px; + background: #fff; + border-right: 1px solid #e5e5ee; + z-index: -1; + } + + ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { + padding-left: 40px; + } + + ul.sections > li { + white-space: nowrap; + } + + ul.sections > li > div { + display: inline-block; + } + + ul.sections > li > div.annotation { + max-width: 350px; + min-width: 350px; + min-height: 5px; + padding: 13px; + overflow-x: hidden; + white-space: normal; + vertical-align: top; + text-align: left; + } + ul.sections > li > div.annotation pre { + margin: 15px 0 15px; + padding-left: 15px; + } + + ul.sections > li > div.content { + padding: 13px; + vertical-align: top; + border: none; + -webkit-box-shadow: none; + box-shadow: none; + } + + .pilwrap { + position: relative; + display: inline; + } + + .pilcrow { + font: 12px Arial; + text-decoration: none; + color: #454545; + position: absolute; + top: 3px; left: -20px; + padding: 1px 2px; + opacity: 0; + -webkit-transition: opacity 0.2s linear; + } + .for-h1 .pilcrow { + top: 47px; + } + .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow { + top: 35px; + } + + ul.sections > li > div.annotation:hover .pilcrow { + opacity: 1; + } +} + +/*---------------------- (> 1025px) ---------------------*/ +@media only screen and (min-width: 1025px) { + + body { + font-size: 16px; + line-height: 24px; + } + + #background { + width: 525px; + } + ul.sections > li > div.annotation { + max-width: 525px; + min-width: 525px; + padding: 10px 25px 1px 50px; + } + ul.sections > li > div.content { + padding: 9px 15px 16px 25px; + } +} + +/*---------------------- Syntax Highlighting -----------------------------*/ + +td.linenos { background-color: #f0f0f0; padding-right: 10px; } +span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } +/* + +github.com style (c) Vasily Polovnyov + +*/ + +pre code { + display: block; padding: 0.5em; + color: #000; + background: #f8f8ff +} + +pre .hljs-comment, +pre .hljs-template_comment, +pre .hljs-diff .hljs-header, +pre .hljs-javadoc { + color: #408080; + font-style: italic +} + +pre .hljs-keyword, +pre .hljs-assignment, +pre .hljs-literal, +pre .hljs-css .hljs-rule .hljs-keyword, +pre .hljs-winutils, +pre .hljs-javascript .hljs-title, +pre .hljs-lisp .hljs-title, +pre .hljs-subst { + color: #954121; + /*font-weight: bold*/ +} + +pre .hljs-number, +pre .hljs-hexcolor { + color: #40a070 +} + +pre .hljs-string, +pre .hljs-tag .hljs-value, +pre .hljs-phpdoc, +pre .hljs-tex .hljs-formula { + color: #219161; +} + +pre .hljs-title, +pre .hljs-id { + color: #19469D; +} +pre .hljs-params { + color: #00F; +} + +pre .hljs-javascript .hljs-title, +pre .hljs-lisp .hljs-title, +pre .hljs-subst { + font-weight: normal +} + +pre .hljs-class .hljs-title, +pre .hljs-haskell .hljs-label, +pre .hljs-tex .hljs-command { + color: #458; + font-weight: bold +} + +pre .hljs-tag, +pre .hljs-tag .hljs-title, +pre .hljs-rules .hljs-property, +pre .hljs-django .hljs-tag .hljs-keyword { + color: #000080; + font-weight: normal +} + +pre .hljs-attribute, +pre .hljs-variable, +pre .hljs-instancevar, +pre .hljs-lisp .hljs-body { + color: #008080 +} + +pre .hljs-regexp { + color: #B68 +} + +pre .hljs-class { + color: #458; + font-weight: bold +} + +pre .hljs-symbol, +pre .hljs-ruby .hljs-symbol .hljs-string, +pre .hljs-ruby .hljs-symbol .hljs-keyword, +pre .hljs-ruby .hljs-symbol .hljs-keymethods, +pre .hljs-lisp .hljs-keyword, +pre .hljs-tex .hljs-special, +pre .hljs-input_number { + color: #990073 +} + +pre .hljs-builtin, +pre .hljs-constructor, +pre .hljs-built_in, +pre .hljs-lisp .hljs-title { + color: #0086b3 +} + +pre .hljs-preprocessor, +pre .hljs-pi, +pre .hljs-doctype, +pre .hljs-shebang, +pre .hljs-cdata { + color: #999; + font-weight: bold +} + +pre .hljs-deletion { + background: #fdd +} + +pre .hljs-addition { + background: #dfd +} + +pre .hljs-diff .hljs-change { + background: #0086b3 +} + +pre .hljs-chunk { + color: #aaa +} + +pre .hljs-tex .hljs-formula { + opacity: 0.5; +} diff --git a/docs/public/fonts/aller-bold.eot b/docs/public/fonts/aller-bold.eot new file mode 100644 index 0000000000000000000000000000000000000000..1b32532a8e40e483069482c3650c3ef22ef16bdd GIT binary patch literal 29804 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 F>VRGqwvGS* literal 0 HcmV?d00001 diff --git a/docs/public/fonts/aller-bold.ttf b/docs/public/fonts/aller-bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c7034fb5cfa61ace4b29b5487c8a98e4c088afab GIT binary patch literal 66832 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 AKmY&$ literal 0 HcmV?d00001 diff --git a/docs/public/fonts/novecento-bold.woff b/docs/public/fonts/novecento-bold.woff new file mode 100644 index 0000000000000000000000000000000000000000..de558b5a29bcb4445be8ffd739c929bf4d3730af GIT binary patch literal 20576 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 F001ed(;ol; literal 0 HcmV?d00001 diff --git a/docs/public/stylesheets/normalize.css b/docs/public/stylesheets/normalize.css new file mode 100644 index 0000000000..73abb76fa4 --- /dev/null +++ b/docs/public/stylesheets/normalize.css @@ -0,0 +1,375 @@ +/*! normalize.css v2.0.1 | MIT License | git.io/normalize */ + +/* ========================================================================== + HTML5 display definitions + ========================================================================== */ + +/* + * Corrects `block` display not defined in IE 8/9. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section, +summary { + display: block; +} + +/* + * Corrects `inline-block` display not defined in IE 8/9. + */ + +audio, +canvas, +video { + display: inline-block; +} + +/* + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/* + * Addresses styling for `hidden` attribute not present in IE 8/9. + */ + +[hidden] { + display: none; +} + +/* ========================================================================== + Base + ========================================================================== */ + +/* + * 1. Sets default font family to sans-serif. + * 2. Prevents iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-family: sans-serif; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ + -ms-text-size-adjust: 100%; /* 2 */ +} + +/* + * Removes default margin. + */ + +body { + margin: 0; +} + +/* ========================================================================== + Links + ========================================================================== */ + +/* + * Addresses `outline` inconsistency between Chrome and other browsers. + */ + +a:focus { + outline: thin dotted; +} + +/* + * Improves readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* ========================================================================== + Typography + ========================================================================== */ + +/* + * Addresses `h1` font sizes within `section` and `article` in Firefox 4+, + * Safari 5, and Chrome. + */ + +h1 { + font-size: 2em; +} + +/* + * Addresses styling not present in IE 8/9, Safari 5, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/* + * Addresses style set to `bolder` in Firefox 4+, Safari 5, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +/* + * Addresses styling not present in Safari 5 and Chrome. + */ + +dfn { + font-style: italic; +} + +/* + * Addresses styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + + +/* + * Corrects font family set oddly in Safari 5 and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + font-size: 1em; +} + +/* + * Improves readability of pre-formatted text in all browsers. + */ + +pre { + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; +} + +/* + * Sets consistent quote types. + */ + +q { + quotes: "\201C" "\201D" "\2018" "\2019"; +} + +/* + * Addresses inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/* + * Prevents `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* ========================================================================== + Embedded content + ========================================================================== */ + +/* + * Removes border when inside `a` element in IE 8/9. + */ + +img { + border: 0; +} + +/* + * Corrects overflow displayed oddly in IE 9. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* ========================================================================== + Figures + ========================================================================== */ + +/* + * Addresses margin not present in IE 8/9 and Safari 5. + */ + +figure { + margin: 0; +} + +/* ========================================================================== + Forms + ========================================================================== */ + +/* + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/* + * 1. Corrects color not being inherited in IE 8/9. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ +} + +/* + * 1. Corrects font family not being inherited in all browsers. + * 2. Corrects font size not being inherited in all browsers. + * 3. Addresses margins set differently in Firefox 4+, Safari 5, and Chrome + */ + +button, +input, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 2 */ + margin: 0; /* 3 */ +} + +/* + * Addresses Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +button, +input { + line-height: normal; +} + +/* + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Corrects inability to style clickable `input` types in iOS. + * 3. Improves usability and consistency of cursor style between image-type + * `input` and others. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} + +/* + * Re-set default cursor for disabled elements. + */ + +button[disabled], +input[disabled] { + cursor: default; +} + +/* + * 1. Addresses box sizing set to `content-box` in IE 8/9. + * 2. Removes excess padding in IE 8/9. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/* + * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome. + * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/* + * Removes inner padding and search cancel button in Safari 5 and Chrome + * on OS X. + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* + * Removes inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/* + * 1. Removes default vertical scrollbar in IE 8/9. + * 2. Improves readability and alignment in all browsers. + */ + +textarea { + overflow: auto; /* 1 */ + vertical-align: top; /* 2 */ +} + +/* ========================================================================== + Tables + ========================================================================== */ + +/* + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} \ No newline at end of file diff --git a/index.html b/index.html deleted file mode 100644 index bfdc2e1c12..0000000000 --- a/index.html +++ /dev/null @@ -1,1967 +0,0 @@ - acorn.js

acorn.js

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

- -

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
-
- -

Please use the github bug tracker to report issues.

- -

This file defines the main parser interface. The library also comes -with a error-tolerant parser and an -abstract syntax tree walker, defined in other files.

(function(root, mod) {
-  if (typeof exports == "object" && typeof module == "object") return mod(exports); // CommonJS
-  if (typeof define == "function" && define.amd) return define(["exports"], mod); // AMD
-  mod(root.acorn || (root.acorn = {})); // Plain browser env
-})(this, function(exports) {
-  "use strict";
-
-  exports.version = "0.7.1";

The main exported interface (under self.acorn when in the -browser) is a parse function that takes a code string and -returns an abstract syntax tree as specified by Mozilla parser -API, with the caveat that inline XML is not recognized.

  var options, input, inputLen, sourceFile;
-
-  exports.parse = function(inpt, opts) {
-    input = String(inpt); inputLen = input.length;
-    setOptions(opts);
-    initTokenState();
-    return parseTopLevel(options.program);
-  };

A second optional argument can be given to further configure -the parser process. These options are recognized:

  var defaultOptions = exports.defaultOptions = {

ecmaVersion indicates the ECMAScript version to parse. Must -be either 3, or 5, or 6. This influences support for strict -mode, the set of reserved words, support for getters and -setters and other features.

    ecmaVersion: 5,

Turn on strictSemicolons to prevent the parser from doing -automatic semicolon insertion.

    strictSemicolons: false,

When allowTrailingCommas is false, the parser will not allow -trailing commas in array and object literals.

    allowTrailingCommas: true,

By default, reserved words are not enforced. Enable -forbidReserved to enforce them. When this option has the -value "everywhere", reserved words and keywords can also not be -used as property names.

    forbidReserved: false,

When enabled, a return at the top level is not considered an -error.

    allowReturnOutsideFunction: false,

When locations is on, loc properties holding objects with -start and end properties in {line, column} form (with -line being 1-based and column 0-based) will be attached to the -nodes.

    locations: false,

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 -boolean indicating whether this is a block (/* */) comment, -text is the content of the comment, and start and end are -character offsets that denote the start and end of the comment. -When the locations option is on, two more parameters are -passed, the full {line, column} locations of the start and -end of the comments. Note that you are not allowed to call the -parser from the callback—that will corrupt its internal state.

    onComment: null,

Nodes have their start and end characters offsets recorded in -start and end properties (directly on the node, rather than -the loc object, which holds line/column data. To also add a -semi-standardized range property holding a [start, -end] array with the same numbers, set the ranges option to -true.

    ranges: false,

It is possible to parse multiple files into a single AST by -passing the tree produced by parsing the first file as -program option in subsequent parses. This will add the -toplevel forms of the parsed file to the Program (top) node -of an existing parse tree.

    program: null,

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

    sourceFile: null,

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

    directSourceFile: null
-  };
-
-  function setOptions(opts) {
-    options = opts || {};
-    for (var opt in defaultOptions) if (!has(options, opt))
-      options[opt] = defaultOptions[opt];
-    sourceFile = options.sourceFile || null;
-
-    isKeyword = options.ecmaVersion >= 6 ? isEcma6Keyword : isEcma5AndLessKeyword;
-  }

The getLineInfo function is mostly useful when the -locations option is off (for performance reasons) and you -want to find the line/column position for a given character -offset. input should be the code string that the offset refers -into.

  var getLineInfo = exports.getLineInfo = function(input, offset) {
-    for (var line = 1, cur = 0;;) {
-      lineBreak.lastIndex = cur;
-      var match = lineBreak.exec(input);
-      if (match && match.index < offset) {
-        ++line;
-        cur = match.index + match[0].length;
-      } else break;
-    }
-    return {line: line, column: offset - cur};
-  };
-
-  var getCurrentToken = function () {
-    var token = {
-      type: tokType,
-      value: tokVal,
-      start: tokStart,
-      end: tokEnd
-    };
-    if (options.locations) {
-      token.startLoc = tokStartLoc;
-      token.endLoc = tokEndLoc;
-    }
-    return token;
-  };

Acorn is organized as a tokenizer and a recursive-descent parser. -The tokenize export provides an interface to the tokenizer. -Because the tokenizer is optimized for being efficiently used by -the Acorn parser itself, this interface is somewhat crude and not -very modular. Performing another parse or call to tokenize will -reset the internal state, and invalidate existing tokenizers.

  exports.tokenize = function(inpt, opts) {
-    input = String(inpt); inputLen = input.length;
-    setOptions(opts);
-    initTokenState();
-
-    function getToken(forceRegexp) {
-      lastEnd = tokEnd;
-      readToken(forceRegexp);
-      return getCurrentToken();
-    }
-    getToken.jumpTo = function(pos, reAllowed) {
-      tokPos = pos;
-      if (options.locations) {
-        tokCurLine = 1;
-        tokLineStart = lineBreak.lastIndex = 0;
-        var match;
-        while ((match = lineBreak.exec(input)) && match.index < pos) {
-          ++tokCurLine;
-          tokLineStart = match.index + match[0].length;
-        }
-      }
-      tokRegexpAllowed = reAllowed;
-      skipSpace();
-    };
-    return getToken;
-  };

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

The current position of the tokenizer in the input.

  var tokPos;

The start and end offsets of the current token.

  var tokStart, tokEnd;

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

  var tokStartLoc, tokEndLoc;

The type and value of the current token. Token types are objects, -named by variables against which they can be compared, and -holding properties that describe them (indicating, for example, -the precedence of an infix operator, and the original name of a -keyword token). The kind of value that's held in tokVal depends -on the type of the token. For literals, it is the literal value, -for operators, the operator name, and so on.

  var tokType, tokVal;

Internal state for the tokenizer. To distinguish between division -operators and regular expressions, it remembers whether the last -token was one that is allowed to be followed by an expression. -(If it is, a slash is probably a regexp, if it isn't it's a -division operator. See the parseStatement function for a -caveat.)

  var tokRegexpAllowed;

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

  var tokCurLine, tokLineStart;

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

  var lastStart, lastEnd, lastEndLoc;

This is the parser's state. inFunction is used to reject -return statements outside of functions, inGenerator to -reject yields outside of generators, labels to verify -that break and continue have somewhere to jump to, and -strict indicates whether strict mode is on.

  var inFunction, inGenerator, labels, strict;

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

  var metParenL;

This is used by parser for detecting if it's inside ES6 -Template String. If it is, it should treat '$' as prefix before -'{expression}' and everything else as string literals.

  var inTemplate;

This function is used to raise exceptions on parse errors. It -takes an offset integer (into the current input) to indicate -the location of the error, attaches the position to the end -of the error message, and then raises a SyntaxError with that -message.

  function raise(pos, message) {
-    var loc = getLineInfo(input, pos);
-    message += " (" + loc.line + ":" + loc.column + ")";
-    var err = new SyntaxError(message);
-    err.pos = pos; err.loc = loc; err.raisedAt = tokPos;
-    throw err;
-  }

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

  var empty = [];

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.

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

  var _num = {type: "num"}, _regexp = {type: "regexp"}, _string = {type: "string"};
-  var _name = {type: "name"}, _eof = {type: "eof"};

Keyword tokens. The keyword property (also used in keyword-like -operators) indicates that the token originated from an -identifier-like word, which is used when parsing property names.

- -

The beforeExpr property is used to disambiguate between regular -expressions and divisions. It is set on all token types that can -be followed by an expression (thus, a slash after them would be a -regular expression).

- -

isLoop marks a keyword as starting a loop, which is important -to know when parsing a label, in order to allow or disallow -continue jumps to that label.

  var _break = {keyword: "break"}, _case = {keyword: "case", beforeExpr: true}, _catch = {keyword: "catch"};
-  var _continue = {keyword: "continue"}, _debugger = {keyword: "debugger"}, _default = {keyword: "default"};
-  var _do = {keyword: "do", isLoop: true}, _else = {keyword: "else", beforeExpr: true};
-  var _finally = {keyword: "finally"}, _for = {keyword: "for", isLoop: true}, _function = {keyword: "function"};
-  var _if = {keyword: "if"}, _return = {keyword: "return", beforeExpr: true}, _switch = {keyword: "switch"};
-  var _throw = {keyword: "throw", beforeExpr: true}, _try = {keyword: "try"}, _var = {keyword: "var"};
-  var _let = {keyword: "let"}, _const = {keyword: "const"};
-  var _while = {keyword: "while", isLoop: true}, _with = {keyword: "with"}, _new = {keyword: "new", beforeExpr: true};
-  var _this = {keyword: "this"};
-  var _class = {keyword: "class"}, _extends = {keyword: "extends", beforeExpr: true};
-  var _export = {keyword: "export"}, _import = {keyword: "import"};
-  var _yield = {keyword: "yield", beforeExpr: true};

The keywords that denote values.

  var _null = {keyword: "null", atomValue: null}, _true = {keyword: "true", atomValue: true};
-  var _false = {keyword: "false", atomValue: false};

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

  var _in = {keyword: "in", binop: 7, beforeExpr: true};

Map keyword names to token types.

  var keywordTypes = {"break": _break, "case": _case, "catch": _catch,
-                      "continue": _continue, "debugger": _debugger, "default": _default,
-                      "do": _do, "else": _else, "finally": _finally, "for": _for,
-                      "function": _function, "if": _if, "return": _return, "switch": _switch,
-                      "throw": _throw, "try": _try, "var": _var, "let": _let, "const": _const,
-                      "while": _while, "with": _with,
-                      "null": _null, "true": _true, "false": _false, "new": _new, "in": _in,
-                      "instanceof": {keyword: "instanceof", binop: 7, beforeExpr: true}, "this": _this,
-                      "typeof": {keyword: "typeof", prefix: true, beforeExpr: true},
-                      "void": {keyword: "void", prefix: true, beforeExpr: true},
-                      "delete": {keyword: "delete", prefix: true, beforeExpr: true},
-                      "class": _class, "extends": _extends,
-                      "export": _export, "import": _import, "yield": _yield};

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

  var _bracketL = {type: "[", beforeExpr: true}, _bracketR = {type: "]"}, _braceL = {type: "{", beforeExpr: true};
-  var _braceR = {type: "}"}, _parenL = {type: "(", beforeExpr: true}, _parenR = {type: ")"};
-  var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true};
-  var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _ellipsis = {type: "..."}, _question = {type: "?", beforeExpr: true};
-  var _arrow = {type: "=>", beforeExpr: true}, _bquote = {type: "`"}, _dollarBraceL = {type: "${", beforeExpr: true};

Operators. These carry several kinds of properties to help the -parser use them properly (the presence of these properties is -what categorizes them as operators).

- -

binop, when present, specifies that this operator is a binary -operator, and will refer to its precedence.

- -

prefix and postfix mark the operator as a prefix or postfix -unary operator. isUpdate specifies that the node produced by -the operator should be of type UpdateExpression rather than -simply UnaryExpression (++ and --).

- -

isAssign marks all of =, +=, -= etcetera, which act as -binary operators with a very low precedence, that should result -in AssignmentExpression nodes.

  var _slash = {binop: 10, beforeExpr: true}, _eq = {isAssign: true, beforeExpr: true};
-  var _assign = {isAssign: true, beforeExpr: true};
-  var _incDec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true};
-  var _logicalOR = {binop: 1, beforeExpr: true};
-  var _logicalAND = {binop: 2, beforeExpr: true};
-  var _bitwiseOR = {binop: 3, beforeExpr: true};
-  var _bitwiseXOR = {binop: 4, beforeExpr: true};
-  var _bitwiseAND = {binop: 5, beforeExpr: true};
-  var _equality = {binop: 6, beforeExpr: true};
-  var _relational = {binop: 7, beforeExpr: true};
-  var _bitShift = {binop: 8, beforeExpr: true};
-  var _plusMin = {binop: 9, prefix: true, beforeExpr: true};
-  var _modulo = {binop: 10, beforeExpr: true};

'*' may be multiply or have special meaning in ES6

  var _star = {binop: 10, beforeExpr: true};

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

  exports.tokTypes = {bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR,
-                      parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon,
-                      dot: _dot, ellipsis: _ellipsis, question: _question, slash: _slash, eq: _eq,
-                      name: _name, eof: _eof, num: _num, regexp: _regexp, string: _string,
-                      arrow: _arrow, bquote: _bquote, dollarBraceL: _dollarBraceL};
-  for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw];

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 -predicate containing a big ugly switch statement is faster than -a regular expression, and on Chrome the two are about on par. -This function uses eval (non-lexical) to produce such a -predicate from a space-separated string of words.

- -

It starts by sorting the words by length.

  function makePredicate(words) {
-    words = words.split(" ");
-    var f = "", cats = [];
-    out: for (var i = 0; i < words.length; ++i) {
-      for (var j = 0; j < cats.length; ++j)
-        if (cats[j][0].length == words[i].length) {
-          cats[j].push(words[i]);
-          continue out;
-        }
-      cats.push([words[i]]);
-    }
-    function compareTo(arr) {
-      if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";";
-      f += "switch(str){";
-      for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":";
-      f += "return true}return false;";
-    }

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

    if (cats.length > 3) {
-      cats.sort(function(a, b) {return b.length - a.length;});
-      f += "switch(str.length){";
-      for (var i = 0; i < cats.length; ++i) {
-        var cat = cats[i];
-        f += "case " + cat[0].length + ":";
-        compareTo(cat);
-      }
-      f += "}";

Otherwise, simply generate a flat switch statement.

    } else {
-      compareTo(words);
-    }
-    return new Function("str", f);
-  }

The ECMAScript 3 reserved word list.

  var isReservedWord3 = makePredicate("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile");

ECMAScript 5 reserved words.

  var isReservedWord5 = makePredicate("class enum extends super const export import");

The additional reserved words in strict mode.

  var isStrictReservedWord = makePredicate("implements interface let package private protected public static yield");

The forbidden variable names in strict mode.

  var isStrictBadIdWord = makePredicate("eval arguments");

And the keywords.

  var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
-
-  var isEcma5AndLessKeyword = makePredicate(ecma5AndLessKeywords);
-
-  var isEcma6Keyword = makePredicate(ecma5AndLessKeywords + " let const class extends export import yield");
-
-  var isKeyword = isEcma5AndLessKeyword;

Character categories

Big ugly regular expressions that match characters in the -whitespace, identifier, and identifier-start categories. These -are only applied when a character is found to actually have a -code point above 128. -Generated by tools/generate-identifier-regex.js.

  var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
-  var nonASCIIidentifierStartChars = "\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC";
-  var nonASCIIidentifierChars = "\u0300-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u0669\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u06F0-\u06F9\u0711\u0730-\u074A\u07A6-\u07B0\u07C0-\u07C9\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E4-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0966-\u096F\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09E6-\u09EF\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A66-\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B66-\u0B6F\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0CE6-\u0CEF\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D66-\u0D6F\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0E50-\u0E59\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0ED0-\u0ED9\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1040-\u1049\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u18A9\u1920-\u192B\u1930-\u193B\u1946-\u194F\u19B0-\u19C0\u19C8\u19C9\u19D0-\u19D9\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AB0-\u1ABD\u1B00-\u1B04\u1B34-\u1B44\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BF3\u1C24-\u1C37\u1C40-\u1C49\u1C50-\u1C59\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u200C\u200D\u203F\u2040\u2054\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA620-\uA629\uA66F\uA674-\uA67D\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F1\uA900-\uA909\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9D0-\uA9D9\uA9E5\uA9F0-\uA9F9\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA50-\uAA59\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uABF0-\uABF9\uFB1E\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFF10-\uFF19\uFF3F";
-  var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
-  var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");

Whether a single character denotes a newline.

  var newline = /[\n\r\u2028\u2029]/;

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

  var lineBreak = /\r\n|[\n\r\u2028\u2029]/g;

Test whether a given character code starts an identifier.

  var isIdentifierStart = exports.isIdentifierStart = function(code) {
-    if (code < 65) return code === 36;
-    if (code < 91) return true;
-    if (code < 97) return code === 95;
-    if (code < 123)return true;
-    return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));
-  };

Test whether a given character is part of an identifier.

  var isIdentifierChar = exports.isIdentifierChar = function(code) {
-    if (code < 48) return code === 36;
-    if (code < 58) return true;
-    if (code < 65) return false;
-    if (code < 91) return true;
-    if (code < 97) return code === 95;
-    if (code < 123)return true;
-    return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));
-  };

Tokenizer

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

  function Position() {
-    this.line = tokCurLine;
-    this.column = tokPos - tokLineStart;
-  }

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

  function initTokenState() {
-    tokCurLine = 1;
-    tokPos = tokLineStart = 0;
-    tokRegexpAllowed = true;
-    metParenL = 0;
-    inTemplate = false;
-    skipSpace();
-  }

Called at the end of every token. Sets tokEnd, tokVal, and -tokRegexpAllowed, and skips the space after the token, so that -the next one's tokStart will point at the right position.

  function finishToken(type, val, shouldSkipSpace) {
-    tokEnd = tokPos;
-    if (options.locations) tokEndLoc = new Position;
-    tokType = type;
-    if (shouldSkipSpace !== false) skipSpace();
-    tokVal = val;
-    tokRegexpAllowed = type.beforeExpr;
-    if (options.onToken) {
-      options.onToken(getCurrentToken());
-    }
-  }
-
-  function skipBlockComment() {
-    var startLoc = options.onComment && options.locations && new Position;
-    var start = tokPos, end = input.indexOf("*/", tokPos += 2);
-    if (end === -1) raise(tokPos - 2, "Unterminated comment");
-    tokPos = end + 2;
-    if (options.locations) {
-      lineBreak.lastIndex = start;
-      var match;
-      while ((match = lineBreak.exec(input)) && match.index < tokPos) {
-        ++tokCurLine;
-        tokLineStart = match.index + match[0].length;
-      }
-    }
-    if (options.onComment)
-      options.onComment(true, input.slice(start + 2, end), start, tokPos,
-                        startLoc, options.locations && new Position);
-  }
-
-  function skipLineComment() {
-    var start = tokPos;
-    var startLoc = options.onComment && options.locations && new Position;
-    var ch = input.charCodeAt(tokPos+=2);
-    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,
-                        startLoc, options.locations && new Position);
-  }

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

  function skipSpace() {
-    while (tokPos < inputLen) {
-      var ch = input.charCodeAt(tokPos);
-      if (ch === 32) { // ' '
-        ++tokPos;
-      } else if (ch === 13) {
-        ++tokPos;
-        var next = input.charCodeAt(tokPos);
-        if (next === 10) {
-          ++tokPos;
-        }
-        if (options.locations) {
-          ++tokCurLine;
-          tokLineStart = tokPos;
-        }
-      } else if (ch === 10 || ch === 8232 || ch === 8233) {
-        ++tokPos;
-        if (options.locations) {
-          ++tokCurLine;
-          tokLineStart = tokPos;
-        }
-      } else if (ch > 8 && ch < 14) {
-        ++tokPos;
-      } else if (ch === 47) { // '/'
-        var next = input.charCodeAt(tokPos + 1);
-        if (next === 42) { // '*'
-          skipBlockComment();
-        } else if (next === 47) { // '/'
-          skipLineComment();
-        } else break;
-      } else if (ch === 160) { // '\xa0'
-        ++tokPos;
-      } else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
-        ++tokPos;
-      } else {
-        break;
-      }
-    }
-  }

Token reading

This is the function that is called to fetch the next token. It -is somewhat obscure, because it works in character codes rather -than characters, and because operator parsing has been inlined -into it.

- -

All in the name of speed.

- -

The forceRegexp parameter is used in the one case where the -tokRegexpAllowed trick does not work. See parseStatement.

  function readToken_dot() {
-    var next = input.charCodeAt(tokPos + 1);
-    if (next >= 48 && next <= 57) return readNumber(true);
-    var next2 = input.charCodeAt(tokPos + 2);
-    if (options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
-      tokPos += 3;
-      return finishToken(_ellipsis);
-    } else {
-      ++tokPos;
-      return finishToken(_dot);
-    }
-  }
-
-  function readToken_slash() { // '/'
-    var next = input.charCodeAt(tokPos + 1);
-    if (tokRegexpAllowed) {++tokPos; return readRegexp();}
-    if (next === 61) return finishOp(_assign, 2);
-    return finishOp(_slash, 1);
-  }
-
-  function readToken_mult_modulo(code) { // '%*'
-    var next = input.charCodeAt(tokPos + 1);
-    if (next === 61) return finishOp(_assign, 2);
-    return finishOp(code === 42 ? _star : _modulo, 1);
-  }
-
-  function readToken_pipe_amp(code) { // '|&'
-    var next = input.charCodeAt(tokPos + 1);
-    if (next === code) return finishOp(code === 124 ? _logicalOR : _logicalAND, 2);
-    if (next === 61) return finishOp(_assign, 2);
-    return finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1);
-  }
-
-  function readToken_caret() { // '^'
-    var next = input.charCodeAt(tokPos + 1);
-    if (next === 61) return finishOp(_assign, 2);
-    return finishOp(_bitwiseXOR, 1);
-  }
-
-  function readToken_plus_min(code) { // '+-'
-    var next = input.charCodeAt(tokPos + 1);
-    if (next === code) {
-      if (next == 45 && input.charCodeAt(tokPos + 2) == 62 &&
-          newline.test(input.slice(lastEnd, tokPos))) {

A --> line comment

        tokPos += 3;
-        skipLineComment();
-        skipSpace();
-        return readToken();
-      }
-      return finishOp(_incDec, 2);
-    }
-    if (next === 61) return finishOp(_assign, 2);
-    return finishOp(_plusMin, 1);
-  }
-
-  function readToken_lt_gt(code) { // '<>'
-    var next = input.charCodeAt(tokPos + 1);
-    var size = 1;
-    if (next === code) {
-      size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2;
-      if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1);
-      return finishOp(_bitShift, size);
-    }
-    if (next == 33 && code == 60 && input.charCodeAt(tokPos + 2) == 45 &&
-        input.charCodeAt(tokPos + 3) == 45) {

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

      tokPos += 4;
-      skipLineComment();
-      skipSpace();
-      return readToken();
-    }
-    if (next === 61)
-      size = input.charCodeAt(tokPos + 2) === 61 ? 3 : 2;
-    return finishOp(_relational, size);
-  }
-
-  function readToken_eq_excl(code) { // '=!', '=>'
-    var next = input.charCodeAt(tokPos + 1);
-    if (next === 61) return finishOp(_equality, input.charCodeAt(tokPos + 2) === 61 ? 3 : 2);
-    if (code === 61 && next === 62 && options.ecmaVersion >= 6) { // '=>'
-      tokPos += 2;
-      return finishToken(_arrow);
-    }
-    return finishOp(code === 61 ? _eq : _prefix, 1);
-  }

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

  function getTemplateToken(code) {

'`' 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.

    case 46: // '.'
-      return readToken_dot();

Punctuation tokens.

    case 40: ++tokPos; return finishToken(_parenL);
-    case 41: ++tokPos; return finishToken(_parenR);
-    case 59: ++tokPos; return finishToken(_semi);
-    case 44: ++tokPos; return finishToken(_comma);
-    case 91: ++tokPos; return finishToken(_bracketL);
-    case 93: ++tokPos; return finishToken(_bracketR);
-    case 123: ++tokPos; return finishToken(_braceL);
-    case 125: ++tokPos; return finishToken(_braceR);
-    case 58: ++tokPos; return finishToken(_colon);
-    case 63: ++tokPos; return finishToken(_question);
-
-    case 96: // '`'
-      if (options.ecmaVersion >= 6) {
-        ++tokPos;
-        return finishToken(_bquote, undefined, false);
-      }
-
-    case 48: // '0'
-      var next = input.charCodeAt(tokPos + 1);
-      if (next === 120 || next === 88) return readRadixNumber(16); // '0x', '0X' - hex number
-      if (options.ecmaVersion >= 6) {
-        if (next === 111 || next === 79) return readRadixNumber(8); // '0o', '0O' - octal number
-        if (next === 98 || next === 66) return readRadixNumber(2); // '0b', '0B' - binary number
-      }

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

    case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
-      return readNumber(false);

Quotes produce strings.

    case 34: case 39: // '"', "'"
-      return readString(code);

Operators are parsed inline in tiny state machines. '=' (61) is -often referred to. finishOp simply skips the amount of -characters it is given as second argument, and returns a token -of the type given by its first argument.

    case 47: // '/'
-      return readToken_slash();
-
-    case 37: case 42: // '%*'
-      return readToken_mult_modulo(code);
-
-    case 124: case 38: // '|&'
-      return readToken_pipe_amp(code);
-
-    case 94: // '^'
-      return readToken_caret();
-
-    case 43: case 45: // '+-'
-      return readToken_plus_min(code);
-
-    case 60: case 62: // '<>'
-      return readToken_lt_gt(code);
-
-    case 61: case 33: // '=!'
-      return readToken_eq_excl(code);
-
-    case 126: // '~'
-      return finishOp(_prefix, 1);
-    }
-
-    return false;
-  }
-
-  function readToken(forceRegexp) {
-    if (!forceRegexp) tokStart = tokPos;
-    else tokPos = tokStart + 1;
-    if (options.locations) tokStartLoc = new Position;
-    if (forceRegexp) return readRegexp();
-    if (tokPos >= inputLen) return finishToken(_eof);
-
-    var code = input.charCodeAt(tokPos);
-
-    if (inTemplate) return getTemplateToken(code);

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

    if (isIdentifierStart(code) || code === 92 /* '\' */) return readWord();
-
-    var tok = getTokenFromCode(code);
-
-    if (tok === false) {

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

      var ch = String.fromCharCode(code);
-      if (ch === "\\" || nonASCIIidentifierStart.test(ch)) return readWord();
-      raise(tokPos, "Unexpected character '" + ch + "'");
-    }
-    return tok;
-  }
-
-  function finishOp(type, size) {
-    var str = input.slice(tokPos, tokPos + size);
-    tokPos += size;
-    finishToken(type, str);
-  }

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

  function readRegexp() {
-    var content = "", escaped, inClass, start = tokPos;
-    for (;;) {
-      if (tokPos >= inputLen) raise(start, "Unterminated regular expression");
-      var ch = input.charAt(tokPos);
-      if (newline.test(ch)) raise(start, "Unterminated regular expression");
-      if (!escaped) {
-        if (ch === "[") inClass = true;
-        else if (ch === "]" && inClass) inClass = false;
-        else if (ch === "/" && !inClass) break;
-        escaped = ch === "\\";
-      } else escaped = false;
-      ++tokPos;
-    }
-    var content = input.slice(start, tokPos);
-    ++tokPos;

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

    var mods = readWord1();
-    if (mods && !/^[gmsiy]*$/.test(mods)) raise(start, "Invalid regular expression flag");
-    try {
-      var value = new RegExp(content, mods);
-    } catch (e) {
-      if (e instanceof SyntaxError) raise(start, "Error parsing regular expression: " + e.message);
-      raise(e);
-    }
-    return finishToken(_regexp, value);
-  }

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

  function readInt(radix, len) {
-    var start = tokPos, total = 0;
-    for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {
-      var code = input.charCodeAt(tokPos), val;
-      if (code >= 97) val = code - 97 + 10; // a
-      else if (code >= 65) val = code - 65 + 10; // A
-      else if (code >= 48 && code <= 57) val = code - 48; // 0-9
-      else val = Infinity;
-      if (val >= radix) break;
-      ++tokPos;
-      total = total * radix + val;
-    }
-    if (tokPos === start || len != null && tokPos - start !== len) return null;
-
-    return total;
-  }
-
-  function readRadixNumber(radix) {
-    tokPos += 2; // 0x
-    var val = readInt(radix);
-    if (val == null) raise(tokStart + 2, "Expected number in radix " + radix);
-    if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number");
-    return finishToken(_num, val);
-  }

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

  function readNumber(startsWithDot) {
-    var start = tokPos, isFloat = false, octal = input.charCodeAt(tokPos) === 48;
-    if (!startsWithDot && readInt(10) === null) raise(start, "Invalid number");
-    if (input.charCodeAt(tokPos) === 46) {
-      ++tokPos;
-      readInt(10);
-      isFloat = true;
-    }
-    var next = input.charCodeAt(tokPos);
-    if (next === 69 || next === 101) { // 'eE'
-      next = input.charCodeAt(++tokPos);
-      if (next === 43 || next === 45) ++tokPos; // '+-'
-      if (readInt(10) === null) raise(start, "Invalid number");
-      isFloat = true;
-    }
-    if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number");
-
-    var str = input.slice(start, tokPos), val;
-    if (isFloat) val = parseFloat(str);
-    else if (!octal || str.length === 1) val = parseInt(str, 10);
-    else if (/[89]/.test(str) || strict) raise(start, "Invalid number");
-    else val = parseInt(str, 8);
-    return finishToken(_num, val);
-  }

Read a string value, interpreting backslash-escapes.

  function readCodePoint() {
-    var ch = input.charCodeAt(tokPos), code;
-
-    if (ch === 123) {
-      if (options.ecmaVersion < 6) unexpected();
-      ++tokPos;
-      code = readHexChar(input.indexOf('}', tokPos) - tokPos);
-      ++tokPos;
-      if (code > 0x10FFFF) unexpected();
-    } else {
-      code = readHexChar(4);
-    }

UTF-16 Encoding

    if (code <= 0xFFFF) {
-      return String.fromCharCode(code);
-    }
-    var cu1 = ((code - 0x10000) >> 10) + 0xD800;
-    var cu2 = ((code - 0x10000) & 1023) + 0xDC00;
-    return String.fromCharCode(cu1, cu2);
-  }
-
-  function readString(quote) {
-    ++tokPos;
-    var out = "";
-    for (;;) {
-      if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant");
-      var ch = input.charCodeAt(tokPos);
-      if (ch === quote) {
-        ++tokPos;
-        return finishToken(_string, out);
-      }
-      if (ch === 92) { // '\'
-        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 (ch === 13 && input.charCodeAt(tokPos) === 10) {
-            ++tokPos;
-            ch = 10;
-          }
-          if (options.locations) {
-            ++tokCurLine;
-            tokLineStart = tokPos;
-          }
-        }
-        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);
-      }
-    }
-  }

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

  function readHexChar(len) {
-    var n = readInt(16, len);
-    if (n === null) raise(tokStart, "Bad character escape sequence");
-    return n;
-  }

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

  var containsEsc;

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

- -

Only builds up the word character-by-character when it actually -containeds an escape, as a micro-optimization.

  function readWord1() {
-    containsEsc = false;
-    var word, first = true, start = tokPos;
-    for (;;) {
-      var ch = input.charCodeAt(tokPos);
-      if (isIdentifierChar(ch)) {
-        if (containsEsc) word += input.charAt(tokPos);
-        ++tokPos;
-      } else if (ch === 92) { // "\"
-        if (!containsEsc) word = input.slice(start, tokPos);
-        containsEsc = true;
-        if (input.charCodeAt(++tokPos) != 117) // "u"
-          raise(tokPos, "Expecting Unicode escape sequence \\uXXXX");
-        ++tokPos;
-        var esc = readHexChar(4);
-        var escStr = String.fromCharCode(esc);
-        if (!escStr) raise(tokPos - 1, "Invalid Unicode escape");
-        if (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc)))
-          raise(tokPos - 4, "Invalid Unicode escape");
-        word += escStr;
-      } else {
-        break;
-      }
-      first = false;
-    }
-    return containsEsc ? word : input.slice(start, tokPos);
-  }

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

  function readWord() {
-    var word = readWord1();
-    var type = _name;
-    if (!containsEsc && isKeyword(word))
-      type = keywordTypes[word];
-    return finishToken(type, word);
-  }

Parser

A recursive descent parser operates by defining functions for all -syntactic elements, and recursively calling those, each function -advancing the input stream and returning an AST node. Precedence -of constructs (for example, the fact that !x[1] means !(x[1]) -instead of (!x)[1] is handled by the fact that the parser -function that parses unary prefix operators is called first, and -in turn calls the function that parses [] subscripts — that -way, it'll receive the node for x[1] already parsed, and wraps -that in the unary operator node.

- -

Acorn uses an operator precedence parser to handle binary -operator precedence, because it is much more compact than using -the technique outlined above, which uses different, nesting -functions to specify precedence, for all of the ten binary -precedence levels that JavaScript defines.

Parser utilities

Continue to the next token.

  function next() {
-    lastStart = tokStart;
-    lastEnd = tokEnd;
-    lastEndLoc = tokEndLoc;
-    readToken();
-  }

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

  function setStrict(strct) {
-    strict = strct;
-    tokPos = tokStart;
-    if (options.locations) {
-      while (tokPos < tokLineStart) {
-        tokLineStart = input.lastIndexOf("\n", tokLineStart - 2) + 1;
-        --tokCurLine;
-      }
-    }
-    skipSpace();
-    readToken();
-  }

Start an AST node, attaching a start offset.

  function Node() {
-    this.type = null;
-    this.start = tokStart;
-    this.end = null;
-  }
-
-  exports.Node = Node;
-
-  function SourceLocation() {
-    this.start = tokStartLoc;
-    this.end = null;
-    if (sourceFile !== null) this.source = sourceFile;
-  }
-
-  function startNode() {
-    var node = new Node();
-    if (options.locations)
-      node.loc = new SourceLocation();
-    if (options.directSourceFile)
-      node.sourceFile = options.directSourceFile;
-    if (options.ranges)
-      node.range = [tokStart, 0];
-    return node;
-  }

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

  function startNodeFrom(other) {
-    var node = new Node();
-    node.start = other.start;
-    if (options.locations) {
-      node.loc = new SourceLocation();
-      node.loc.start = other.loc.start;
-    }
-    if (options.ranges)
-      node.range = [other.range[0], 0];
-
-    return node;
-  }

Finish an AST node, adding type and end properties.

  function finishNode(node, type) {
-    node.type = type;
-    node.end = lastEnd;
-    if (options.locations)
-      node.loc.end = lastEndLoc;
-    if (options.ranges)
-      node.range[1] = lastEnd;
-    return node;
-  }

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

  function isUseStrict(stmt) {
-    return options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" &&
-      stmt.expression.type === "Literal" && stmt.expression.value === "use strict";
-  }

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

  function eat(type) {
-    if (tokType === type) {
-      next();
-      return true;
-    } else {
-      return false;
-    }
-  }

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

  function canInsertSemicolon() {
-    return !options.strictSemicolons &&
-      (tokType === _eof || tokType === _braceR || newline.test(input.slice(lastEnd, tokStart)));
-  }

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

  function semicolon() {
-    if (!eat(_semi) && !canInsertSemicolon()) unexpected();
-  }

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

  function expect(type) {
-    eat(type) || unexpected();
-  }

Raise an unexpected token error.

  function unexpected(pos) {
-    raise(pos != null ? pos : tokStart, "Unexpected token");
-  }

Checks if hash object has a property.

  function has(obj, propName) {
-    return Object.prototype.hasOwnProperty.call(obj, propName);
-  }

Convert existing expression atom to assignable pattern -if possible.

  function toAssignable(node, allowSpread, checkType) {
-    if (options.ecmaVersion >= 6 && node) {
-      switch (node.type) {
-        case "Identifier":
-        case "MemberExpression":
-          break;
-
-        case "ObjectExpression":
-          node.type = "ObjectPattern";
-          for (var i = 0; i < node.properties.length; i++) {
-            var prop = node.properties[i];
-            if (prop.kind !== "init") unexpected(prop.key.start);
-            toAssignable(prop.value, false, checkType);
-          }
-          break;
-
-        case "ArrayExpression":
-          node.type = "ArrayPattern";
-          for (var i = 0, lastI = node.elements.length - 1; i <= lastI; i++) {
-            toAssignable(node.elements[i], i === lastI, checkType);
-          }
-          break;
-
-        case "SpreadElement":
-          if (allowSpread) {
-            toAssignable(node.argument, false, checkType);
-            checkSpreadAssign(node.argument);
-          } else {
-            unexpected(node.start);
-          }
-          break;
-
-        default:
-          if (checkType) unexpected(node.start);
-      }
-    }
-    return node;
-  }

Checks if node can be assignable spread argument.

  function checkSpreadAssign(node) {
-    if (node.type !== "Identifier" && node.type !== "ArrayPattern")
-      unexpected(node.start);
-  }

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

  function checkFunctionParam(param, nameHash) {
-    switch (param.type) {
-      case "Identifier":
-        if (isStrictReservedWord(param.name) || isStrictBadIdWord(param.name))
-          raise(param.start, "Defining '" + param.name + "' in strict mode");
-        if (has(nameHash, param.name))
-          raise(param.start, "Argument name clash in strict mode");
-        nameHash[param.name] = true;
-        break;
-
-      case "ObjectPattern":
-        for (var i = 0; i < param.properties.length; i++)
-          checkFunctionParam(param.properties[i].value, nameHash);
-        break;
-
-      case "ArrayPattern":
-        for (var i = 0; i < param.elements.length; i++)
-          checkFunctionParam(param.elements[i], nameHash);
-        break;
-    }
-  }

Check if property name clashes with already added. -Object/class getters and setters are not allowed to clash — -either with each other or with an init property — and in -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;
-    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] = {
-        init: false,
-        get: false,
-        set: false
-      };
-    }
-    other[kind] = true;
-  }

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

  function checkLVal(expr, isBinding) {
-    switch (expr.type) {
-      case "Identifier":
-        if (strict && (isStrictBadIdWord(expr.name) || isStrictReservedWord(expr.name)))
-          raise(expr.start, isBinding
-            ? "Binding " + expr.name + " in strict mode"
-            : "Assigning to " + expr.name + " in strict mode"
-          );
-        break;
-
-      case "MemberExpression":
-        if (!isBinding) break;
-
-      case "ObjectPattern":
-        for (var i = 0; i < expr.properties.length; i++)
-          checkLVal(expr.properties[i].value, isBinding);
-        break;
-
-      case "ArrayPattern":
-        for (var i = 0; i < expr.elements.length; i++) {
-          var elem = expr.elements[i];
-          if (elem) checkLVal(elem, isBinding);
-        }
-        break;
-
-      case "SpreadElement":
-        break;
-
-      default:
-        raise(expr.start, "Assigning to rvalue");
-    }
-  }

Statement parsing

Parse a program. Initializes the parser, reads any number of -statements, and wraps them in a Program node. Optionally takes a -program argument. If present, the statements will be appended -to its body instead of creating a new node.

  function parseTopLevel(program) {
-    lastStart = lastEnd = tokPos;
-    if (options.locations) lastEndLoc = new Position;
-    inFunction = inGenerator = strict = null;
-    labels = [];
-    readToken();
-
-    var node = program || startNode(), first = true;
-    if (!program) node.body = [];
-    while (tokType !== _eof) {
-      var stmt = parseStatement();
-      node.body.push(stmt);
-      if (first && isUseStrict(stmt)) setStrict(true);
-      first = false;
-    }
-    return finishNode(node, "Program");
-  }
-
-  var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"};

Parse a single statement.

- -

If expecting a statement and finding a slash operator, parse a -regular expression literal. This is to handle cases like -if (foo) /blah/.exec(foo);, where looking at the previous token -does not help.

  function parseStatement() {
-    if (tokType === _slash || tokType === _assign && tokVal == "/=")
-      readToken(true);
-
-    var starttype = tokType, node = startNode();

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

    switch (starttype) {
-    case _break: case _continue: return parseBreakContinueStatement(node, starttype.keyword);
-    case _debugger: return parseDebuggerStatement(node);
-    case _do: return parseDoStatement(node);
-    case _for: return parseForStatement(node);
-    case _function: return parseFunctionStatement(node);
-    case _class: return parseClass(node, true);
-    case _if: return parseIfStatement(node);
-    case _return: return parseReturnStatement(node);
-    case _switch: return parseSwitchStatement(node);
-    case _throw: return parseThrowStatement(node);
-    case _try: return parseTryStatement(node);
-    case _var: case _let: case _const: return parseVarStatement(node, starttype.keyword);
-    case _while: return parseWhileStatement(node);
-    case _with: return parseWithStatement(node);
-    case _braceL: return parseBlock(); // no point creating a function for this
-    case _semi: return parseEmptyStatement(node);
-    case _export: return parseExport(node);
-    case _import: return parseImport(node);

If the statement does not start with a statement keyword or a -brace, it's an ExpressionStatement or LabeledStatement. We -simply start parsing an expression, and afterwards, if the -next token is a colon and the expression was a simple -Identifier node, we switch to interpreting it as a label.

    default:
-      var maybeName = tokVal, expr = parseExpression();
-      if (starttype === _name && expr.type === "Identifier" && eat(_colon))
-        return parseLabeledStatement(node, maybeName, expr);
-      else return parseExpressionStatement(node, expr);
-    }
-  }
-
-  function parseBreakContinueStatement(node, keyword) {
-    var isBreak = keyword == "break";
-    next();
-    if (eat(_semi) || canInsertSemicolon()) node.label = null;
-    else if (tokType !== _name) unexpected();
-    else {
-      node.label = parseIdent();
-      semicolon();
-    }

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

    for (var i = 0; i < labels.length; ++i) {
-      var lab = labels[i];
-      if (node.label == null || lab.name === node.label.name) {
-        if (lab.kind != null && (isBreak || lab.kind === "loop")) break;
-        if (node.label && isBreak) break;
-      }
-    }
-    if (i === labels.length) raise(node.start, "Unsyntactic " + keyword);
-    return finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement");
-  }
-
-  function parseDebuggerStatement(node) {
-    next();
-    semicolon();
-    return finishNode(node, "DebuggerStatement");
-  }
-
-  function parseDoStatement(node) {
-    next();
-    labels.push(loopLabel);
-    node.body = parseStatement();
-    labels.pop();
-    expect(_while);
-    node.test = parseParenExpression();
-    semicolon();
-    return finishNode(node, "DoWhileStatement");
-  }

Disambiguating between a for and a for/in or for/of -loop is non-trivial. Basically, we have to parse the init var -statement or expression, disallowing the in operator (see -the second parameter to parseExpression), and then check -whether the next token is in or of. When there is no init -part (semicolon immediately after the opening parenthesis), it -is a regular for loop.

  function parseForStatement(node) {
-    next();
-    labels.push(loopLabel);
-    expect(_parenL);
-    if (tokType === _semi) return parseFor(node, null);
-    if (tokType === _var || tokType === _let) {
-      var init = startNode(), varKind = tokType.keyword, isLet = tokType === _let;
-      next();
-      parseVar(init, true, varKind);
-      finishNode(init, "VariableDeclaration");
-      if ((tokType === _in || (tokType === _name && tokVal === "of")) && init.declarations.length === 1 &&
-          !(isLet && init.declarations[0].init))
-        return parseForIn(node, init);
-      return parseFor(node, init);
-    }
-    var init = parseExpression(false, true);
-    if (tokType === _in || (tokType === _name && tokVal === "of")) {
-      checkLVal(init);
-      return parseForIn(node, init);
-    }
-    return parseFor(node, init);
-  }
-
-  function parseFunctionStatement(node) {
-    next();
-    return parseFunction(node, true);
-  }
-
-  function parseIfStatement(node) {
-    next();
-    node.test = parseParenExpression();
-    node.consequent = parseStatement();
-    node.alternate = eat(_else) ? parseStatement() : null;
-    return finishNode(node, "IfStatement");
-  }
-
-  function parseReturnStatement(node) {
-    if (!inFunction && !options.allowReturnOutsideFunction)
-      raise(tokStart, "'return' outside of function");
-    next();

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

    if (eat(_semi) || canInsertSemicolon()) node.argument = null;
-    else { node.argument = parseExpression(); semicolon(); }
-    return finishNode(node, "ReturnStatement");
-  }
-
-  function parseSwitchStatement(node) {
-    next();
-    node.discriminant = parseParenExpression();
-    node.cases = [];
-    expect(_braceL);
-    labels.push(switchLabel);

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

    for (var cur, sawDefault; tokType != _braceR;) {
-      if (tokType === _case || tokType === _default) {
-        var isCase = tokType === _case;
-        if (cur) finishNode(cur, "SwitchCase");
-        node.cases.push(cur = startNode());
-        cur.consequent = [];
-        next();
-        if (isCase) cur.test = parseExpression();
-        else {
-          if (sawDefault) raise(lastStart, "Multiple default clauses"); sawDefault = true;
-          cur.test = null;
-        }
-        expect(_colon);
-      } else {
-        if (!cur) unexpected();
-        cur.consequent.push(parseStatement());
-      }
-    }
-    if (cur) finishNode(cur, "SwitchCase");
-    next(); // Closing brace
-    labels.pop();
-    return finishNode(node, "SwitchStatement");
-  }
-
-  function parseThrowStatement(node) {
-    next();
-    if (newline.test(input.slice(lastEnd, tokStart)))
-      raise(lastEnd, "Illegal newline after throw");
-    node.argument = parseExpression();
-    semicolon();
-    return finishNode(node, "ThrowStatement");
-  }
-
-  function parseTryStatement(node) {
-    next();
-    node.block = parseBlock();
-    node.handler = null;
-    if (tokType === _catch) {
-      var clause = startNode();
-      next();
-      expect(_parenL);
-      clause.param = parseIdent();
-      if (strict && isStrictBadIdWord(clause.param.name))
-        raise(clause.param.start, "Binding " + clause.param.name + " in strict mode");
-      expect(_parenR);
-      clause.guard = null;
-      clause.body = parseBlock();
-      node.handler = finishNode(clause, "CatchClause");
-    }
-    node.guardedHandlers = empty;
-    node.finalizer = eat(_finally) ? parseBlock() : null;
-    if (!node.handler && !node.finalizer)
-      raise(node.start, "Missing catch or finally clause");
-    return finishNode(node, "TryStatement");
-  }
-
-  function parseVarStatement(node, kind) {
-    next();
-    parseVar(node, false, kind);
-    semicolon();
-    return finishNode(node, "VariableDeclaration");
-  }
-
-  function parseWhileStatement(node) {
-    next();
-    node.test = parseParenExpression();
-    labels.push(loopLabel);
-    node.body = parseStatement();
-    labels.pop();
-    return finishNode(node, "WhileStatement");
-  }
-
-  function parseWithStatement(node) {
-    if (strict) raise(tokStart, "'with' in strict mode");
-    next();
-    node.object = parseParenExpression();
-    node.body = parseStatement();
-    return finishNode(node, "WithStatement");
-  }
-
-  function parseEmptyStatement(node) {
-    next();
-    return finishNode(node, "EmptyStatement");
-  }
-
-  function parseLabeledStatement(node, maybeName, expr) {
-    for (var i = 0; i < labels.length; ++i)
-      if (labels[i].name === maybeName) raise(expr.start, "Label '" + maybeName + "' is already declared");
-    var kind = tokType.isLoop ? "loop" : tokType === _switch ? "switch" : null;
-    labels.push({name: maybeName, kind: kind});
-    node.body = parseStatement();
-    labels.pop();
-    node.label = expr;
-    return finishNode(node, "LabeledStatement");
-  }
-
-  function parseExpressionStatement(node, expr) {
-    node.expression = expr;
-    semicolon();
-    return finishNode(node, "ExpressionStatement");
-  }

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

  function parseParenExpression() {
-    expect(_parenL);
-    var val = parseExpression();
-    expect(_parenR);
-    return val;
-  }

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

  function parseBlock(allowStrict) {
-    var node = startNode(), first = true, strict = false, oldStrict;
-    node.body = [];
-    expect(_braceL);
-    while (!eat(_braceR)) {
-      var stmt = parseStatement();
-      node.body.push(stmt);
-      if (first && allowStrict && isUseStrict(stmt)) {
-        oldStrict = strict;
-        setStrict(strict = true);
-      }
-      first = false;
-    }
-    if (strict && !oldStrict) setStrict(false);
-    return finishNode(node, "BlockStatement");
-  }

Parse a regular for loop. The disambiguation code in -parseStatement will already have parsed the init statement or -expression.

  function parseFor(node, init) {
-    node.init = init;
-    expect(_semi);
-    node.test = tokType === _semi ? null : parseExpression();
-    expect(_semi);
-    node.update = tokType === _parenR ? null : parseExpression();
-    expect(_parenR);
-    node.body = parseStatement();
-    labels.pop();
-    return finishNode(node, "ForStatement");
-  }

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

  function parseForIn(node, init) {
-    var type = tokType === _in ? "ForInStatement" : "ForOfStatement";
-    next();
-    node.left = init;
-    node.right = parseExpression();
-    expect(_parenR);
-    node.body = parseStatement();
-    labels.pop();
-    return finishNode(node, type);
-  }

Parse a list of variable declarations.

  function parseVar(node, noIn, kind) {
-    node.declarations = [];
-    node.kind = kind;
-    for (;;) {
-      var decl = startNode();
-      decl.id = options.ecmaVersion >= 6 ? toAssignable(parseExprAtom()) : parseIdent();
-      checkLVal(decl.id, true);
-      decl.init = eat(_eq) ? parseExpression(true, noIn) : (kind === _const.keyword ? unexpected() : null);
-      node.declarations.push(finishNode(decl, "VariableDeclarator"));
-      if (!eat(_comma)) break;
-    }
-    return node;
-  }

Expression parsing

These nest, from the most general expression type at the top to -'atomic', nondivisible expression types at the bottom. Most of -the functions will simply let the function(s) below them parse, -and, if the syntactic construct they handle is present, wrap -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) -or the in operator (in for loops initalization expressions).

  function parseExpression(noComma, noIn) {
-    var expr = parseMaybeAssign(noIn);
-    if (!noComma && tokType === _comma) {
-      var node = startNodeFrom(expr);
-      node.expressions = [expr];
-      while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn));
-      return finishNode(node, "SequenceExpression");
-    }
-    return expr;
-  }

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

  function parseMaybeAssign(noIn) {
-    var left = parseMaybeConditional(noIn);
-    if (tokType.isAssign) {
-      var node = startNodeFrom(left);
-      node.operator = tokVal;
-      node.left = tokType === _eq ? toAssignable(left) : left;
-      checkLVal(left);
-      next();
-      node.right = parseMaybeAssign(noIn);
-      return finishNode(node, "AssignmentExpression");
-    }
-    return left;
-  }

Parse a ternary conditional (?:) operator.

  function parseMaybeConditional(noIn) {
-    var expr = parseExprOps(noIn);
-    if (eat(_question)) {
-      var node = startNodeFrom(expr);
-      node.test = expr;
-      node.consequent = parseExpression(true);
-      expect(_colon);
-      node.alternate = parseExpression(true, noIn);
-      return finishNode(node, "ConditionalExpression");
-    }
-    return expr;
-  }

Start the precedence parser.

  function parseExprOps(noIn) {
-    return parseExprOp(parseMaybeUnary(), -1, noIn);
-  }

Parse binary operators with the operator precedence parsing -algorithm. left is the left-hand side of the operator. -minPrec provides context that allows the function to stop and -defer further parser to one of its callers when it encounters an -operator that has a lower precedence than the set it is parsing.

  function parseExprOp(left, minPrec, noIn) {
-    var prec = tokType.binop;
-    if (prec != null && (!noIn || tokType !== _in)) {
-      if (prec > minPrec) {
-        var node = startNodeFrom(left);
-        node.left = left;
-        node.operator = tokVal;
-        var op = tokType;
-        next();
-        node.right = parseExprOp(parseMaybeUnary(), prec, noIn);
-        var exprNode = finishNode(node, (op === _logicalOR || op === _logicalAND) ? "LogicalExpression" : "BinaryExpression");
-        return parseExprOp(exprNode, minPrec, noIn);
-      }
-    }
-    return left;
-  }

Parse unary operators, both prefix and postfix.

  function parseMaybeUnary() {
-    if (tokType.prefix) {
-      var node = startNode(), update = tokType.isUpdate;
-      node.operator = tokVal;
-      node.prefix = true;
-      tokRegexpAllowed = true;
-      next();
-      node.argument = parseMaybeUnary();
-      if (update) checkLVal(node.argument);
-      else if (strict && node.operator === "delete" &&
-               node.argument.type === "Identifier")
-        raise(node.start, "Deleting local variable in strict mode");
-      return finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
-    }
-    var expr = parseExprSubscripts();
-    while (tokType.postfix && !canInsertSemicolon()) {
-      var node = startNodeFrom(expr);
-      node.operator = tokVal;
-      node.prefix = false;
-      node.argument = expr;
-      checkLVal(expr);
-      next();
-      expr = finishNode(node, "UpdateExpression");
-    }
-    return expr;
-  }

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

  function parseExprSubscripts() {
-    return parseSubscripts(parseExprAtom());
-  }
-
-  function parseSubscripts(base, noCalls) {
-    if (eat(_dot)) {
-      var node = startNodeFrom(base);
-      node.object = base;
-      node.property = parseIdent(true);
-      node.computed = false;
-      return parseSubscripts(finishNode(node, "MemberExpression"), noCalls);
-    } else if (eat(_bracketL)) {
-      var node = startNodeFrom(base);
-      node.object = base;
-      node.property = parseExpression();
-      node.computed = true;
-      expect(_bracketR);
-      return parseSubscripts(finishNode(node, "MemberExpression"), noCalls);
-    } else if (!noCalls && eat(_parenL)) {
-      var node = startNodeFrom(base);
-      node.callee = base;
-      node.arguments = parseExprList(_parenR, false);
-      return parseSubscripts(finishNode(node, "CallExpression"), noCalls);
-    } else if (tokType === _bquote) {
-      var node = startNodeFrom(base);
-      node.tag = base;
-      node.quasi = parseTemplate();
-      return parseSubscripts(finishNode(node, "TaggedTemplateExpression"), noCalls);
-    } return base;
-  }

Parse an atomic expression — either a single token that is an -expression, an expression started by a keyword like function or -new, or an expression wrapped in punctuation like (), [], -or {}.

  function parseExprAtom() {
-    switch (tokType) {
-    case _this:
-      var node = startNode();
-      next();
-      return finishNode(node, "ThisExpression");
-
-    case _yield:
-      if (inGenerator) return parseYield();
-
-    case _name:
-      var id = parseIdent(tokType !== _name);
-      if (eat(_arrow)) {
-        return parseArrowExpression(startNodeFrom(id), [id]);
-      }
-      return id;
-
-    case _num: case _string: case _regexp:
-      var node = startNode();
-      node.value = tokVal;
-      node.raw = input.slice(tokStart, tokEnd);
-      next();
-      return finishNode(node, "Literal");
-
-    case _null: case _true: case _false:
-      var node = startNode();
-      node.value = tokType.atomValue;
-      node.raw = tokType.keyword;
-      next();
-      return finishNode(node, "Literal");
-
-    case _parenL:
-      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();
-          exprList = val.type === "SequenceExpression" ? val.expressions : [val];
-        } else {
-          exprList = [];
-        }
-        expect(_parenR);

if '=>' follows '(...)', convert contents to arguments

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

forbid '()' before everything but '=>'

          if (!val) unexpected(lastStart);

forbid '...' in sequence expressions

          if (options.ecmaVersion >= 6) {
-            for (var i = 0; i < exprList.length; i++) {
-              if (exprList[i].type === "SpreadElement") unexpected();
-            }
-          }
-        }
-      }
-      val.start = tokStart1;
-      val.end = lastEnd;
-      if (options.locations) {
-        val.loc.start = tokStartLoc1;
-        val.loc.end = lastEndLoc;
-      }
-      if (options.ranges) {
-        val.range = [tokStart1, lastEnd];
-      }
-      return val;
-
-    case _bracketL:
-      var node = startNode();
-      next();

check whether this is array comprehension or regular array

      if (options.ecmaVersion >= 6 && tokType === _for) {
-        return parseComprehension(node, false);
-      }
-      node.elements = parseExprList(_bracketR, true, true);
-      return finishNode(node, "ArrayExpression");
-
-    case _braceL:
-      return parseObj();
-
-    case _function:
-      var node = startNode();
-      next();
-      return parseFunction(node, false);
-
-    case _class:
-      return parseClass(startNode(), false);
-
-    case _new:
-      return parseNew();
-
-    case _ellipsis:
-      return parseSpread();
-
-    case _bquote:
-      return parseTemplate();
-
-    default:
-      unexpected();
-    }
-  }

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

  function parseNew() {
-    var node = startNode();
-    next();
-    node.callee = parseSubscripts(parseExprAtom(), true);
-    if (eat(_parenL)) node.arguments = parseExprList(_parenR, false);
-    else node.arguments = empty;
-    return finishNode(node, "NewExpression");
-  }

Parse spread element '...expr'

  function parseSpread() {
-    var node = startNode();
-    next();
-    node.argument = parseExpression(true);
-    return finishNode(node, "SpreadElement");
-  }

Parse template expression.

  function parseTemplate() {
-    var node = startNode();
-    node.expressions = [];
-    node.quasis = [];
-    inTemplate = true;
-    next();
-    for (;;) {
-      var elem = startNode();
-      elem.value = {cooked: tokVal, raw: input.slice(tokStart, tokEnd)};
-      elem.tail = false;
-      next();
-      node.quasis.push(finishNode(elem, "TemplateElement"));
-      if (eat(_bquote)) { // '`', end of template
-        elem.tail = true;
-        break;
-      }
-      inTemplate = false;
-      expect(_dollarBraceL);
-      node.expressions.push(parseExpression());
-      inTemplate = true;
-      expect(_braceR);
-    }
-    inTemplate = false;
-    return finishNode(node, "TemplateLiteral");
-  }

Parse an object literal.

  function parseObj() {
-    var node = startNode(), first = true, propHash = {};
-    node.properties = [];
-    next();
-    while (!eat(_braceR)) {
-      if (!first) {
-        expect(_comma);
-        if (options.allowTrailingCommas && eat(_braceR)) break;
-      } else first = false;
-
-      var prop = startNode(), isGenerator;
-      if (options.ecmaVersion >= 6) {
-        prop.method = false;
-        prop.shorthand = false;
-        isGenerator = eat(_star);
-      }
-      parsePropertyName(prop);
-      if (eat(_colon)) {
-        prop.value = parseExpression(true);
-        prop.kind = "init";
-      } else if (options.ecmaVersion >= 6 && tokType === _parenL) {
-        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();
-        prop.kind = prop.key.name;
-        parsePropertyName(prop);
-        prop.value = parseMethod(false);
-      } else if (options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
-        prop.kind = "init";
-        prop.value = prop.key;
-        prop.shorthand = true;
-      } else unexpected();
-
-      checkPropClash(prop, propHash);
-      node.properties.push(finishNode(prop, "Property"));
-    }
-    return finishNode(node, "ObjectExpression");
-  }
-
-  function parsePropertyName(prop) {
-    if (options.ecmaVersion >= 6) {
-      if (eat(_bracketL)) {
-        prop.computed = true;
-        prop.key = parseExpression();
-        expect(_bracketR);
-        return;
-      } else {
-        prop.computed = false;
-      }
-    }
-    prop.key = (tokType === _num || tokType === _string) ? parseExprAtom() : parseIdent(true);
-  }

Initialize empty function node.

  function initFunction(node) {
-    node.id = null;
-    node.params = [];
-    if (options.ecmaVersion >= 6) {
-      node.defaults = [];
-      node.rest = null;
-      node.generator = false;
-    }
-  }

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

  function parseFunction(node, isStatement, allowExpressionBody) {
-    initFunction(node);
-    if (options.ecmaVersion >= 6) {
-      node.generator = eat(_star);
-    }
-    if (isStatement || tokType === _name) {
-      node.id = parseIdent();
-    }
-    parseFunctionParams(node);
-    parseFunctionBody(node, allowExpressionBody);
-    return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
-  }

Parse object or class method.

  function parseMethod(isGenerator) {
-    var node = startNode();
-    initFunction(node);
-    parseFunctionParams(node);
-    var allowExpressionBody;
-    if (options.ecmaVersion >= 6) {
-      node.generator = isGenerator;
-      allowExpressionBody = true;
-    } else {
-      allowExpressionBody = false;
-    }
-    parseFunctionBody(node, allowExpressionBody);
-    return finishNode(node, "FunctionExpression");
-  }

Parse arrow function expression with given parameters.

  function parseArrowExpression(node, params) {
-    initFunction(node);
-
-    var defaults = node.defaults, hasDefaults = false;
-
-    for (var i = 0, lastI = params.length - 1; i <= lastI; i++) {
-      var param = params[i];
-
-      if (param.type === "AssignmentExpression" && param.operator === "=") {
-        hasDefaults = true;
-        params[i] = param.left;
-        defaults.push(param.right);
-      } else {
-        toAssignable(param, i === lastI, true);
-        defaults.push(null);
-        if (param.type === "SpreadElement") {
-          params.length--;
-          node.rest = param.argument;
-          break;
-        }
-      }
-    }
-
-    node.params = params;
-    if (!hasDefaults) node.defaults = [];
-
-    parseFunctionBody(node, true);
-    return finishNode(node, "ArrowFunctionExpression");
-  }

Parse function parameters.

  function parseFunctionParams(node) {
-    var defaults = [], hasDefaults = false;
-
-    expect(_parenL);
-    for (;;) {
-      if (eat(_parenR)) {
-        break;
-      } else if (options.ecmaVersion >= 6 && eat(_ellipsis)) {
-        node.rest = toAssignable(parseExprAtom(), false, true);
-        checkSpreadAssign(node.rest);
-        expect(_parenR);
-        break;
-      } else {
-        node.params.push(options.ecmaVersion >= 6 ? toAssignable(parseExprAtom(), false, true) : parseIdent());
-        if (options.ecmaVersion >= 6 && tokType === _eq) {
-          next();
-          hasDefaults = true;
-          defaults.push(parseExpression(true));
-        }
-        if (!eat(_comma)) {
-          expect(_parenR);
-          break;
-        }
-      }
-    }
-
-    if (hasDefaults) node.defaults = defaults;
-  }

Parse function body and check parameters.

  function parseFunctionBody(node, allowExpression) {
-    var isExpression = allowExpression && tokType !== _braceL;
-
-    if (isExpression) {
-      node.body = parseExpression(true);
-      node.expression = true;
-    } else {

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

      var oldInFunc = inFunction, oldInGen = inGenerator, oldLabels = labels;
-      inFunction = true; inGenerator = node.generator; labels = [];
-      node.body = parseBlock(true);
-      node.expression = false;
-      inFunction = oldInFunc; inGenerator = oldInGen; labels = oldLabels;
-    }

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

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

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

  function parseClass(node, isStatement) {
-    next();
-    node.id = tokType === _name ? parseIdent() : isStatement ? unexpected() : null;
-    node.superClass = eat(_extends) ? parseExpression() : null;
-    var classBody = startNode(), methodHash = {}, staticMethodHash = {};
-    classBody.body = [];
-    expect(_braceL);
-    while (!eat(_braceR)) {
-      var method = startNode();
-      if (tokType === _name && tokVal === "static") {
-        next();
-        method['static'] = true;
-      } else {
-        method['static'] = false;
-      }
-      var isGenerator = eat(_star);
-      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;
-        parsePropertyName(method);
-      } else {
-        method.kind = "";
-      }
-      method.value = parseMethod(isGenerator);
-      checkPropClash(method, method['static'] ? staticMethodHash : methodHash);
-      classBody.body.push(finishNode(method, "MethodDefinition"));
-      eat(_semi);
-    }
-    node.body = finishNode(classBody, "ClassBody");
-    return finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
-  }

Parses a comma-separated list of expressions, and returns them as -an array. close is the token type that ends the list, and -allowEmpty can be turned on to allow subsequent commas with -nothing in between them to be parsed as null (which is needed -for array literals).

  function parseExprList(close, allowTrailingComma, allowEmpty) {
-    var elts = [], first = true;
-    while (!eat(close)) {
-      if (!first) {
-        expect(_comma);
-        if (allowTrailingComma && options.allowTrailingCommas && eat(close)) break;
-      } else first = false;
-
-      if (allowEmpty && tokType === _comma) elts.push(null);
-      else elts.push(parseExpression(true));
-    }
-    return elts;
-  }

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

  function parseIdent(liberal) {
-    var node = startNode();
-    if (liberal && options.forbidReserved == "everywhere") liberal = false;
-    if (tokType === _name) {
-      if (!liberal &&
-          (options.forbidReserved &&
-           (options.ecmaVersion === 3 ? isReservedWord3 : isReservedWord5)(tokVal) ||
-           strict && isStrictReservedWord(tokVal)) &&
-          input.slice(tokStart, tokEnd).indexOf("\\") == -1)
-        raise(tokStart, "The keyword '" + tokVal + "' is reserved");
-      node.name = tokVal;
-    } else if (liberal && tokType.keyword) {
-      node.name = tokType.keyword;
-    } else {
-      unexpected();
-    }
-    tokRegexpAllowed = false;
-    next();
-    return finishNode(node, "Identifier");
-  }

Parses module export declaration.

  function parseExport(node) {
-    next();

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

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

export default ...;

    if (eat(_default)) {
-      node.declaration = parseExpression(true);
-      node['default'] = true;
-      node.specifiers = null;
-      node.source = null;
-      semicolon();
-    } else {

export * from '...' -export { x, y as z } [from '...']

      var isBatch = tokType === _star;
-      node.declaration = null;
-      node['default'] = false;
-      node.specifiers = parseExportSpecifiers();
-      if (tokType === _name && tokVal === "from") {
-        next();
-        node.source = tokType === _string ? parseExprAtom() : unexpected();
-      } else {
-        if (isBatch) unexpected();
-        node.source = null;
-      }
-    }
-    return finishNode(node, "ExportDeclaration");
-  }

Parses a comma-separated list of module exports.

  function parseExportSpecifiers() {
-    var nodes = [], first = true;
-    if (tokType === _star) {

export * from '...'

      var node = startNode();
-      next();
-      nodes.push(finishNode(node, "ExportBatchSpecifier"));
-    } else {

export { x, y as z } [from '...']

      expect(_braceL);
-      while (!eat(_braceR)) {
-        if (!first) {
-          expect(_comma);
-          if (options.allowTrailingCommas && eat(_braceR)) break;
-        } else first = false;
-
-        var node = startNode();
-        node.id = parseIdent();
-        if (tokType === _name && tokVal === "as") {
-          next();
-          node.name = parseIdent(true);
-        } else {
-          node.name = null;
-        }
-        nodes.push(finishNode(node, "ExportSpecifier"));
-      }
-    }
-    return nodes;
-  }

Parses import declaration.

  function parseImport(node) {
-    next();

import '...';

    if (tokType === _string) {
-      node.specifiers = [];
-      node.source = parseExprAtom();
-      node.kind = "";
-    } else {
-      node.specifiers = parseImportSpecifiers();
-      if (tokType !== _name || tokVal !== "from") unexpected();
-      next();
-      node.source = tokType === _string ? parseExprAtom() : unexpected();

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

      node.kind = node.specifiers[0]['default'] ? "default" : "named";
-    }
-    return finishNode(node, "ImportDeclaration");
-  }

Parses a comma-separated list of module imports.

  function parseImportSpecifiers() {
-    var nodes = [], first = true;
-    if (tokType === _star) {
-      var node = startNode();
-      next();
-      if (tokType !== _name || tokVal !== "as") unexpected();
-      next();
-      node.name = parseIdent();
-      checkLVal(node.name, true);
-      nodes.push(finishNode(node, "ImportBatchSpecifier"));
-      return nodes;
-    }
-    if (tokType === _name) {

import defaultObj, { x, y as z } from '...'

      var node = startNode();
-      node.id = parseIdent();
-      checkLVal(node.id, true);
-      node.name = null;
-      node['default'] = true;
-      nodes.push(finishNode(node, "ImportSpecifier"));
-      if (!eat(_comma)) return nodes;
-    }
-    expect(_braceL);
-    while (!eat(_braceR)) {
-      if (!first) {
-        expect(_comma);
-        if (options.allowTrailingCommas && eat(_braceR)) break;
-      } else first = false;
-
-      var node = startNode();
-      node.id = parseIdent(true);
-      if (tokType === _name && tokVal === "as") {
-        next();
-        node.name = parseIdent();
-      } else {
-        node.name = null;
-      }
-      checkLVal(node.name || node.id, true);
-      node['default'] = false;
-      nodes.push(finishNode(node, "ImportSpecifier"));
-    }
-    return nodes;
-  }

Parses yield expression inside generator.

  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");
-  }
-
-});
-
-
\ No newline at end of file diff --git a/package.json b/package.json index 8f029de5cb..4d238cf157 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,27 @@ { - "name": "acorn", - "description": "ECMAScript parser", - "homepage": "http://marijnhaverbeke.nl/acorn/", + "name": "acorn-jsx", + "description": "Alternative React JSX parser", "main": "acorn.js", "version": "0.7.1", - "engines": {"node": ">=0.4.0"}, - "maintainers": [{"name": "Marijn Haverbeke", - "email": "marijnh@gmail.com", - "web": "http://marijnhaverbeke.nl"}], - "repository": {"type": "git", - "url": "http://marijnhaverbeke.nl/git/acorn"}, - "licenses": [{"type": "MIT", - "url": "http://marijnhaverbeke.nl/acorn/LICENSE"}], + "maintainers": [ + { + "name": "Marijn Haverbeke", + "email": "marijnh@gmail.com", + "web": "http://marijnhaverbeke.nl" + }, + { + "name": "Ingvar Stepanyan", + "email": "me@rreverser.com", + "web": "https://github.com/RReverser" + } + ], + "repository": "RReverser/acorn-jsx", + "licenses": [{ + "type": "MIT", + "url": "http://marijnhaverbeke.nl/acorn/LICENSE" + }], "scripts": {"test": "node test/run.js"}, - "bin": {"acorn": "./bin/acorn"}, + "bin": {"acorn-jsx": "./bin/acorn"}, "devDependencies": {"regenerate": "~0.6.2", "unicode-7.0.0": "~0.1.5"} } From 817120b3701c3efd60090eeb34c970d8c6982576 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 11 Jul 2014 01:51:33 +0300 Subject: [PATCH 015/198] Small test refactoring. --- test/tests-jsx.js | 2766 ++++++++++++++++++++++----------------------- 1 file changed, 1381 insertions(+), 1385 deletions(-) diff --git a/test/tests-jsx.js b/test/tests-jsx.js index a65f51b2b8..bd2b7d307f 100644 --- a/test/tests-jsx.js +++ b/test/tests-jsx.js @@ -1,108 +1,99 @@ // React JSX tests -if (typeof exports != "undefined") { +if (typeof exports !== "undefined") { var test = require("./driver.js").test; - var testFail = require("./driver.js").testFail; - var testAssert = require("./driver.js").testAssert; } // Simply taken from esprima-fb/fbtest.js var fbTestFixture = { - 'XJS': { - '': { - type: "ExpressionStatement", - expression: { - type: "XJSElement", - openingElement: { - type: "XJSOpeningElement", - name: { - type: "XJSIdentifier", - name: "a", - range: [1, 2], - loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 2 } - } - }, - selfClosing: true, - attributes: [], - range: [0, 5], + '': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "a", + range: [1, 2], loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 5 } + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } } }, - children: [], + selfClosing: true, + attributes: [], range: [0, 5], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 5 } } }, + children: [], range: [0, 5], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 5 } } }, - '': { - type: 'ExpressionStatement', - expression: { - type: 'XJSElement', - openingElement: { - type: 'XJSOpeningElement', + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + '': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSNamespacedName', + namespace: { + type: 'XJSIdentifier', + name: 'n', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + name: { + type: 'XJSIdentifier', + name: 'a', + range: [3, 4], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + range: [1, 4], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 4 } + } + }, + selfClosing: true, + attributes: [{ + type: 'XJSAttribute', name: { type: 'XJSNamespacedName', namespace: { type: 'XJSIdentifier', name: 'n', - range: [1, 2], + range: [5, 6], loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 2 } + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } } }, name: { type: 'XJSIdentifier', - name: 'a', - range: [3, 4], + name: 'v', + range: [7, 8], loc: { - start: { line: 1, column: 3 }, - end: { line: 1, column: 4 } - } - }, - range: [1, 4], - loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 4 } - } - }, - selfClosing: true, - attributes: [{ - type: 'XJSAttribute', - name: { - type: 'XJSNamespacedName', - namespace: { - type: 'XJSIdentifier', - name: 'n', - range: [5, 6], - loc: { - start: { line: 1, column: 5 }, - end: { line: 1, column: 6 } - } - }, - name: { - type: 'XJSIdentifier', - name: 'v', - range: [7, 8], - loc: { - start: { line: 1, column: 7 }, - end: { line: 1, column: 8 } - } - }, - range: [5, 8], - loc: { - start: { line: 1, column: 5 }, + start: { line: 1, column: 7 }, end: { line: 1, column: 8 } } }, @@ -111,395 +102,385 @@ var fbTestFixture = { start: { line: 1, column: 5 }, end: { line: 1, column: 8 } } - }], - range: [0, 11], + }, + range: [5, 8], loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 11 } + start: { line: 1, column: 5 }, + end: { line: 1, column: 8 } } - }, - children: [], + }], range: [0, 11], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 11 } } }, + children: [], range: [0, 11], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 11 } } }, - ' {value} ': { - type: 'ExpressionStatement', - expression: { + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + ' {value} ': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + selfClosing: false, + attributes: [{ + type: 'XJSAttribute', + name: { + type: 'XJSNamespacedName', + namespace: { + type: 'XJSIdentifier', + name: 'n', + range: [3, 4], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + name: { + type: 'XJSIdentifier', + name: 'foo', + range: [5, 8], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 8 } + } + }, + range: [3, 8], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 8 } + } + }, + value: { + type: 'Literal', + value: 'bar', + raw: '"bar"', + range: [9, 14], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 14 } + } + }, + range: [3, 14], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 14 } + } + }], + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [38, 39], + loc: { + start: { line: 1, column: 38 }, + end: { line: 1, column: 39 } + } + }, + range: [36, 40], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 40 } + } + }, + children: [{ + type: 'Literal', + value: ' ', + raw: ' ', + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, { + type: 'XJSExpressionContainer', + expression: { + type: 'Identifier', + name: 'value', + range: [17, 22], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 22 } + } + }, + range: [16, 23], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 23 } + } + }, { + type: 'Literal', + value: ' ', + raw: ' ', + range: [23, 24], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 24 } + } + }, { type: 'XJSElement', openingElement: { type: 'XJSOpeningElement', name: { type: 'XJSIdentifier', - name: 'a', - range: [1, 2], + name: 'b', + range: [25, 26], loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 2 } + start: { line: 1, column: 25 }, + end: { line: 1, column: 26 } } }, selfClosing: false, - attributes: [{ - type: 'XJSAttribute', - name: { - type: 'XJSNamespacedName', - namespace: { - type: 'XJSIdentifier', - name: 'n', - range: [3, 4], - loc: { - start: { line: 1, column: 3 }, - end: { line: 1, column: 4 } - } - }, - name: { - type: 'XJSIdentifier', - name: 'foo', - range: [5, 8], - loc: { - start: { line: 1, column: 5 }, - end: { line: 1, column: 8 } - } - }, - range: [3, 8], - loc: { - start: { line: 1, column: 3 }, - end: { line: 1, column: 8 } - } - }, - value: { - type: 'Literal', - value: 'bar', - raw: '"bar"', - range: [9, 14], - loc: { - start: { line: 1, column: 9 }, - end: { line: 1, column: 14 } - } - }, - range: [3, 14], - loc: { - start: { line: 1, column: 3 }, - end: { line: 1, column: 14 } - } - }], - range: [0, 15], + attributes: [], + range: [24, 27], loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 15 } + start: { line: 1, column: 24 }, + end: { line: 1, column: 27 } } }, closingElement: { type: 'XJSClosingElement', name: { type: 'XJSIdentifier', - name: 'a', - range: [38, 39], + name: 'b', + range: [34, 35], loc: { - start: { line: 1, column: 38 }, - end: { line: 1, column: 39 } + start: { line: 1, column: 34 }, + end: { line: 1, column: 35 } } }, - range: [36, 40], + range: [32, 36], loc: { - start: { line: 1, column: 36 }, - end: { line: 1, column: 40 } + start: { line: 1, column: 32 }, + end: { line: 1, column: 36 } } }, children: [{ - type: 'Literal', - value: ' ', - raw: ' ', - range: [15, 16], - loc: { - start: { line: 1, column: 15 }, - end: { line: 1, column: 16 } - } - }, { - type: 'XJSExpressionContainer', - expression: { - type: 'Identifier', - name: 'value', - range: [17, 22], - loc: { - start: { line: 1, column: 17 }, - end: { line: 1, column: 22 } - } - }, - range: [16, 23], - loc: { - start: { line: 1, column: 16 }, - end: { line: 1, column: 23 } - } - }, { - type: 'Literal', - value: ' ', - raw: ' ', - range: [23, 24], - loc: { - start: { line: 1, column: 23 }, - end: { line: 1, column: 24 } - } - }, { type: 'XJSElement', openingElement: { type: 'XJSOpeningElement', name: { type: 'XJSIdentifier', - name: 'b', - range: [25, 26], + name: 'c', + range: [28, 29], loc: { - start: { line: 1, column: 25 }, - end: { line: 1, column: 26 } + start: { line: 1, column: 28 }, + end: { line: 1, column: 29 } } }, - selfClosing: false, + selfClosing: true, attributes: [], - range: [24, 27], - loc: { - start: { line: 1, column: 24 }, - end: { line: 1, column: 27 } - } - }, - closingElement: { - type: 'XJSClosingElement', - name: { - type: 'XJSIdentifier', - name: 'b', - range: [34, 35], - loc: { - start: { line: 1, column: 34 }, - end: { line: 1, column: 35 } - } - }, - range: [32, 36], - loc: { - start: { line: 1, column: 32 }, - end: { line: 1, column: 36 } - } - }, - children: [{ - type: 'XJSElement', - openingElement: { - type: 'XJSOpeningElement', - name: { - type: 'XJSIdentifier', - name: 'c', - range: [28, 29], - loc: { - start: { line: 1, column: 28 }, - end: { line: 1, column: 29 } - } - }, - selfClosing: true, - attributes: [], - range: [27, 32], - loc: { - start: { line: 1, column: 27 }, - end: { line: 1, column: 32 } - } - }, - children: [], range: [27, 32], loc: { start: { line: 1, column: 27 }, end: { line: 1, column: 32 } } - }], - range: [24, 36], + }, + children: [], + range: [27, 32], loc: { - start: { line: 1, column: 24 }, - end: { line: 1, column: 36 } + start: { line: 1, column: 27 }, + end: { line: 1, column: 32 } } }], - range: [0, 40], + range: [24, 36], loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 40 } + start: { line: 1, column: 24 }, + end: { line: 1, column: 36 } } - }, + }], range: [0, 40], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 40 } } }, - '': { - type: "ExpressionStatement", - expression: { - type: "XJSElement", - openingElement: { - type: "XJSOpeningElement", - name: { - type: "XJSIdentifier", - name: "a", - range: [1, 2], - loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 2 } - } - }, - selfClosing: true, - attributes: [ - { - type: "XJSAttribute", - name: { - type: "XJSIdentifier", - name: "b", - range: [3, 4], - loc: { - start: { line: 1, column: 3 }, - end: { line: 1, column: 4 } - } - }, - value: { - type: "XJSExpressionContainer", - expression: { - type: "Literal", - value: " ", - raw: "\" \"", - range: [6, 9], - loc: { - start: { line: 1, column: 6 }, - end: { line: 1, column: 9 } - } - }, - range: [5, 10], - loc: { - start: { line: 1, column: 5 }, - end: { line: 1, column: 10 } - } - }, - range: [3, 10], + range: [0, 40], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 40 } + } + }, + '': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "a", + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + selfClosing: true, + attributes: [ + { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "b", + range: [3, 4], loc: { start: { line: 1, column: 3 }, - end: { line: 1, column: 10 } + end: { line: 1, column: 4 } } }, - { - type: "XJSAttribute", - name: { - type: "XJSIdentifier", - name: "c", - range: [11, 12], - loc: { - start: { line: 1, column: 11 }, - end: { line: 1, column: 12 } - } - }, - value: { + value: { + type: "XJSExpressionContainer", + expression: { type: "Literal", value: " ", raw: "\" \"", - range: [13, 16], + range: [6, 9], loc: { - start: { line: 1, column: 13 }, - end: { line: 1, column: 16 } + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } } }, - range: [11, 16], + range: [5, 10], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 10 } + } + }, + range: [3, 10], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 10 } + } + }, + { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "c", + range: [11, 12], loc: { start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + value: { + type: "Literal", + value: " ", + raw: "\" \"", + range: [13, 16], + loc: { + start: { line: 1, column: 13 }, end: { line: 1, column: 16 } } }, - { - type: "XJSAttribute", - name: { - type: "XJSIdentifier", - name: "d", - range: [17, 18], - loc: { - start: { line: 1, column: 17 }, - end: { line: 1, column: 18 } - } - }, - value: { - type: "Literal", - value: "&", - raw: "\"&\"", - range: [19, 26], - loc: { - start: { line: 1, column: 19 }, - end: { line: 1, column: 26 } - } - }, - range: [17, 26], + range: [11, 16], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 16 } + } + }, + { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "d", + range: [17, 18], loc: { start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }, + value: { + type: "Literal", + value: "&", + raw: "\"&\"", + range: [19, 26], + loc: { + start: { line: 1, column: 19 }, end: { line: 1, column: 26 } } + }, + range: [17, 26], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 26 } } - ], - range: [0, 29], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 29 } } - }, - children: [], + ], range: [0, 29], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 29 } } }, + children: [], range: [0, 29], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 29 } } }, - '': { - type: "ExpressionStatement", - expression: { - type: "XJSElement", - openingElement: { - type: "XJSOpeningElement", - name: { - type: "XJSIdentifier", - name: "a", - range: [ - 1, - 2 - ], - loc: { - start: { - line: 1, - column: 1 - }, - end: { - line: 1, - column: 2 - } - } - }, - selfClosing: true, - attributes: [], + range: [0, 29], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 29 } + } + }, + '': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "a", range: [ - 0, - 5 + 1, + 2 ], loc: { start: { line: 1, - column: 0 + column: 1 }, end: { - line: 2, + line: 1, column: 2 } } }, - children: [], + selfClosing: true, + attributes: [], range: [ 0, 5 @@ -515,6 +496,7 @@ var fbTestFixture = { } } }, + children: [], range: [ 0, 5 @@ -530,98 +512,98 @@ var fbTestFixture = { } } }, - '<日本語>': { - type: "ExpressionStatement", - expression: { - type: "XJSElement", - openingElement: { - type: "XJSOpeningElement", - name: { - type: "XJSIdentifier", - name: "日本語", - range: [ - 1, - 4 - ], - loc: { - start: { - line: 1, - column: 1 - }, - end: { - line: 1, - column: 4 - } - } - }, - selfClosing: false, - attributes: [], + range: [ + 0, + 5 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 2, + column: 2 + } + } + }, + '<日本語>': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "日本語", range: [ - 0, - 5 + 1, + 4 ], loc: { start: { line: 1, - column: 0 + column: 1 }, end: { line: 1, - column: 5 + column: 4 } } }, - closingElement: { - type: "XJSClosingElement", - name: { - type: "XJSIdentifier", - name: "日本語", - range: [ - 7, - 10 - ], - loc: { - start: { - line: 1, - column: 7 - }, - end: { - line: 1, - column: 10 - } - } - }, - range: [ - 5, - 11 - ], - loc: { - start: { - line: 1, - column: 5 - }, - end: { - line: 1, - column: 11 - } - } - }, - children: [], + selfClosing: false, + attributes: [], range: [ 0, - 11 + 5 ], loc: { start: { line: 1, column: 0 }, + end: { + line: 1, + column: 5 + } + } + }, + closingElement: { + type: "XJSClosingElement", + name: { + type: "XJSIdentifier", + name: "日本語", + range: [ + 7, + 10 + ], + loc: { + start: { + line: 1, + column: 7 + }, + end: { + line: 1, + column: 10 + } + } + }, + range: [ + 5, + 11 + ], + loc: { + start: { + line: 1, + column: 5 + }, end: { line: 1, column: 11 } } }, + children: [], range: [ 0, 11 @@ -637,174 +619,174 @@ var fbTestFixture = { } } }, + range: [ + 0, + 11 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 11 + } + } + }, - '\nbar\nbaz\r\n': { - type: "ExpressionStatement", - expression: { - type: "XJSElement", - openingElement: { - type: "XJSOpeningElement", - name: { - type: "XJSIdentifier", - name: "AbC-def", - range: [ - 1, - 8 - ], - loc: { - start: { - line: 1, - column: 1 - }, - end: { - line: 1, - column: 8 - } + '\nbar\nbaz\r\n': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "AbC-def", + range: [ + 1, + 8 + ], + loc: { + start: { + line: 1, + column: 1 + }, + end: { + line: 1, + column: 8 } - }, - selfClosing: false, - attributes: [ - { - type: "XJSAttribute", - name: { - type: "XJSIdentifier", - name: "test", - range: [ - 11, - 15 - ], - loc: { - start: { - line: 2, - column: 2 - }, - end: { - line: 2, - column: 6 - } - } - }, - value: { - type: "Literal", - value: "&&", - raw: "\"&&\"", - range: [ - 16, - 31 - ], - loc: { - start: { - line: 2, - column: 7 - }, - end: { - line: 2, - column: 22 - } - } - }, + } + }, + selfClosing: false, + attributes: [ + { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "test", range: [ 11, - 31 + 15 ], loc: { start: { line: 2, column: 2 }, + end: { + line: 2, + column: 6 + } + } + }, + value: { + type: "Literal", + value: "&&", + raw: "\"&&\"", + range: [ + 16, + 31 + ], + loc: { + start: { + line: 2, + column: 7 + }, end: { line: 2, column: 22 } } - } - ], - range: [ - 0, - 32 - ], - loc: { - start: { - line: 1, - column: 0 }, - end: { - line: 2, - column: 23 - } - } - }, - closingElement: { - type: "XJSClosingElement", - name: { - type: "XJSIdentifier", - name: "AbC-def", range: [ - 44, - 51 - ], - loc: { - start: { - line: 5, - column: 2 - }, - end: { - line: 5, - column: 9 - } - } - }, - range: [ - 42, - 52 - ], - loc: { - start: { - line: 5, - column: 0 - }, - end: { - line: 5, - column: 10 - } - } - }, - children: [ - { - type: "Literal", - value: "\nbar\nbaz\r\n", - raw: "\nbar\nbaz\r\n", - range: [ - 32, - 42 + 11, + 31 ], loc: { start: { line: 2, - column: 23 + column: 2 }, end: { - line: 5, - column: 0 + line: 2, + column: 22 } } } ], range: [ 0, - 52 + 32 ], loc: { start: { line: 1, column: 0 }, + end: { + line: 2, + column: 23 + } + } + }, + closingElement: { + type: "XJSClosingElement", + name: { + type: "XJSIdentifier", + name: "AbC-def", + range: [ + 44, + 51 + ], + loc: { + start: { + line: 5, + column: 2 + }, + end: { + line: 5, + column: 9 + } + } + }, + range: [ + 42, + 52 + ], + loc: { + start: { + line: 5, + column: 0 + }, end: { line: 5, column: 10 } } }, + children: [ + { + type: "Literal", + value: "\nbar\nbaz\r\n", + raw: "\nbar\nbaz\r\n", + range: [ + 32, + 42 + ], + loc: { + start: { + line: 2, + column: 23 + }, + end: { + line: 5, + column: 0 + } + } + } + ], range: [ 0, 52 @@ -820,115 +802,114 @@ var fbTestFixture = { } } }, + range: [ + 0, + 52 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 5, + column: 10 + } + } + }, - ' : } />': { - type: "ExpressionStatement", - expression: { - type: "XJSElement", - openingElement: { - type: "XJSOpeningElement", - name: { - type: "XJSIdentifier", - name: "a", - range: [ - 1, - 2 - ], - loc: { - start: { - line: 1, - column: 1 - }, - end: { - line: 1, - column: 2 - } + ' : } />': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "a", + range: [ + 1, + 2 + ], + loc: { + start: { + line: 1, + column: 1 + }, + end: { + line: 1, + column: 2 } - }, - selfClosing: true, - attributes: [ - { - type: "XJSAttribute", - name: { - type: "XJSIdentifier", - name: "b", - range: [ - 3, - 4 - ], - loc: { - start: { - line: 1, - column: 3 - }, - end: { - line: 1, - column: 4 - } + } + }, + selfClosing: true, + attributes: [ + { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "b", + range: [ + 3, + 4 + ], + loc: { + start: { + line: 1, + column: 3 + }, + end: { + line: 1, + column: 4 } - }, - value: { - type: "XJSExpressionContainer", - expression: { - type: "ConditionalExpression", - test: { - type: "Identifier", - name: "x", - range: [ - 6, - 7 - ], - loc: { - start: { - line: 1, - column: 6 - }, - end: { - line: 1, - column: 7 - } + } + }, + value: { + type: "XJSExpressionContainer", + expression: { + type: "ConditionalExpression", + test: { + type: "Identifier", + name: "x", + range: [ + 6, + 7 + ], + loc: { + start: { + line: 1, + column: 6 + }, + end: { + line: 1, + column: 7 } - }, - consequent: { - type: "XJSElement", - openingElement: { - type: "XJSOpeningElement", - name: { - type: "XJSIdentifier", - name: "c", - range: [ - 11, - 12 - ], - loc: { - start: { - line: 1, - column: 11 - }, - end: { - line: 1, - column: 12 - } - } - }, - selfClosing: true, - attributes: [], + } + }, + consequent: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "c", range: [ - 10, - 15 + 11, + 12 ], loc: { start: { line: 1, - column: 10 + column: 11 }, end: { line: 1, - column: 15 + column: 12 } } }, - children: [], + selfClosing: true, + attributes: [], range: [ 10, 15 @@ -944,46 +925,46 @@ var fbTestFixture = { } } }, - alternate: { - type: "XJSElement", - openingElement: { - type: "XJSOpeningElement", - name: { - type: "XJSIdentifier", - name: "d", - range: [ - 19, - 20 - ], - loc: { - start: { - line: 1, - column: 19 - }, - end: { - line: 1, - column: 20 - } - } - }, - selfClosing: true, - attributes: [], + children: [], + range: [ + 10, + 15 + ], + loc: { + start: { + line: 1, + column: 10 + }, + end: { + line: 1, + column: 15 + } + } + }, + alternate: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "d", range: [ - 18, - 23 + 19, + 20 ], loc: { start: { line: 1, - column: 18 + column: 19 }, end: { line: 1, - column: 23 + column: 20 } } }, - children: [], + selfClosing: true, + attributes: [], range: [ 18, 23 @@ -999,14 +980,15 @@ var fbTestFixture = { } } }, + children: [], range: [ - 6, + 18, 23 ], loc: { start: { line: 1, - column: 6 + column: 18 }, end: { line: 1, @@ -1015,52 +997,51 @@ var fbTestFixture = { } }, range: [ - 5, - 24 + 6, + 23 ], loc: { start: { line: 1, - column: 5 + column: 6 }, end: { line: 1, - column: 24 + column: 23 } } }, range: [ - 3, + 5, 24 ], loc: { start: { line: 1, - column: 3 + column: 5 }, end: { line: 1, column: 24 } } - } - ], - range: [ - 0, - 27 - ], - loc: { - start: { - line: 1, - column: 0 }, - end: { - line: 1, - column: 27 + range: [ + 3, + 24 + ], + loc: { + start: { + line: 1, + column: 3 + }, + end: { + line: 1, + column: 24 + } } } - }, - children: [], + ], range: [ 0, 27 @@ -1076,6 +1057,7 @@ var fbTestFixture = { } } }, + children: [], range: [ 0, 27 @@ -1091,324 +1073,323 @@ var fbTestFixture = { } } }, + range: [ + 0, + 27 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 27 + } + } + }, - '{}': { - type: 'ExpressionStatement', - expression: { - type: 'XJSElement', - openingElement: { - type: 'XJSOpeningElement', - name: { - type: 'XJSIdentifier', - name: 'a', - range: [1, 2], - loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 2 } - } - }, - selfClosing: false, - attributes: [], - range: [0, 3], + '{}': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [1, 2], loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 3 } + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } } }, - closingElement: { - type: 'XJSClosingElement', - name: { - type: 'XJSIdentifier', - name: 'a', - range: [7, 8], - loc: { - start: { line: 1, column: 7 }, - end: { line: 1, column: 8 } - } - }, - range: [5, 9], - loc: { - start: { line: 1, column: 5 }, - end: { line: 1, column: 9 } - } - }, - children: [{ - type: 'XJSExpressionContainer', - expression: { - type: 'XJSEmptyExpression', - range: [4, 4], - loc: { - start: { line: 1, column: 4 }, - end: { line: 1, column: 4 } - } - }, - range: [3, 5], - loc: { - start: { line: 1, column: 3 }, - end: { line: 1, column: 5 } - } - }], - range: [0, 9], + selfClosing: false, + attributes: [], + range: [0, 3], loc: { start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + range: [5, 9], + loc: { + start: { line: 1, column: 5 }, end: { line: 1, column: 9 } } }, + children: [{ + type: 'XJSExpressionContainer', + expression: { + type: 'XJSEmptyExpression', + range: [4, 4], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 4 } + } + }, + range: [3, 5], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 5 } + } + }], range: [0, 9], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 9 } } }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, - '{/* this is a comment */}': { - type: 'ExpressionStatement', - expression: { - type: 'XJSElement', - openingElement: { - type: 'XJSOpeningElement', - name: { - type: 'XJSIdentifier', - name: 'a', - range: [1, 2], - loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 2 } - } - }, - selfClosing: false, - attributes: [], - range: [0, 3], + '{/* this is a comment */}': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [1, 2], loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 3 } + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } } }, - closingElement: { - type: 'XJSClosingElement', - name: { - type: 'XJSIdentifier', - name: 'a', - range: [30, 31], - loc: { - start: { line: 1, column: 30 }, - end: { line: 1, column: 31 } - } - }, - range: [28, 32], - loc: { - start: { line: 1, column: 28 }, - end: { line: 1, column: 32 } - } - }, - children: [{ - type: 'XJSExpressionContainer', - expression: { - type: 'XJSEmptyExpression', - range: [4, 27], - loc: { - start: { line: 1, column: 4 }, - end: { line: 1, column: 27 } - } - }, - range: [3, 28], - loc: { - start: { line: 1, column: 3 }, - end: { line: 1, column: 28 } - } - }], - range: [0, 32], + selfClosing: false, + attributes: [], + range: [0, 3], loc: { start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [30, 31], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 31 } + } + }, + range: [28, 32], + loc: { + start: { line: 1, column: 28 }, end: { line: 1, column: 32 } } }, + children: [{ + type: 'XJSExpressionContainer', + expression: { + type: 'XJSEmptyExpression', + range: [4, 27], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 27 } + } + }, + range: [3, 28], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 28 } + } + }], range: [0, 32], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 32 } } }, + range: [0, 32], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 32 } + } + }, - '
@test content
': { - type: 'ExpressionStatement', - expression: { - type: 'XJSElement', - openingElement: { - type: 'XJSOpeningElement', - name: { - type: 'XJSIdentifier', - name: 'div', - range: [1, 4], - loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 4 } - } - }, - selfClosing: false, - attributes: [], - range: [0, 5], + '
@test content
': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [1, 4], loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 5 } + start: { line: 1, column: 1 }, + end: { line: 1, column: 4 } } }, - closingElement: { - type: 'XJSClosingElement', - name: { - type: 'XJSIdentifier', - name: 'div', - range: [20, 23], - loc: { - start: { line: 1, column: 20 }, - end: { line: 1, column: 23 } - } - }, - range: [18, 24], - loc: { - start: { line: 1, column: 18 }, - end: { line: 1, column: 24 } - } - }, - children: [{ - type: 'Literal', - value: '@test content', - raw: '@test content', - range: [5, 18], - loc: { - start: { line: 1, column: 5 }, - end: { line: 1, column: 18 } - } - }], - range: [0, 24], + selfClosing: false, + attributes: [], + range: [0, 5], loc: { start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [20, 23], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 23 } + } + }, + range: [18, 24], + loc: { + start: { line: 1, column: 18 }, end: { line: 1, column: 24 } } }, + children: [{ + type: 'Literal', + value: '@test content', + raw: '@test content', + range: [5, 18], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 18 } + } + }], range: [0, 24], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 24 } } }, + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + }, - '

7x invalid-js-identifier
': { - type: 'ExpressionStatement', - expression: { + '

7x invalid-js-identifier
': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [ + 1, + 4 + ], + loc: { + start: { + line: 1, + column: 1 + }, + end: { + line: 1, + column: 4 + } + } + }, + selfClosing: false, + attributes: [], + range: [ + 0, + 5 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 5 + } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [ + 37, + 40 + ], + loc: { + start: { + line: 1, + column: 37 + }, + end: { + line: 1, + column: 40 + } + } + }, + range: [ + 35, + 41 + ], + loc: { + start: { + line: 1, + column: 35 + }, + end: { + line: 1, + column: 41 + } + } + }, + children: [{ type: 'XJSElement', openingElement: { type: 'XJSOpeningElement', name: { type: 'XJSIdentifier', - name: 'div', + name: 'br', range: [ - 1, - 4 + 6, + 8 ], loc: { start: { line: 1, - column: 1 + column: 6 }, end: { line: 1, - column: 4 + column: 8 } } }, - selfClosing: false, + selfClosing: true, attributes: [], - range: [ - 0, - 5 - ], - loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 5 - } - } - }, - closingElement: { - type: 'XJSClosingElement', - name: { - type: 'XJSIdentifier', - name: 'div', - range: [ - 37, - 40 - ], - loc: { - start: { - line: 1, - column: 37 - }, - end: { - line: 1, - column: 40 - } - } - }, - range: [ - 35, - 41 - ], - loc: { - start: { - line: 1, - column: 35 - }, - end: { - line: 1, - column: 41 - } - } - }, - children: [{ - type: 'XJSElement', - openingElement: { - type: 'XJSOpeningElement', - name: { - type: 'XJSIdentifier', - name: 'br', - range: [ - 6, - 8 - ], - loc: { - start: { - line: 1, - column: 6 - }, - end: { - line: 1, - column: 8 - } - } - }, - selfClosing: true, - attributes: [], - range: [ - 5, - 11 - ], - loc: { - start: { - line: 1, - column: 5 - }, - end: { - line: 1, - column: 11 - } - } - }, - children: [], range: [ 5, 11 @@ -1423,40 +1404,41 @@ var fbTestFixture = { column: 11 } } - }, { - type: 'Literal', - value: '7x invalid-js-identifier', - raw: '7x invalid-js-identifier', - range: [ - 11, - 35 - ], - loc: { - start: { - line: 1, - column: 11 - }, - end: { - line: 1, - column: 35 - } - } - }], + }, + children: [], range: [ - 0, - 41 + 5, + 11 ], loc: { start: { line: 1, - column: 0 + column: 5 }, end: { line: 1, - column: 41 + column: 11 } } - }, + }, { + type: 'Literal', + value: '7x invalid-js-identifier', + raw: '7x invalid-js-identifier', + range: [ + 11, + 35 + ], + loc: { + start: { + line: 1, + column: 11 + }, + end: { + line: 1, + column: 35 + } + } + }], range: [ 0, 41 @@ -1472,93 +1454,92 @@ var fbTestFixture = { } } }, + range: [ + 0, + 41 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 41 + } + } + }, - ' right=monkeys /> gorillas />': { - "type": "ExpressionStatement", - "expression": { - "type": "XJSElement", - "openingElement": { - "type": "XJSOpeningElement", - "name": { - "type": "XJSIdentifier", - "name": "LeftRight", - "range": [ - 1, - 10 - ], - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 10 - } + ' right=monkeys /> gorillas />': { + "type": "ExpressionStatement", + "expression": { + "type": "XJSElement", + "openingElement": { + "type": "XJSOpeningElement", + "name": { + "type": "XJSIdentifier", + "name": "LeftRight", + "range": [ + 1, + 10 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 10 } - }, - "selfClosing": true, - "attributes": [ - { - "type": "XJSAttribute", - "name": { - "type": "XJSIdentifier", - "name": "left", - "range": [ - 11, - 15 - ], - "loc": { - "start": { - "line": 1, - "column": 11 - }, - "end": { - "line": 1, - "column": 15 - } + } + }, + "selfClosing": true, + "attributes": [ + { + "type": "XJSAttribute", + "name": { + "type": "XJSIdentifier", + "name": "left", + "range": [ + 11, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 15 } - }, - "value": { - "type": "XJSElement", - "openingElement": { - "type": "XJSOpeningElement", - "name": { - "type": "XJSIdentifier", - "name": "a", - "range": [ - 17, - 18 - ], - "loc": { - "start": { - "line": 1, - "column": 17 - }, - "end": { - "line": 1, - "column": 18 - } - } - }, - "selfClosing": true, - "attributes": [], + } + }, + "value": { + "type": "XJSElement", + "openingElement": { + "type": "XJSOpeningElement", + "name": { + "type": "XJSIdentifier", + "name": "a", "range": [ - 16, - 21 + 17, + 18 ], "loc": { "start": { "line": 1, - "column": 16 + "column": 17 }, "end": { "line": 1, - "column": 21 + "column": 18 } } }, - "children": [], + "selfClosing": true, + "attributes": [], "range": [ 16, 21 @@ -1574,14 +1555,15 @@ var fbTestFixture = { } } }, + "children": [], "range": [ - 11, + 16, 21 ], "loc": { "start": { "line": 1, - "column": 11 + "column": 16 }, "end": { "line": 1, @@ -1589,168 +1571,167 @@ var fbTestFixture = { } } }, - { - "type": "XJSAttribute", - "name": { - "type": "XJSIdentifier", - "name": "right", - "range": [ - 22, - 27 - ], - "loc": { - "start": { - "line": 1, - "column": 22 - }, - "end": { - "line": 1, - "column": 27 - } - } - }, - "value": { - "type": "XJSElement", - "openingElement": { - "type": "XJSOpeningElement", - "name": { - "type": "XJSIdentifier", - "name": "b", - "range": [ - 29, - 30 - ], - "loc": { - "start": { - "line": 1, - "column": 29 - }, - "end": { - "line": 1, - "column": 30 - } - } - }, - "selfClosing": false, - "attributes": [], - "range": [ - 28, - 31 - ], - "loc": { - "start": { - "line": 1, - "column": 28 - }, - "end": { - "line": 1, - "column": 31 - } - } - }, - "closingElement": { - "type": "XJSClosingElement", - "name": { - "type": "XJSIdentifier", - "name": "b", - "range": [ - 52, - 53 - ], - "loc": { - "start": { - "line": 1, - "column": 52 - }, - "end": { - "line": 1, - "column": 53 - } - } - }, - "range": [ - 50, - 54 - ], - "loc": { - "start": { - "line": 1, - "column": 50 - }, - "end": { - "line": 1, - "column": 54 - } - } - }, - "children": [ - { - "type": "Literal", - "value": "monkeys /> gorillas", - "raw": "monkeys /> gorillas", - "range": [ - 31, - 50 - ], - "loc": { - "start": { - "line": 1, - "column": 31 - }, - "end": { - "line": 1, - "column": 50 - } - } - } - ], - "range": [ - 28, - 54 - ], - "loc": { - "start": { - "line": 1, - "column": 28 - }, - "end": { - "line": 1, - "column": 54 - } - } + "range": [ + 11, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 11 }, + "end": { + "line": 1, + "column": 21 + } + } + }, + { + "type": "XJSAttribute", + "name": { + "type": "XJSIdentifier", + "name": "right", "range": [ 22, - 54 + 27 ], "loc": { "start": { "line": 1, "column": 22 }, + "end": { + "line": 1, + "column": 27 + } + } + }, + "value": { + "type": "XJSElement", + "openingElement": { + "type": "XJSOpeningElement", + "name": { + "type": "XJSIdentifier", + "name": "b", + "range": [ + 29, + 30 + ], + "loc": { + "start": { + "line": 1, + "column": 29 + }, + "end": { + "line": 1, + "column": 30 + } + } + }, + "selfClosing": false, + "attributes": [], + "range": [ + 28, + 31 + ], + "loc": { + "start": { + "line": 1, + "column": 28 + }, + "end": { + "line": 1, + "column": 31 + } + } + }, + "closingElement": { + "type": "XJSClosingElement", + "name": { + "type": "XJSIdentifier", + "name": "b", + "range": [ + 52, + 53 + ], + "loc": { + "start": { + "line": 1, + "column": 52 + }, + "end": { + "line": 1, + "column": 53 + } + } + }, + "range": [ + 50, + 54 + ], + "loc": { + "start": { + "line": 1, + "column": 50 + }, + "end": { + "line": 1, + "column": 54 + } + } + }, + "children": [ + { + "type": "Literal", + "value": "monkeys /> gorillas", + "raw": "monkeys /> gorillas", + "range": [ + 31, + 50 + ], + "loc": { + "start": { + "line": 1, + "column": 31 + }, + "end": { + "line": 1, + "column": 50 + } + } + } + ], + "range": [ + 28, + 54 + ], + "loc": { + "start": { + "line": 1, + "column": 28 + }, "end": { "line": 1, "column": 54 } } - } - ], - "range": [ - 0, - 57 - ], - "loc": { - "start": { - "line": 1, - "column": 0 }, - "end": { - "line": 1, - "column": 57 + "range": [ + 22, + 54 + ], + "loc": { + "start": { + "line": 1, + "column": 22 + }, + "end": { + "line": 1, + "column": 54 + } } } - }, - "children": [], + ], "range": [ 0, 57 @@ -1766,6 +1747,7 @@ var fbTestFixture = { } } }, + "children": [], "range": [ 0, 57 @@ -1781,14 +1763,119 @@ var fbTestFixture = { } } }, + "range": [ + 0, + 57 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 57 + } + } + }, - '': { - type: 'ExpressionStatement', - expression: { - type: 'XJSElement', - openingElement: { - type: 'XJSOpeningElement', - name: { + '': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSMemberExpression', + object: { + type: 'XJSIdentifier', + name: 'a', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + property: { + type: 'XJSIdentifier', + name: 'b', + range: [3, 4], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + range: [1, 4], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 4 } + } + }, + selfClosing: false, + attributes: [], + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSMemberExpression', + object: { + type: 'XJSIdentifier', + name: 'a', + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + property: { + type: 'XJSIdentifier', + name: 'b', + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + range: [7, 10], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 10 } + } + }, + range: [5, 11], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 11 } + } + }, + children: [], + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + + '': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSMemberExpression', + object: { type: 'XJSMemberExpression', object: { type: 'XJSIdentifier', @@ -1814,247 +1901,156 @@ var fbTestFixture = { end: { line: 1, column: 4 } } }, - selfClosing: false, - attributes: [], - range: [0, 5], + property: { + type: 'XJSIdentifier', + name: 'c', + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [1, 6], loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 5 } + start: { line: 1, column: 1 }, + end: { line: 1, column: 6 } } }, - closingElement: { - type: 'XJSClosingElement', - name: { + selfClosing: false, + attributes: [], + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSMemberExpression', + object: { type: 'XJSMemberExpression', object: { type: 'XJSIdentifier', name: 'a', - range: [7, 8], - loc: { - start: { line: 1, column: 7 }, - end: { line: 1, column: 8 } - } - }, - property: { - type: 'XJSIdentifier', - name: 'b', range: [9, 10], loc: { start: { line: 1, column: 9 }, end: { line: 1, column: 10 } } }, - range: [7, 10], - loc: { - start: { line: 1, column: 7 }, - end: { line: 1, column: 10 } - } - }, - range: [5, 11], - loc: { - start: { line: 1, column: 5 }, - end: { line: 1, column: 11 } - } - }, - children: [], - range: [0, 11], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 11 } - } - }, - range: [0, 11], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 11 } - } - }, - - '': { - type: 'ExpressionStatement', - expression: { - type: 'XJSElement', - openingElement: { - type: 'XJSOpeningElement', - name: { - type: 'XJSMemberExpression', - object: { - type: 'XJSMemberExpression', - object: { - type: 'XJSIdentifier', - name: 'a', - range: [1, 2], - loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 2 } - } - }, - property: { - type: 'XJSIdentifier', - name: 'b', - range: [3, 4], - loc: { - start: { line: 1, column: 3 }, - end: { line: 1, column: 4 } - } - }, - range: [1, 4], - loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 4 } - } - }, property: { type: 'XJSIdentifier', - name: 'c', - range: [5, 6], + name: 'b', + range: [11, 12], loc: { - start: { line: 1, column: 5 }, - end: { line: 1, column: 6 } - } - }, - range: [1, 6], - loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 6 } - } - }, - selfClosing: false, - attributes: [], - range: [0, 7], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 7 } - } - }, - closingElement: { - type: 'XJSClosingElement', - name: { - type: 'XJSMemberExpression', - object: { - type: 'XJSMemberExpression', - object: { - type: 'XJSIdentifier', - name: 'a', - range: [9, 10], - loc: { - start: { line: 1, column: 9 }, - end: { line: 1, column: 10 } - } - }, - property: { - type: 'XJSIdentifier', - name: 'b', - range: [11, 12], - loc: { - start: { line: 1, column: 11 }, - end: { line: 1, column: 12 } - } - }, - range: [9, 12], - loc: { - start: { line: 1, column: 9 }, + start: { line: 1, column: 11 }, end: { line: 1, column: 12 } } }, - property: { - type: 'XJSIdentifier', - name: 'c', - range: [13, 14], - loc: { - start: { line: 1, column: 13 }, - end: { line: 1, column: 14 } - } - }, - range: [9, 14], + range: [9, 12], loc: { start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + property: { + type: 'XJSIdentifier', + name: 'c', + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, end: { line: 1, column: 14 } } }, - range: [7, 15], + range: [9, 14], loc: { - start: { line: 1, column: 7 }, - end: { line: 1, column: 15 } + start: { line: 1, column: 9 }, + end: { line: 1, column: 14 } } }, - children: [], - range: [0, 15], + range: [7, 15], loc: { - start: { line: 1, column: 0 }, + start: { line: 1, column: 7 }, end: { line: 1, column: 15 } } }, + children: [], range: [0, 15], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 15 } } }, + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, - // In order to more useful parse errors, we disallow following an - // XJSElement by a less-than symbol. In the rare case that the binary - // operator was intended, the tag can be wrapped in parentheses: - '(
) < x;': { - type: 'ExpressionStatement', - expression: { - type: 'BinaryExpression', - operator: '<', - left: { - type: 'XJSElement', - openingElement: { - type: 'XJSOpeningElement', - name: { - type: 'XJSIdentifier', - name: 'div', - range: [2, 5], - loc: { - start: { line: 1, column: 2 }, - end: { line: 1, column: 5 } - } - }, - selfClosing: true, - attributes: [], - range: [1, 8], + // In order to more useful parse errors, we disallow following an + // XJSElement by a less-than symbol. In the rare case that the binary + // operator was intended, the tag can be wrapped in parentheses: + '(
) < x;': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '<', + left: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [2, 5], loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 8 } + start: { line: 1, column: 2 }, + end: { line: 1, column: 5 } } }, - children: [], - range: [0, 9], + selfClosing: true, + attributes: [], + range: [1, 8], loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 9 } + start: { line: 1, column: 1 }, + end: { line: 1, column: 8 } } }, - right: { - type: 'Identifier', - name: 'x', - range: [12, 13], - loc: { - start: { line: 1, column: 12 }, - end: { line: 1, column: 13 } - } - }, - range: [0, 13], + children: [], + range: [0, 9], loc: { start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + right: { + type: 'Identifier', + name: 'x', + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, end: { line: 1, column: 13 } } }, - range: [0, 14], + range: [0, 13], loc: { start: { line: 1, column: 0 }, - end: { line: 1, column: 14 } + end: { line: 1, column: 13 } } + }, + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } } } }; -for (var code in fbTestFixture.XJS) { +for (var code in fbTestFixture) { test(code, { type: 'Program', - body: [fbTestFixture.XJS[code]] + body: [fbTestFixture[code]] }, {locations: true, ranges: true}); } \ No newline at end of file From fe6cafa1418f24c5fb1c3a3812214c5c312010e1 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 11 Jul 2014 02:00:53 +0300 Subject: [PATCH 016/198] Upgrade esprima to esprima-fb and update docs. Conflicts: test/compare/esprima.js --- README.md | 14 +- test/compare/esprima.js | 1232 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 1169 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index b1d822faf0..857158f7bb 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,18 @@ This is modification of [Acorn][acorn] - a tiny, fast JavaScript parser, written completely in JavaScript. -It was forked to create experimental, alternative, faster [React.js JSX][jsx] parser since, according to -[benchmarks](http://marijnhaverbeke.nl/acorn/test/bench.html), Acorn is 5x faster than Esprima when parsing code -with location tracking (call it "source maps enabled mode"), and JSX extensions almost don't affect those numbers. +It was forked to create experimental, alternative, faster [React.js JSX][jsx] parser by integrating pieces +of code from official parser, modified to match Acorn's parsing logic. -This parser was created by integrating pieces of code from official parser, modified to match Acorn's parsing logic. +According to [benchmarks](http://marijnhaverbeke.nl/acorn/test/bench.html), Acorn is 5x faster than Esprima +when parsing code with location tracking (call it "source maps enabled mode"), and JSX extensions almost don't +affect those numbers. However, [esprima-fb](https://github.com/facebook/esprima) is forked&maintained from +harmony branch of esprima which is being heavily optimized and currently `acorn-jsx` is only 1.5-2x faster than +`esprima-fb`. Currently, it consumes all the ES5+JSX syntax that can be consumed by official [Esprima-based parser][esprima-fb]. -However, official parser can consume ES6 syntax as well, and is maintained by authors of React.js itself, so it's preferred to be used in real projects. +However, official parser can consume ES6 syntax as well, and is maintained by authors of React.js itself, so it's +preferred to be used in real projects. [acorn]: http://marijnhaverbeke.nl/acorn/ [esprima-fb]: https://github.com/facebook/esprima diff --git a/test/compare/esprima.js b/test/compare/esprima.js index 7913c5224b..fa1dac5fff 100644 --- a/test/compare/esprima.js +++ b/test/compare/esprima.js @@ -42,6 +42,10 @@ parseImportSpecifier: true, parseLeftHandSideExpression: true, parseParams: true, validateParam: true, parseSpreadOrAssignmentExpression: true, parseStatement: true, parseSourceElement: true, parseModuleBlock: true, parseConciseBody: true, +advanceXJSChild: true, isXJSIdentifierStart: true, isXJSIdentifierPart: true, +scanXJSStringLiteral: true, scanXJSIdentifier: true, +parseXJSAttributeValue: true, parseXJSChild: true, parseXJSElement: true, parseXJSExpressionContainer: true, parseXJSEmptyExpression: true, +parseTypeAnnotation: true, parseTypeAnnotatableIdentifier: true, parseYieldExpression: true */ @@ -68,6 +72,7 @@ parseYieldExpression: true Messages, Regex, SyntaxTreeDelegate, + XHTMLEntities, ClassPropertyType, source, strict, @@ -90,7 +95,9 @@ parseYieldExpression: true Punctuator: 7, StringLiteral: 8, RegularExpression: 9, - Template: 10 + Template: 10, + XJSIdentifier: 11, + XJSText: 12 }; TokenName = {}; @@ -102,6 +109,8 @@ parseYieldExpression: true TokenName[Token.NumericLiteral] = 'Numeric'; TokenName[Token.Punctuator] = 'Punctuator'; TokenName[Token.StringLiteral] = 'String'; + TokenName[Token.XJSIdentifier] = 'XJSIdentifier'; + TokenName[Token.XJSText] = 'XJSText'; TokenName[Token.RegularExpression] = 'RegularExpression'; // A function following one of those tokens is an expression. @@ -128,6 +137,7 @@ parseYieldExpression: true ClassBody: 'ClassBody', ClassDeclaration: 'ClassDeclaration', ClassExpression: 'ClassExpression', + ClassProperty: 'ClassProperty', ComprehensionBlock: 'ComprehensionBlock', ComprehensionExpression: 'ComprehensionExpression', ConditionalExpression: 'ConditionalExpression', @@ -157,11 +167,16 @@ parseYieldExpression: true NewExpression: 'NewExpression', ObjectExpression: 'ObjectExpression', ObjectPattern: 'ObjectPattern', + ObjectTypeAnnotation: 'ObjectTypeAnnotation', + OptionalParameter: 'OptionalParameter', + ParametricTypeAnnotation: 'ParametricTypeAnnotation', + ParametricallyTypedIdentifier: 'ParametricallyTypedIdentifier', Program: 'Program', Property: 'Property', ReturnStatement: 'ReturnStatement', SequenceExpression: 'SequenceExpression', SpreadElement: 'SpreadElement', + SpreadProperty: 'SpreadProperty', SwitchCase: 'SwitchCase', SwitchStatement: 'SwitchStatement', TaggedTemplateExpression: 'TaggedTemplateExpression', @@ -170,12 +185,26 @@ parseYieldExpression: true ThisExpression: 'ThisExpression', ThrowStatement: 'ThrowStatement', TryStatement: 'TryStatement', + TypeAnnotatedIdentifier: 'TypeAnnotatedIdentifier', + TypeAnnotation: 'TypeAnnotation', UnaryExpression: 'UnaryExpression', UpdateExpression: 'UpdateExpression', VariableDeclaration: 'VariableDeclaration', VariableDeclarator: 'VariableDeclarator', + VoidTypeAnnotation: 'VoidTypeAnnotation', WhileStatement: 'WhileStatement', WithStatement: 'WithStatement', + XJSIdentifier: 'XJSIdentifier', + XJSNamespacedName: 'XJSNamespacedName', + XJSMemberExpression: 'XJSMemberExpression', + XJSEmptyExpression: 'XJSEmptyExpression', + XJSExpressionContainer: 'XJSExpressionContainer', + XJSElement: 'XJSElement', + XJSClosingElement: 'XJSClosingElement', + XJSOpeningElement: 'XJSOpeningElement', + XJSAttribute: 'XJSAttribute', + XJSSpreadAttribute: 'XJSSpreadAttribute', + XJSText: 'XJSText', YieldExpression: 'YieldExpression' }; @@ -223,6 +252,7 @@ parseYieldExpression: true ParameterAfterRestParameter: 'Rest parameter must be final parameter of an argument list', DefaultRestParameter: 'Rest parameter can not have a default value', ElementAfterSpreadElement: 'Spread must be the final element of an element list', + PropertyAfterSpreadProperty: 'A rest property must be the final property of an object literal', ObjectPatternAsRestParameter: 'Invalid rest parameter', ObjectPatternAsSpread: 'Invalid spread argument', StrictFunctionName: 'Function name may not be eval or arguments in strict mode', @@ -242,7 +272,10 @@ parseYieldExpression: true NoUnintializedConst: 'Const must be initialized', ComprehensionRequiresBlock: 'Comprehension must have at least one block', ComprehensionError: 'Comprehension Error', - EachNotAllowed: 'Each is not supported' + EachNotAllowed: 'Each is not supported', + InvalidXJSAttributeValue: 'XJS value should be either an expression or a quoted XJS text', + ExpectedXJSClosingTag: 'Expected corresponding XJS closing tag for %0', + AdjacentXJSElements: 'Adjacent XJS elements must be wrapped in an enclosing tag' }; // See also tools/generate-unicode-regex.py. @@ -1409,7 +1442,9 @@ parseYieldExpression: true function advance() { var ch; - skipComment(); + if (!state.inXJSChild) { + skipComment(); + } if (index >= length) { return { @@ -1420,6 +1455,10 @@ parseYieldExpression: true }; } + if (state.inXJSChild) { + return advanceXJSChild(); + } + ch = source.charCodeAt(index); // Very common: ( and ) and ; @@ -1429,9 +1468,16 @@ parseYieldExpression: true // String literal starts with single quote (#39) or double quote (#34). if (ch === 39 || ch === 34) { + if (state.inXJSTag) { + return scanXJSStringLiteral(); + } return scanStringLiteral(); } + if (state.inXJSTag && isXJSIdentifierStart(ch)) { + return scanXJSIdentifier(); + } + if (ch === 96) { return scanTemplate(); } @@ -1524,6 +1570,13 @@ parseYieldExpression: true return {offset: index, line: lineNumber, col: index - lineStart}; } + function markerCreatePreserveWhitespace() { + if (!extra.loc && !extra.range) { + return undefined; + } + return {offset: index, line: lineNumber, col: index - lineStart}; + } + function markerApply(marker, node) { if (extra.range) { node.range = [marker.offset, index]; @@ -1681,7 +1734,8 @@ parseYieldExpression: true }; }, - createFunctionDeclaration: function (id, params, defaults, body, rest, generator, expression) { + createFunctionDeclaration: function (id, params, defaults, body, rest, generator, expression, + returnType, parametricType) { return { type: Syntax.FunctionDeclaration, id: id, @@ -1690,11 +1744,14 @@ parseYieldExpression: true body: body, rest: rest, generator: generator, - expression: expression + expression: expression, + returnType: returnType, + parametricType: parametricType }; }, - createFunctionExpression: function (id, params, defaults, body, rest, generator, expression) { + createFunctionExpression: function (id, params, defaults, body, rest, generator, expression, + returnType, parametricType) { return { type: Syntax.FunctionExpression, id: id, @@ -1703,13 +1760,143 @@ parseYieldExpression: true body: body, rest: rest, generator: generator, - expression: expression + expression: expression, + returnType: returnType, + parametricType: parametricType }; }, createIdentifier: function (name) { return { type: Syntax.Identifier, + name: name, + // Only here to initialize the shape of the object to ensure + // that the 'typeAnnotation' key is ordered before others that + // are added later (like 'loc' and 'range'). This just helps + // keep the shape of Identifier nodes consistent with everything + // else. + typeAnnotation: undefined + }; + }, + + createTypeAnnotation: function (typeIdentifier, parametricType, params, returnType, nullable) { + return { + type: Syntax.TypeAnnotation, + id: typeIdentifier, + parametricType: parametricType, + params: params, + returnType: returnType, + nullable: nullable + }; + }, + + createParametricTypeAnnotation: function (parametricTypes) { + return { + type: Syntax.ParametricTypeAnnotation, + params: parametricTypes + }; + }, + + createVoidTypeAnnotation: function () { + return { + type: Syntax.VoidTypeAnnotation + }; + }, + + createObjectTypeAnnotation: function (properties) { + return { + type: Syntax.ObjectTypeAnnotation, + properties: properties + }; + }, + + createTypeAnnotatedIdentifier: function (identifier, annotation, isOptionalParam) { + return { + type: Syntax.TypeAnnotatedIdentifier, + id: identifier, + annotation: annotation + }; + }, + + createOptionalParameter: function (identifier) { + return { + type: Syntax.OptionalParameter, + id: identifier + }; + }, + + createXJSAttribute: function (name, value) { + return { + type: Syntax.XJSAttribute, + name: name, + value: value + }; + }, + + createXJSSpreadAttribute: function (argument) { + return { + type: Syntax.XJSSpreadAttribute, + argument: argument + }; + }, + + createXJSIdentifier: function (name) { + return { + type: Syntax.XJSIdentifier, + name: name + }; + }, + + createXJSNamespacedName: function (namespace, name) { + return { + type: Syntax.XJSNamespacedName, + namespace: namespace, + name: name + }; + }, + + createXJSMemberExpression: function (object, property) { + return { + type: Syntax.XJSMemberExpression, + object: object, + property: property + }; + }, + + createXJSElement: function (openingElement, closingElement, children) { + return { + type: Syntax.XJSElement, + openingElement: openingElement, + closingElement: closingElement, + children: children + }; + }, + + createXJSEmptyExpression: function () { + return { + type: Syntax.XJSEmptyExpression + }; + }, + + createXJSExpressionContainer: function (expression) { + return { + type: Syntax.XJSExpressionContainer, + expression: expression + }; + }, + + createXJSOpeningElement: function (name, attributes, selfClosing) { + return { + type: Syntax.XJSOpeningElement, + name: name, + selfClosing: selfClosing, + attributes: attributes + }; + }, + + createXJSClosingElement: function (name) { + return { + type: Syntax.XJSClosingElement, name: name }; }, @@ -1916,6 +2103,13 @@ parseYieldExpression: true }; }, + createSpreadProperty: function (argument) { + return { + type: Syntax.SpreadProperty, + argument: argument + }; + }, + createTaggedTemplateExpression: function (tag, quasi) { return { type: Syntax.TaggedTemplateExpression, @@ -1947,6 +2141,13 @@ parseYieldExpression: true }; }, + createClassProperty: function (propertyIdentifier) { + return { + type: Syntax.ClassProperty, + id: propertyIdentifier + }; + }, + createClassBody: function (body) { return { type: Syntax.ClassBody, @@ -1954,21 +2155,24 @@ parseYieldExpression: true }; }, - createClassExpression: function (id, superClass, body) { + createClassExpression: function (id, superClass, body, parametricType) { return { type: Syntax.ClassExpression, id: id, superClass: superClass, - body: body + body: body, + parametricType: parametricType }; }, - createClassDeclaration: function (id, superClass, body) { + createClassDeclaration: function (id, superClass, body, parametricType, superParametricType) { return { type: Syntax.ClassDeclaration, id: id, superClass: superClass, - body: body + body: body, + parametricType: parametricType, + superParametricType: superParametricType }; }, @@ -2110,7 +2314,7 @@ parseYieldExpression: true throwError(token, Messages.UnexpectedNumber); } - if (token.type === Token.StringLiteral) { + if (token.type === Token.StringLiteral || token.type === Token.XJSText) { throwError(token, Messages.UnexpectedString); } @@ -2323,7 +2527,9 @@ parseYieldExpression: true body, options.rest || null, options.generator, - body.type !== Syntax.BlockStatement + body.type !== Syntax.BlockStatement, + options.returnType, + options.parametricType )); } @@ -2345,7 +2551,9 @@ parseYieldExpression: true params: tmp.params, defaults: tmp.defaults, rest: tmp.rest, - generator: options.generator + generator: options.generator, + returnType: tmp.returnType, + parametricType: options.parametricType }); strict = previousStrict; @@ -2408,7 +2616,7 @@ parseYieldExpression: true key = parseObjectPropertyKey(); expect('('); token = lookahead; - param = [ parseVariableIdentifier() ]; + param = [ parseTypeAnnotatableIdentifier() ]; expect(')'); return markerApply(marker, delegate.createProperty('set', key, parsePropertyFunction({ params: param, generator: false, name: token }), false, false, computed)); } @@ -2452,6 +2660,12 @@ parseYieldExpression: true throwUnexpected(lex()); } + function parseObjectSpreadProperty() { + var marker = markerCreate(); + expect('...'); + return markerApply(marker, delegate.createSpreadProperty(parseAssignmentExpression())); + } + function parseObjectInitialiser() { var properties = [], property, name, key, kind, map = {}, toString = String, marker = markerCreate(); @@ -2459,33 +2673,37 @@ parseYieldExpression: true expect('{'); while (!match('}')) { - property = parseObjectProperty(); - - if (property.key.type === Syntax.Identifier) { - name = property.key.name; + if (match('...')) { + property = parseObjectSpreadProperty(); } else { - name = toString(property.key.value); - } - kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set; + property = parseObjectProperty(); - key = '$' + name; - if (Object.prototype.hasOwnProperty.call(map, key)) { - if (map[key] === PropertyKind.Data) { - if (strict && kind === PropertyKind.Data) { - throwErrorTolerant({}, Messages.StrictDuplicateProperty); - } else if (kind !== PropertyKind.Data) { - throwErrorTolerant({}, Messages.AccessorDataProperty); - } + if (property.key.type === Syntax.Identifier) { + name = property.key.name; } else { - if (kind === PropertyKind.Data) { - throwErrorTolerant({}, Messages.AccessorDataProperty); - } else if (map[key] & kind) { - throwErrorTolerant({}, Messages.AccessorGetSet); - } + name = toString(property.key.value); + } + kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set; + + key = '$' + name; + if (Object.prototype.hasOwnProperty.call(map, key)) { + if (map[key] === PropertyKind.Data) { + if (strict && kind === PropertyKind.Data) { + throwErrorTolerant({}, Messages.StrictDuplicateProperty); + } else if (kind !== PropertyKind.Data) { + throwErrorTolerant({}, Messages.AccessorDataProperty); + } + } else { + if (kind === PropertyKind.Data) { + throwErrorTolerant({}, Messages.AccessorDataProperty); + } else if (map[key] & kind) { + throwErrorTolerant({}, Messages.AccessorGetSet); + } + } + map[key] |= kind; + } else { + map[key] = kind; } - map[key] |= kind; - } else { - map[key] = kind; } properties.push(property); @@ -2619,6 +2837,10 @@ parseYieldExpression: true return parseTemplateLiteral(); } + if (match('<')) { + return parseXJSElement(); + } + throwUnexpected(lex()); } @@ -2983,10 +3205,17 @@ parseYieldExpression: true expr.type = Syntax.ObjectPattern; for (i = 0, len = expr.properties.length; i < len; i += 1) { property = expr.properties[i]; - if (property.kind !== 'init') { - throwError({}, Messages.InvalidLHSInAssignment); + if (property.type === Syntax.SpreadProperty) { + if (i < len - 1) { + throwError({}, Messages.PropertyAfterSpreadProperty); + } + reinterpretAsAssignmentBindingPattern(property.argument); + } else { + if (property.kind !== 'init') { + throwError({}, Messages.InvalidLHSInAssignment); + } + reinterpretAsAssignmentBindingPattern(property.value); } - reinterpretAsAssignmentBindingPattern(property.value); } } else if (expr.type === Syntax.ArrayExpression) { expr.type = Syntax.ArrayPattern; @@ -3020,10 +3249,17 @@ parseYieldExpression: true expr.type = Syntax.ObjectPattern; for (i = 0, len = expr.properties.length; i < len; i += 1) { property = expr.properties[i]; - if (property.kind !== 'init') { - throwError({}, Messages.InvalidLHSInFormalsList); + if (property.type === Syntax.SpreadProperty) { + if (i < len - 1) { + throwError({}, Messages.PropertyAfterSpreadProperty); + } + reinterpretAsDestructuredParameter(options, property.argument); + } else { + if (property.kind !== 'init') { + throwError({}, Messages.InvalidLHSInFormalsList); + } + reinterpretAsDestructuredParameter(options, property.value); } - reinterpretAsDestructuredParameter(options, property.value); } } else if (expr.type === Syntax.ArrayExpression) { expr.type = Syntax.ArrayPattern; @@ -3273,6 +3509,120 @@ parseYieldExpression: true // 12.2 Variable Statement + function parseObjectTypeAnnotation() { + var isMethod, marker, properties = [], property, propertyKey, + propertyTypeAnnotation; + + expect('{'); + + while (!match('}')) { + marker = markerCreate(); + propertyKey = parseObjectPropertyKey(); + isMethod = match('('); + propertyTypeAnnotation = parseTypeAnnotation(); + properties.push(markerApply(marker, delegate.createProperty( + 'init', + propertyKey, + propertyTypeAnnotation, + isMethod, + false + ))); + + if (!match('}')) { + if (match(',') || match(';')) { + lex(); + } else { + throwUnexpected(lookahead); + } + } + } + + expect('}'); + + return delegate.createObjectTypeAnnotation(properties); + } + + function parseVoidTypeAnnotation() { + var marker = markerCreate(); + expectKeyword('void'); + return markerApply(marker, delegate.createVoidTypeAnnotation()); + } + + function parseParametricTypeAnnotation() { + var marker = markerCreate(), typeIdentifier, paramTypes = []; + + expect('<'); + while (!match('>')) { + paramTypes.push(parseVariableIdentifier()); + if (!match('>')) { + expect(','); + } + } + expect('>'); + + return markerApply(marker, delegate.createParametricTypeAnnotation( + paramTypes + )); + } + + function parseTypeAnnotation(dontExpectColon) { + var typeIdentifier = null, params = null, returnType = null, + nullable = false, marker = markerCreate(), returnTypeMarker = null, + parametricType, annotation; + + if (!dontExpectColon) { + expect(':'); + } + + if (match('{')) { + return markerApply(marker, parseObjectTypeAnnotation()); + } + + if (match('?')) { + lex(); + nullable = true; + } + + if (lookahead.type === Token.Identifier) { + typeIdentifier = parseVariableIdentifier(); + if (match('<')) { + parametricType = parseParametricTypeAnnotation(); + } + } else if (match('(')) { + lex(); + params = []; + while (lookahead.type === Token.Identifier || match('?')) { + params.push(parseTypeAnnotatableIdentifier( + true, /* requireTypeAnnotation */ + true /* canBeOptionalParam */ + )); + if (!match(')')) { + expect(','); + } + } + expect(')'); + + returnTypeMarker = markerCreate(); + expect('=>'); + + returnType = parseTypeAnnotation(true); + } else { + if (!matchKeyword('void')) { + throwUnexpected(lookahead); + } else { + return parseVoidTypeAnnotation(); + } + } + + return markerApply(marker, delegate.createTypeAnnotation( + typeIdentifier, + parametricType, + params, + returnType, + nullable + )); + } + function parseVariableIdentifier() { var marker = markerCreate(), token = lex(); @@ -3284,6 +3634,30 @@ parseYieldExpression: true return markerApply(marker, delegate.createIdentifier(token.value)); } + function parseTypeAnnotatableIdentifier(requireTypeAnnotation, canBeOptionalParam) { + var marker = markerCreate(), + ident = parseVariableIdentifier(), + isOptionalParam = false; + + if (canBeOptionalParam && match('?')) { + expect('?'); + isOptionalParam = true; + } + + if (requireTypeAnnotation || match(':')) { + ident = markerApply(marker, delegate.createTypeAnnotatedIdentifier( + ident, + parseTypeAnnotation() + )); + } + + if (isOptionalParam) { + ident = markerApply(marker, delegate.createOptionalParameter(ident)); + } + + return ident; + } + function parseVariableDeclaration(kind) { var id, marker = markerCreate(), @@ -3295,7 +3669,7 @@ parseYieldExpression: true id = parseArrayInitialiser(); reinterpretAsAssignmentBindingPattern(id); } else { - id = state.allowKeyword ? parseNonComputedProperty() : parseVariableIdentifier(); + id = state.allowKeyword ? parseNonComputedProperty() : parseTypeAnnotatableIdentifier(); // 12.2.1 if (strict && isRestrictedWord(id.name)) { throwErrorTolerant({}, Messages.StrictVarName); @@ -4207,7 +4581,15 @@ parseYieldExpression: true param = parseObjectInitialiser(); reinterpretAsDestructuredParameter(options, param); } else { - param = parseVariableIdentifier(); + // Typing rest params is awkward, so punting on that for now + param = + rest + ? parseVariableIdentifier() + : parseTypeAnnotatableIdentifier( + false, /* requireTypeAnnotation */ + true /* canBeOptionalParam */ + ); + validateParam(options, token, token.value); } @@ -4262,12 +4644,16 @@ parseYieldExpression: true options.defaults = []; } + if (match(':')) { + options.returnType = parseTypeAnnotation(); + } + return markerApply(marker, options); } function parseFunctionDeclaration() { var id, body, token, tmp, firstRestricted, message, previousStrict, previousYieldAllowed, generator, - marker = markerCreate(); + marker = markerCreate(), parametricType; expectKeyword('function'); @@ -4281,6 +4667,10 @@ parseYieldExpression: true id = parseVariableIdentifier(); + if (match('<')) { + parametricType = parseParametricTypeAnnotation(); + } + if (strict) { if (isRestrictedWord(token.value)) { throwErrorTolerant(token, Messages.StrictFunctionName); @@ -4316,12 +4706,13 @@ parseYieldExpression: true strict = previousStrict; state.yieldAllowed = previousYieldAllowed; - return markerApply(marker, delegate.createFunctionDeclaration(id, tmp.params, tmp.defaults, body, tmp.rest, generator, false)); + return markerApply(marker, delegate.createFunctionDeclaration(id, tmp.params, tmp.defaults, body, tmp.rest, generator, false, + tmp.returnType, parametricType)); } function parseFunctionExpression() { var token, id = null, firstRestricted, message, tmp, body, previousStrict, previousYieldAllowed, generator, - marker = markerCreate(); + marker = markerCreate(), parametricType; expectKeyword('function'); @@ -4333,21 +4724,28 @@ parseYieldExpression: true } if (!match('(')) { - token = lookahead; - id = parseVariableIdentifier(); - if (strict) { - if (isRestrictedWord(token.value)) { - throwErrorTolerant(token, Messages.StrictFunctionName); - } - } else { - if (isRestrictedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictFunctionName; - } else if (isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = Messages.StrictReservedWord; + if (!match('<')) { + token = lookahead; + id = parseVariableIdentifier(); + + if (strict) { + if (isRestrictedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } } } + + if (match('<')) { + parametricType = parseParametricTypeAnnotation(); + } } tmp = parseParams(firstRestricted); @@ -4371,7 +4769,8 @@ parseYieldExpression: true strict = previousStrict; state.yieldAllowed = previousYieldAllowed; - return markerApply(marker, delegate.createFunctionExpression(id, tmp.params, tmp.defaults, body, tmp.rest, generator, false)); + return markerApply(marker, delegate.createFunctionExpression(id, tmp.params, tmp.defaults, body, tmp.rest, generator, false, + tmp.returnType, parametricType)); } function parseYieldExpression() { @@ -4399,7 +4798,8 @@ parseYieldExpression: true function parseMethodDefinition(existingPropNames) { var token, key, param, propType, isValidDuplicateProp = false, - marker = markerCreate(); + marker = markerCreate(), token2, parametricType, + parametricTypeMarker, annotationMarker; if (lookahead.value === 'static') { propType = ClassPropertyType.static; @@ -4419,6 +4819,7 @@ parseYieldExpression: true } token = lookahead; + //parametricTypeMarker = markerCreate(); key = parseObjectPropertyKey(); if (token.value === 'get' && !match('(')) { @@ -4474,7 +4875,7 @@ parseYieldExpression: true expect('('); token = lookahead; - param = [ parseVariableIdentifier() ]; + param = [ parseTypeAnnotatableIdentifier() ]; expect(')'); return markerApply(marker, delegate.createMethodDefinition( propType, @@ -4484,6 +4885,10 @@ parseYieldExpression: true )); } + if (match('<')) { + parametricType = parseParametricTypeAnnotation(); + } + // It is a syntax error if any other properties have the same name as a // non-getter, non-setter method if (existingPropNames[propType].hasOwnProperty(key.name)) { @@ -4497,7 +4902,21 @@ parseYieldExpression: true propType, '', key, - parsePropertyMethodFunction({ generator: false }) + parsePropertyMethodFunction({ + generator: false, + parametricType: parametricType + }) + )); + } + + function parseClassProperty(existingPropNames) { + var marker = markerCreate(), propertyIdentifier; + + propertyIdentifier = parseTypeAnnotatableIdentifier(); + expect(';'); + + return markerApply(marker, delegate.createClassProperty( + propertyIdentifier )); } @@ -4506,6 +4925,14 @@ parseYieldExpression: true lex(); return; } + + var doubleLookahead = lookahead2(); + if (doubleLookahead.type === Token.Punctuator) { + if (doubleLookahead.value === ':') { + return parseClassProperty(existingProps); + } + } + return parseMethodDefinition(existingProps); } @@ -4534,7 +4961,8 @@ parseYieldExpression: true } function parseClassExpression() { - var id, previousYieldAllowed, superClass = null, marker = markerCreate(); + var id, previousYieldAllowed, superClass = null, marker = markerCreate(), + parametricType; expectKeyword('class'); @@ -4542,6 +4970,10 @@ parseYieldExpression: true id = parseVariableIdentifier(); } + if (match('<')) { + parametricType = parseParametricTypeAnnotation(); + } + if (matchKeyword('extends')) { expectKeyword('extends'); previousYieldAllowed = state.yieldAllowed; @@ -4550,16 +4982,21 @@ parseYieldExpression: true state.yieldAllowed = previousYieldAllowed; } - return markerApply(marker, delegate.createClassExpression(id, superClass, parseClassBody())); + return markerApply(marker, delegate.createClassExpression(id, superClass, parseClassBody(), parametricType)); } function parseClassDeclaration() { - var id, previousYieldAllowed, superClass = null, marker = markerCreate(); + var id, previousYieldAllowed, superClass = null, marker = markerCreate(), + parametricType, superParametricType; expectKeyword('class'); id = parseVariableIdentifier(); + if (match('<')) { + parametricType = parseParametricTypeAnnotation(); + } + if (matchKeyword('extends')) { expectKeyword('extends'); previousYieldAllowed = state.yieldAllowed; @@ -4568,7 +5005,7 @@ parseYieldExpression: true state.yieldAllowed = previousYieldAllowed; } - return markerApply(marker, delegate.createClassDeclaration(id, superClass, parseClassBody())); + return markerApply(marker, delegate.createClassDeclaration(id, superClass, parseClassBody(), parametricType, superParametricType)); } // 15 Program @@ -4857,10 +5294,659 @@ parseYieldExpression: true } } + // 16 XJS + + XHTMLEntities = { + quot: '\u0022', + amp: '&', + apos: '\u0027', + lt: '<', + gt: '>', + nbsp: '\u00A0', + iexcl: '\u00A1', + cent: '\u00A2', + pound: '\u00A3', + curren: '\u00A4', + yen: '\u00A5', + brvbar: '\u00A6', + sect: '\u00A7', + uml: '\u00A8', + copy: '\u00A9', + ordf: '\u00AA', + laquo: '\u00AB', + not: '\u00AC', + shy: '\u00AD', + reg: '\u00AE', + macr: '\u00AF', + deg: '\u00B0', + plusmn: '\u00B1', + sup2: '\u00B2', + sup3: '\u00B3', + acute: '\u00B4', + micro: '\u00B5', + para: '\u00B6', + middot: '\u00B7', + cedil: '\u00B8', + sup1: '\u00B9', + ordm: '\u00BA', + raquo: '\u00BB', + frac14: '\u00BC', + frac12: '\u00BD', + frac34: '\u00BE', + iquest: '\u00BF', + Agrave: '\u00C0', + Aacute: '\u00C1', + Acirc: '\u00C2', + Atilde: '\u00C3', + Auml: '\u00C4', + Aring: '\u00C5', + AElig: '\u00C6', + Ccedil: '\u00C7', + Egrave: '\u00C8', + Eacute: '\u00C9', + Ecirc: '\u00CA', + Euml: '\u00CB', + Igrave: '\u00CC', + Iacute: '\u00CD', + Icirc: '\u00CE', + Iuml: '\u00CF', + ETH: '\u00D0', + Ntilde: '\u00D1', + Ograve: '\u00D2', + Oacute: '\u00D3', + Ocirc: '\u00D4', + Otilde: '\u00D5', + Ouml: '\u00D6', + times: '\u00D7', + Oslash: '\u00D8', + Ugrave: '\u00D9', + Uacute: '\u00DA', + Ucirc: '\u00DB', + Uuml: '\u00DC', + Yacute: '\u00DD', + THORN: '\u00DE', + szlig: '\u00DF', + agrave: '\u00E0', + aacute: '\u00E1', + acirc: '\u00E2', + atilde: '\u00E3', + auml: '\u00E4', + aring: '\u00E5', + aelig: '\u00E6', + ccedil: '\u00E7', + egrave: '\u00E8', + eacute: '\u00E9', + ecirc: '\u00EA', + euml: '\u00EB', + igrave: '\u00EC', + iacute: '\u00ED', + icirc: '\u00EE', + iuml: '\u00EF', + eth: '\u00F0', + ntilde: '\u00F1', + ograve: '\u00F2', + oacute: '\u00F3', + ocirc: '\u00F4', + otilde: '\u00F5', + ouml: '\u00F6', + divide: '\u00F7', + oslash: '\u00F8', + ugrave: '\u00F9', + uacute: '\u00FA', + ucirc: '\u00FB', + uuml: '\u00FC', + yacute: '\u00FD', + thorn: '\u00FE', + yuml: '\u00FF', + OElig: '\u0152', + oelig: '\u0153', + Scaron: '\u0160', + scaron: '\u0161', + Yuml: '\u0178', + fnof: '\u0192', + circ: '\u02C6', + tilde: '\u02DC', + Alpha: '\u0391', + Beta: '\u0392', + Gamma: '\u0393', + Delta: '\u0394', + Epsilon: '\u0395', + Zeta: '\u0396', + Eta: '\u0397', + Theta: '\u0398', + Iota: '\u0399', + Kappa: '\u039A', + Lambda: '\u039B', + Mu: '\u039C', + Nu: '\u039D', + Xi: '\u039E', + Omicron: '\u039F', + Pi: '\u03A0', + Rho: '\u03A1', + Sigma: '\u03A3', + Tau: '\u03A4', + Upsilon: '\u03A5', + Phi: '\u03A6', + Chi: '\u03A7', + Psi: '\u03A8', + Omega: '\u03A9', + alpha: '\u03B1', + beta: '\u03B2', + gamma: '\u03B3', + delta: '\u03B4', + epsilon: '\u03B5', + zeta: '\u03B6', + eta: '\u03B7', + theta: '\u03B8', + iota: '\u03B9', + kappa: '\u03BA', + lambda: '\u03BB', + mu: '\u03BC', + nu: '\u03BD', + xi: '\u03BE', + omicron: '\u03BF', + pi: '\u03C0', + rho: '\u03C1', + sigmaf: '\u03C2', + sigma: '\u03C3', + tau: '\u03C4', + upsilon: '\u03C5', + phi: '\u03C6', + chi: '\u03C7', + psi: '\u03C8', + omega: '\u03C9', + thetasym: '\u03D1', + upsih: '\u03D2', + piv: '\u03D6', + ensp: '\u2002', + emsp: '\u2003', + thinsp: '\u2009', + zwnj: '\u200C', + zwj: '\u200D', + lrm: '\u200E', + rlm: '\u200F', + ndash: '\u2013', + mdash: '\u2014', + lsquo: '\u2018', + rsquo: '\u2019', + sbquo: '\u201A', + ldquo: '\u201C', + rdquo: '\u201D', + bdquo: '\u201E', + dagger: '\u2020', + Dagger: '\u2021', + bull: '\u2022', + hellip: '\u2026', + permil: '\u2030', + prime: '\u2032', + Prime: '\u2033', + lsaquo: '\u2039', + rsaquo: '\u203A', + oline: '\u203E', + frasl: '\u2044', + euro: '\u20AC', + image: '\u2111', + weierp: '\u2118', + real: '\u211C', + trade: '\u2122', + alefsym: '\u2135', + larr: '\u2190', + uarr: '\u2191', + rarr: '\u2192', + darr: '\u2193', + harr: '\u2194', + crarr: '\u21B5', + lArr: '\u21D0', + uArr: '\u21D1', + rArr: '\u21D2', + dArr: '\u21D3', + hArr: '\u21D4', + forall: '\u2200', + part: '\u2202', + exist: '\u2203', + empty: '\u2205', + nabla: '\u2207', + isin: '\u2208', + notin: '\u2209', + ni: '\u220B', + prod: '\u220F', + sum: '\u2211', + minus: '\u2212', + lowast: '\u2217', + radic: '\u221A', + prop: '\u221D', + infin: '\u221E', + ang: '\u2220', + and: '\u2227', + or: '\u2228', + cap: '\u2229', + cup: '\u222A', + 'int': '\u222B', + there4: '\u2234', + sim: '\u223C', + cong: '\u2245', + asymp: '\u2248', + ne: '\u2260', + equiv: '\u2261', + le: '\u2264', + ge: '\u2265', + sub: '\u2282', + sup: '\u2283', + nsub: '\u2284', + sube: '\u2286', + supe: '\u2287', + oplus: '\u2295', + otimes: '\u2297', + perp: '\u22A5', + sdot: '\u22C5', + lceil: '\u2308', + rceil: '\u2309', + lfloor: '\u230A', + rfloor: '\u230B', + lang: '\u2329', + rang: '\u232A', + loz: '\u25CA', + spades: '\u2660', + clubs: '\u2663', + hearts: '\u2665', + diams: '\u2666' + }; + + function getQualifiedXJSName(object) { + if (object.type === Syntax.XJSIdentifier) { + return object.name; + } + if (object.type === Syntax.XJSNamespacedName) { + return object.namespace.name + ':' + object.name.name; + } + if (object.type === Syntax.XJSMemberExpression) { + return ( + getQualifiedXJSName(object.object) + '.' + + getQualifiedXJSName(object.property) + ); + } + } + + function isXJSIdentifierStart(ch) { + // exclude backslash (\) + return (ch !== 92) && isIdentifierStart(ch); + } + + function isXJSIdentifierPart(ch) { + // exclude backslash (\) and add hyphen (-) + return (ch !== 92) && (ch === 45 || isIdentifierPart(ch)); + } + + function scanXJSIdentifier() { + var ch, start, value = ''; + + start = index; + while (index < length) { + ch = source.charCodeAt(index); + if (!isXJSIdentifierPart(ch)) { + break; + } + value += source[index++]; + } + + return { + type: Token.XJSIdentifier, + value: value, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanXJSEntity() { + var ch, str = '', count = 0, entity; + ch = source[index]; + assert(ch === '&', 'Entity must start with an ampersand'); + index++; + while (index < length && count++ < 10) { + ch = source[index++]; + if (ch === ';') { + break; + } + str += ch; + } + + if (str[0] === '#' && str[1] === 'x') { + entity = String.fromCharCode(parseInt(str.substr(2), 16)); + } else if (str[0] === '#') { + entity = String.fromCharCode(parseInt(str.substr(1), 10)); + } else { + entity = XHTMLEntities[str]; + } + return entity; + } + + function scanXJSText(stopChars) { + var ch, str = '', start; + start = index; + while (index < length) { + ch = source[index]; + if (stopChars.indexOf(ch) !== -1) { + break; + } + if (ch === '&') { + str += scanXJSEntity(); + } else { + index++; + if (isLineTerminator(ch.charCodeAt(0))) { + ++lineNumber; + lineStart = index; + } + str += ch; + } + } + return { + type: Token.XJSText, + value: str, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanXJSStringLiteral() { + var innerToken, quote, start; + + quote = source[index]; + assert((quote === '\'' || quote === '"'), + 'String literal must starts with a quote'); + + start = index; + ++index; + + innerToken = scanXJSText([quote]); + + if (quote !== source[index]) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + ++index; + + innerToken.range = [start, index]; + + return innerToken; + } + + /** + * Between XJS opening and closing tags (e.g. HERE), anything that + * is not another XJS tag and is not an expression wrapped by {} is text. + */ + function advanceXJSChild() { + var ch = source.charCodeAt(index); + + // { (123) and < (60) + if (ch !== 123 && ch !== 60) { + return scanXJSText(['<', '{']); + } + + return scanPunctuator(); + } + + function parseXJSIdentifier() { + var token, marker = markerCreate(); + + if (lookahead.type !== Token.XJSIdentifier) { + throwUnexpected(lookahead); + } + + token = lex(); + return markerApply(marker, delegate.createXJSIdentifier(token.value)); + } + + function parseXJSNamespacedName() { + var namespace, name, marker = markerCreate(); + + namespace = parseXJSIdentifier(); + expect(':'); + name = parseXJSIdentifier(); + + return markerApply(marker, delegate.createXJSNamespacedName(namespace, name)); + } + + function parseXJSMemberExpression() { + var marker = markerCreate(), + expr = parseXJSIdentifier(); + + while (match('.')) { + lex(); + expr = markerApply(marker, delegate.createXJSMemberExpression(expr, parseXJSIdentifier())); + } + + return expr; + } + + function parseXJSElementName() { + if (lookahead2().value === ':') { + return parseXJSNamespacedName(); + } + if (lookahead2().value === '.') { + return parseXJSMemberExpression(); + } + + return parseXJSIdentifier(); + } + + function parseXJSAttributeName() { + if (lookahead2().value === ':') { + return parseXJSNamespacedName(); + } + + return parseXJSIdentifier(); + } + + function parseXJSAttributeValue() { + var value, marker; + if (match('{')) { + value = parseXJSExpressionContainer(); + if (value.expression.type === Syntax.XJSEmptyExpression) { + throwError( + value, + 'XJS attributes must only be assigned a non-empty ' + + 'expression' + ); + } + } else if (match('<')) { + value = parseXJSElement(); + } else if (lookahead.type === Token.XJSText) { + marker = markerCreate(); + value = markerApply(marker, delegate.createLiteral(lex())); + } else { + throwError({}, Messages.InvalidXJSAttributeValue); + } + return value; + } + + function parseXJSEmptyExpression() { + var marker = markerCreatePreserveWhitespace(); + while (source.charAt(index) !== '}') { + index++; + } + return markerApply(marker, delegate.createXJSEmptyExpression()); + } + + function parseXJSExpressionContainer() { + var expression, origInXJSChild, origInXJSTag, marker = markerCreate(); + + origInXJSChild = state.inXJSChild; + origInXJSTag = state.inXJSTag; + state.inXJSChild = false; + state.inXJSTag = false; + + expect('{'); + + if (match('}')) { + expression = parseXJSEmptyExpression(); + } else { + expression = parseExpression(); + } + + state.inXJSChild = origInXJSChild; + state.inXJSTag = origInXJSTag; + + expect('}'); + + return markerApply(marker, delegate.createXJSExpressionContainer(expression)); + } + + function parseXJSSpreadAttribute() { + var expression, origInXJSChild, origInXJSTag, marker = markerCreate(); + + origInXJSChild = state.inXJSChild; + origInXJSTag = state.inXJSTag; + state.inXJSChild = false; + state.inXJSTag = false; + + expect('{'); + expect('...'); + + expression = parseAssignmentExpression(); + + state.inXJSChild = origInXJSChild; + state.inXJSTag = origInXJSTag; + + expect('}'); + + return markerApply(marker, delegate.createXJSSpreadAttribute(expression)); + } + + function parseXJSAttribute() { + var name, marker; + + if (match('{')) { + return parseXJSSpreadAttribute(); + } + + marker = markerCreate(); + + name = parseXJSAttributeName(); + + // HTML empty attribute + if (match('=')) { + lex(); + return markerApply(marker, delegate.createXJSAttribute(name, parseXJSAttributeValue())); + } + + return markerApply(marker, delegate.createXJSAttribute(name)); + } + + function parseXJSChild() { + var token, marker; + if (match('{')) { + token = parseXJSExpressionContainer(); + } else if (lookahead.type === Token.XJSText) { + marker = markerCreatePreserveWhitespace(); + token = markerApply(marker, delegate.createLiteral(lex())); + } else { + token = parseXJSElement(); + } + return token; + } + + function parseXJSClosingElement() { + var name, origInXJSChild, origInXJSTag, marker = markerCreate(); + origInXJSChild = state.inXJSChild; + origInXJSTag = state.inXJSTag; + state.inXJSChild = false; + state.inXJSTag = true; + expect('<'); + expect('/'); + name = parseXJSElementName(); + // Because advance() (called by lex() called by expect()) expects there + // to be a valid token after >, it needs to know whether to look for a + // standard JS token or an XJS text node + state.inXJSChild = origInXJSChild; + state.inXJSTag = origInXJSTag; + expect('>'); + return markerApply(marker, delegate.createXJSClosingElement(name)); + } + + function parseXJSOpeningElement() { + var name, attribute, attributes = [], selfClosing = false, origInXJSChild, origInXJSTag, marker = markerCreate(); + + origInXJSChild = state.inXJSChild; + origInXJSTag = state.inXJSTag; + state.inXJSChild = false; + state.inXJSTag = true; + + expect('<'); + + name = parseXJSElementName(); + + while (index < length && + lookahead.value !== '/' && + lookahead.value !== '>') { + attributes.push(parseXJSAttribute()); + } + + state.inXJSTag = origInXJSTag; + + if (lookahead.value === '/') { + expect('/'); + // Because advance() (called by lex() called by expect()) expects + // there to be a valid token after >, it needs to know whether to + // look for a standard JS token or an XJS text node + state.inXJSChild = origInXJSChild; + expect('>'); + selfClosing = true; + } else { + state.inXJSChild = true; + expect('>'); + } + return markerApply(marker, delegate.createXJSOpeningElement(name, attributes, selfClosing)); + } + + function parseXJSElement() { + var openingElement, closingElement, children = [], origInXJSChild, origInXJSTag, marker = markerCreate(); + + origInXJSChild = state.inXJSChild; + origInXJSTag = state.inXJSTag; + openingElement = parseXJSOpeningElement(); + + if (!openingElement.selfClosing) { + while (index < length) { + state.inXJSChild = false; // Call lookahead2() with inXJSChild = false because one
two
; + // + // the default error message is a bit incomprehensible. Since it's + // rarely (never?) useful to write a less-than sign after an XJS + // element, we disallow it here in the parser in order to provide a + // better error message. (In the rare case that the less-than operator + // was intended, the left tag can be wrapped in parentheses.) + if (!origInXJSChild && match('<')) { + throwError(lookahead, Messages.AdjacentXJSElements); + } + + return markerApply(marker, delegate.createXJSElement(openingElement, closingElement, children)); + } + function collectToken() { var start, loc, token, range, value; - skipComment(); + if (!state.inXJSChild) { + skipComment(); + } + start = index; loc = { start: { @@ -5123,6 +6209,8 @@ parseYieldExpression: true inFunctionBody: false, inIteration: false, inSwitch: false, + inXJSChild: false, + inXJSTag: false, lastCommentStart: -1, yieldAllowed: false }; @@ -5187,7 +6275,7 @@ parseYieldExpression: true } // Sync with *.json manifests. - exports.version = '1.1.0-dev-harmony'; + exports.version = '4001.3001.0000-dev-harmony-fb'; exports.tokenize = tokenize; From 35c8f104bd409b82f6b90a6ce226a55e6a7b3e7c Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sun, 27 Jul 2014 02:56:41 +0300 Subject: [PATCH 017/198] Spread attribute support and small optimizations. Conflicts: acorn.js docs/acorn.html package.json test/tests.js --- README.md | 2 + acorn.js | 292 ++-- docs/acorn.html | 2038 ++++++++++++++++++------ package.json | 2 +- test/run.js | 1 + test/tests-jsx.js | 3801 ++++++++++++++++++++++++++------------------- test/tests.js | 1 - 7 files changed, 3910 insertions(+), 2227 deletions(-) diff --git a/README.md b/README.md index 857158f7bb..323e2d2d95 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Acorn (JSX edition) +[![Build Status](https://travis-ci.org/RReverser/acorn.svg?branch=master)](https://travis-ci.org/RReverser/acorn) + This is modification of [Acorn][acorn] - a tiny, fast JavaScript parser, written completely in JavaScript. It was forked to create experimental, alternative, faster [React.js JSX][jsx] parser by integrating pieces diff --git a/acorn.js b/acorn.js index be448ca306..195748c920 100644 --- a/acorn.js +++ b/acorn.js @@ -351,6 +351,7 @@ var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true}; var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _ellipsis = {type: "..."}, _question = {type: "?", beforeExpr: true}; var _arrow = {type: "=>", beforeExpr: true}, _bquote = {type: "`"}, _dollarBraceL = {type: "${", beforeExpr: true}; + var _ltSlash = {type: "' may be relational or have special meaning in JSX + var _lt = {binop: 7, beforeExpr: true}, _gt = {binop: 7, beforeExpr: true}; + // Provide access to the token types for external users of the // tokenizer. @@ -544,14 +548,14 @@ tokEnd = tokPos; if (options.locations) tokEndLoc = new Position; tokType = type; - if (shouldSkipSpace !== false && !(inXJSTag && val === '>') && !(inXJSChild && tokType !== _braceL)) { + if (shouldSkipSpace !== false && !(inXJSTag && type === _gt) && !(inXJSChild && tokType !== _braceL)) { skipSpace(); } tokVal = val; tokRegexpAllowed = type.beforeExpr; if (options.onToken) { options.onToken(getCurrentToken()); - } + } } function skipBlockComment() { @@ -712,9 +716,16 @@ skipSpace(); return readToken(); } - if (next === 61) + if (next === 61) { size = input.charCodeAt(tokPos + 2) === 61 ? 3 : 2; - return finishOp(_relational, size); + return finishOp(_relational, size); + } + if (next === 47) { + // '' @@ -732,34 +743,34 @@ function getTemplateToken(code) { // '`' and '${' have special meanings, but they should follow // string (can be empty) - if (tokType === _string) { - if (code === 96) { // '`' - ++tokPos; - return finishToken(_bquote); + 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 === 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 + // 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. + switch(code) { + // The interpretation of a dot depends on whether it is followed + // by a digit or another two dots. case 46: // '.' return readToken_dot(); - // Punctuation tokens. + // Punctuation tokens. case 40: ++tokPos; return finishToken(_parenL); case 41: ++tokPos; return finishToken(_parenR); case 59: ++tokPos; return finishToken(_semi); @@ -784,12 +795,12 @@ if (next === 111 || next === 79) return readRadixNumber(8); // '0o', '0O' - octal number if (next === 98 || next === 66) return readRadixNumber(2); // '0b', '0B' - binary number } - // Anything else beginning with a digit is an integer, octal - // number, or float. + // Anything else beginning with a digit is an integer, octal + // number, or float. case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9 return readNumber(false); - // Quotes produce strings. + // Quotes produce strings. case 34: case 39: // '"', "'" return inXJSTag ? readXJSStringLiteral() : readString(code); @@ -957,7 +968,7 @@ function readCodePoint() { var ch = input.charCodeAt(tokPos), code; - + if (ch === 123) { if (options.ecmaVersion < 6) unexpected(); ++tokPos; @@ -993,9 +1004,9 @@ ++tokPos; if (newline.test(String.fromCharCode(ch))) { raise(tokStart, "Unterminated string constant"); - } + } out += String.fromCharCode(ch); // '\' - } + } } } @@ -1011,15 +1022,15 @@ } else { ++tokPos; if (newline.test(String.fromCharCode(ch))) { - if (ch === 13 && input.charCodeAt(tokPos) === 10) { - ++tokPos; - ch = 10; - } - if (options.locations) { - ++tokCurLine; - tokLineStart = tokPos; - } - } + if (ch === 13 && input.charCodeAt(tokPos) === 10) { + ++tokPos; + ch = 10; + } + if (options.locations) { + ++tokCurLine; + tokLineStart = tokPos; + } + } out += String.fromCharCode(ch); // '\' } } @@ -1497,7 +1508,7 @@ this.start = tokStart; this.end = null; } - + exports.Node = Node; function SourceLocation() { @@ -1611,7 +1622,7 @@ function has(obj, propName) { return Object.prototype.hasOwnProperty.call(obj, propName); } - // Convert existing expression atom to assignable pattern +// Convert existing expression atom to assignable pattern // if possible. function toAssignable(node, allowSpread, checkType) { @@ -1619,7 +1630,7 @@ switch (node.type) { case "Identifier": case "MemberExpression": - break; + break; case "ObjectExpression": node.type = "ObjectPattern"; @@ -1726,7 +1737,7 @@ : "Assigning to " + expr.name + " in strict mode" ); break; - + case "MemberExpression": if (!isBinding) break; @@ -1746,8 +1757,8 @@ break; default: - raise(expr.start, "Assigning to rvalue"); - } + raise(expr.start, "Assigning to rvalue"); + } } // ### Statement parsing @@ -1826,7 +1837,7 @@ else return parseExpressionStatement(node, expr); } } - + function parseBreakContinueStatement(node, keyword) { var isBreak = keyword == "break"; next(); @@ -1849,13 +1860,13 @@ if (i === labels.length) raise(node.start, "Unsyntactic " + keyword); return finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement"); } - + function parseDebuggerStatement(node) { next(); semicolon(); return finishNode(node, "DebuggerStatement"); } - + function parseDoStatement(node) { next(); labels.push(loopLabel); @@ -1866,7 +1877,7 @@ semicolon(); return finishNode(node, "DoWhileStatement"); } - + // Disambiguating between a `for` and a `for`/`in` or `for`/`of` // loop is non-trivial. Basically, we have to parse the init `var` // statement or expression, disallowing the `in` operator (see @@ -1874,7 +1885,7 @@ // whether the next token is `in` or `of`. When there is no init // part (semicolon immediately after the opening parenthesis), it // is a regular `for` loop. - + function parseForStatement(node) { next(); labels.push(loopLabel); @@ -1897,12 +1908,12 @@ } return parseFor(node, init); } - + function parseFunctionStatement(node) { next(); return parseFunction(node, true); } - + function parseIfStatement(node) { next(); node.test = parseParenExpression(); @@ -1910,7 +1921,7 @@ node.alternate = eat(_else) ? parseStatement() : null; return finishNode(node, "IfStatement"); } - + function parseReturnStatement(node) { if (!inFunction && !options.allowReturnOutsideFunction) raise(tokStart, "'return' outside of function"); @@ -1924,7 +1935,7 @@ else { node.argument = parseExpression(); semicolon(); } return finishNode(node, "ReturnStatement"); } - + function parseSwitchStatement(node) { next(); node.discriminant = parseParenExpression(); @@ -1959,7 +1970,7 @@ labels.pop(); return finishNode(node, "SwitchStatement"); } - + function parseThrowStatement(node) { next(); if (newline.test(input.slice(lastEnd, tokStart))) @@ -1968,7 +1979,7 @@ semicolon(); return finishNode(node, "ThrowStatement"); } - + function parseTryStatement(node) { next(); node.block = parseBlock(); @@ -1991,14 +2002,14 @@ raise(node.start, "Missing catch or finally clause"); return finishNode(node, "TryStatement"); } - + function parseVarStatement(node, kind) { next(); parseVar(node, false, kind); semicolon(); return finishNode(node, "VariableDeclaration"); } - + function parseWhileStatement(node) { next(); node.test = parseParenExpression(); @@ -2007,7 +2018,7 @@ labels.pop(); return finishNode(node, "WhileStatement"); } - + function parseWithStatement(node) { if (strict) raise(tokStart, "'with' in strict mode"); next(); @@ -2015,12 +2026,12 @@ node.body = parseStatement(); return finishNode(node, "WithStatement"); } - + function parseEmptyStatement(node) { next(); return finishNode(node, "EmptyStatement"); } - + function parseLabeledStatement(node, maybeName, expr) { for (var i = 0; i < labels.length; ++i) if (labels[i].name === maybeName) raise(expr.start, "Label '" + maybeName + "' is already declared"); @@ -2031,7 +2042,7 @@ node.label = expr; return finishNode(node, "LabeledStatement"); } - + function parseExpressionStatement(node, expr) { node.expression = expr; semicolon(); @@ -2272,7 +2283,7 @@ var node = startNode(); next(); return finishNode(node, "ThisExpression"); - + case _yield: if (inGenerator) return parseYield(); @@ -2282,7 +2293,7 @@ return parseArrowExpression(startNodeFrom(id), [id]); } return id; - + case _num: case _string: case _regexp: case _xjsText: var node = startNode(); node.value = tokVal; @@ -2304,28 +2315,28 @@ if (options.ecmaVersion >= 6 && tokType === _for) { val = parseComprehension(startNode(), true); } else { - var oldParenL = ++metParenL; - if (tokType !== _parenR) { - val = parseExpression(); - exprList = val.type === "SequenceExpression" ? val.expressions : [val]; - } else { - exprList = []; - } - expect(_parenR); - // if '=>' follows '(...)', convert contents to arguments - if (metParenL === oldParenL && eat(_arrow)) { + var oldParenL = ++metParenL; + if (tokType !== _parenR) { + val = parseExpression(); + exprList = val.type === "SequenceExpression" ? val.expressions : [val]; + } else { + exprList = []; + } + expect(_parenR); + // if '=>' follows '(...)', convert contents to arguments + if (metParenL === oldParenL && eat(_arrow)) { val = parseArrowExpression(startNode(), exprList); - } else { - // forbid '()' before everything but '=>' - if (!val) unexpected(lastStart); - // forbid '...' in sequence expressions - if (options.ecmaVersion >= 6) { - for (var i = 0; i < exprList.length; i++) { - if (exprList[i].type === "SpreadElement") unexpected(); - } + } else { + // forbid '()' before everything but '=>' + if (!val) unexpected(lastStart); + // forbid '...' in sequence expressions + if (options.ecmaVersion >= 6) { + for (var i = 0; i < exprList.length; i++) { + if (exprList[i].type === "SpreadElement") unexpected(); } } } + } val.start = tokStart1; val.end = lastEnd; if (options.locations) { @@ -2343,7 +2354,7 @@ // check whether this is array comprehension or regular array if (options.ecmaVersion >= 6 && tokType === _for) { return parseComprehension(node, false); - } + } node.elements = parseExprList(_bracketR, true, true); return finishNode(node, "ArrayExpression"); @@ -2367,10 +2378,8 @@ case _bquote: return parseTemplate(); - case _relational: - if (tokVal === '<') { - return parseXJSElement(); - } + case _lt: + return parseXJSElement(); default: unexpected(); @@ -2467,9 +2476,9 @@ checkPropClash(prop, propHash); node.properties.push(finishNode(prop, "Property")); - } + } return finishNode(node, "ObjectExpression"); - } + } function parsePropertyName(prop) { if (options.ecmaVersion >= 6) { @@ -2494,7 +2503,7 @@ node.defaults = []; node.rest = null; node.generator = false; - } + } } // Parse a function declaration or literal (depending on the @@ -2536,7 +2545,7 @@ initFunction(node); var defaults = node.defaults, hasDefaults = false; - + for (var i = 0, lastI = params.length - 1; i <= lastI; i++) { var param = params[i]; @@ -2566,7 +2575,7 @@ function parseFunctionParams(node) { var defaults = [], hasDefaults = false; - + expect(_parenL); for (;;) { if (eat(_parenR)) { @@ -2597,16 +2606,16 @@ function parseFunctionBody(node, allowExpression) { var isExpression = allowExpression && tokType !== _braceL; - + if (isExpression) { node.body = parseExpression(true); node.expression = true; } else { - // Start a new scope with regard to labels and the `inFunction` - // flag (restore them to their old value afterwards). + // Start a new scope with regard to labels and the `inFunction` + // flag (restore them to their old value afterwards). var oldInFunc = inFunction, oldInGen = inGenerator, oldLabels = labels; inFunction = true; inGenerator = node.generator; labels = []; - node.body = parseBlock(true); + node.body = parseBlock(true); node.expression = false; inFunction = oldInFunc; inGenerator = oldInGen; labels = oldLabels; } @@ -2627,7 +2636,7 @@ // Parse a class declaration or literal (depending on the // `isStatement` parameter). - + function parseClass(node, isStatement) { next(); node.id = tokType === _name ? parseIdent() : isStatement ? unexpected() : null; @@ -2640,9 +2649,9 @@ if (tokType === _name && tokVal === "static") { next(); method['static'] = true; - } else { + } else { method['static'] = false; - } + } var isGenerator = eat(_star); parsePropertyName(method); if (tokType === _name && !method.computed && method.key.type === "Identifier" && @@ -2851,8 +2860,8 @@ node.delegate = false; node.argument = null; } else { - node.delegate = eat(_star); - node.argument = parseExpression(true); + node.delegate = eat(_star); + node.argument = parseExpression(true); } return finishNode(node, "YieldExpression"); } @@ -2972,24 +2981,27 @@ // Parses any type of JSX attribute value. function parseXJSAttributeValue() { - var node; - if (tokType === _braceL) { - node = parseXJSExpressionContainer(); - if (node.expression.type === "XJSEmptyExpression") { - raise( - node.start, - 'XJS attributes must only be assigned a non-empty ' + - 'expression' - ); - } - } else if (tokVal === '<') { - node = parseXJSElement(); - } else if (tokType === _xjsText) { - node = parseExprAtom(); - } else { - raise(tokStart, "XJS value should be either an expression or a quoted XJS text"); + switch (tokType) { + case _braceL: + var node = parseXJSExpressionContainer(); + if (node.expression.type === "XJSEmptyExpression") { + raise( + node.start, + 'XJS attributes must only be assigned a non-empty ' + + 'expression' + ); + } + return node; + + case _lt: + return parseXJSElement(); + + case _xjsText: + return parseExprAtom(); + + default: + raise(tokStart, "XJS value should be either an expression or a quoted XJS text"); } - return node; } // XJSEmptyExpression is unique type since it doesn't actually parse anything, @@ -3022,28 +3034,54 @@ var origInXJSTag = inXJSTag; inXJSTag = false; - expect(_braceL); - + next(); node.expression = tokType === _braceR ? parseXJSEmptyExpression() : parseExpression(); inXJSTag = origInXJSTag; - + expect(_braceR); - return finishNode(node, "XJSExpressionContainer"); } // Parses following JSX attribute name-value pair. function parseXJSAttribute() { - var node = startNode(); + if (tokType === _braceL) { + var tokStart1 = tokStart, tokStartLoc1 = tokStartLoc; + var origInXJSTag = inXJSTag; + inXJSTag = false; + + next(); + var node = parseSpread(); + + inXJSTag = origInXJSTag; + + expect(_braceR); + node.type = "XJSSpreadAttribute"; + + node.start = tokStart1; + node.end = lastEnd; + if (options.locations) { + node.loc.start = tokStartLoc1; + node.loc.end = lastEndLoc; + } + if (options.ranges) { + node.range = [tokStart1, lastEnd]; + } + + return node; + } + + var node = startNode(); node.name = parseXJSAttributeName(); // HTML empty attribute - if (tokVal === "=") { + if (tokType === _eq) { next(); node.value = parseXJSAttributeValue(); + } else { + node.value = null; } return finishNode(node, "XJSAttribute"); @@ -3074,11 +3112,11 @@ inXJSChild = false; inXJSTag = true; - expectChar('<'); + next(); node.name = parseXJSElementName(); - while (tokType !== _eof && tokType !== _slash && tokVal !== '>') { + while (tokType !== _eof && tokType !== _slash && tokType !== _gt) { attributes.push(parseXJSAttribute()); } @@ -3091,7 +3129,7 @@ inXJSChild = true; } - expectChar('>'); + expect(_gt); return finishNode(node, "XJSOpeningElement"); } @@ -3105,8 +3143,7 @@ inXJSChild = false; inXJSTag = true; tokRegexpAllowed = false; - expectChar('<'); - expect(_slash); + expect(_ltSlash); node.name = parseXJSElementName(); skipSpace(); // A valid token is expected after >, so parser needs to know @@ -3114,7 +3151,7 @@ inXJSChild = origInXJSChild; inXJSTag = origInXJSTag; tokRegexpAllowed = false; - expectChar('>'); + expect(_gt); return finishNode(node, "XJSClosingElement"); } @@ -3127,14 +3164,15 @@ var origInXJSChild = inXJSChild; var openingElement = parseXJSOpeningElement(); + var closingElement = null; if (!openingElement.selfClosing) { - while (tokType !== _eof && !(tokVal === '<' && nextChar() === '/')) { + while (tokType !== _eof && tokType !== _ltSlash) { inXJSChild = true; children.push(parseXJSChild()); } inXJSChild = origInXJSChild; - var closingElement = parseXJSClosingElement(); + closingElement = parseXJSClosingElement(); if (getQualifiedXJSName(closingElement.name) !== getQualifiedXJSName(openingElement.name)) { raise( closingElement.start, @@ -3152,7 +3190,7 @@ // element, we disallow it here in the parser in order to provide a // better error message. (In the rare case that the less-than operator // was intended, the left tag can be wrapped in parentheses.) - if (!origInXJSChild && tokVal === '<') { + if (!origInXJSChild && tokType === _lt) { raise(tokStart, "Adjacent XJS elements must be wrapped in an enclosing tag"); } diff --git a/docs/acorn.html b/docs/acorn.html index 9bfaf46a83..9a8c3459e7 100644 --- a/docs/acorn.html +++ b/docs/acorn.html @@ -46,8 +46,8 @@ with a error-tolerant parser and an if (typeof exports == "object" && typeof module == "object") return mod(exports); // CommonJS if (typeof define == "function" && define.amd) return define(["exports"], mod); // AMD mod(root.acorn || (root.acorn = {})); // Plain browser env -})(this, function(exports) { - "use strict"; +})(this, function(exports) { + "use strict"; exports.version = "0.6.1";

--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 q6yXA@F-u0Z~1!1poleYR}~W literal 0 HcmV?d00001 diff --git a/docs/public/fonts/aller-light.eot b/docs/public/fonts/aller-light.eot new file mode 100644 index 0000000000000000000000000000000000000000..40bd654b5fe63501ae64d5673b5aa45051a69e65 GIT binary patch literal 29509 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�y6>nTFX z89qx2yw;f;*p=y^$kUQ5cObm}D-;bcqX-#Ey-h6r|`EUXCrFU|9gv=Xz(yMhoLiLz&8;sdc%~>Q-s=mPnB~MLr{18JiBINDg4C zT0BkxLODynYSgZBg9>Y9Jn&;{$MFGi6qFpCf}u>Y#eY-Ao-og=gc0Bpaz-8#Nkgk^ z8^lY(B9rkGod=#(wFQM*PeWC|ylhoFtvMVt^$Ryel=Usn%(+!@SbbG#?mfR)e(!e` zeb9viOj;EheU*wZTmYV;?50arn{mH`-h+>yDM-(IrBJ|p;0CbNR1rPW}vTT`W#r8xa_^@aT9Hz^J zGwiP1TWp;nCKTZDOP+ZtX=690&n`2nS**Jv_V#kXjJ;h2 z)~1EjPTYT@e=@B~?H8~kugICqF@kAQOyPDXw1r-h3NEmTXetj`8B0G%C|D)kH+Z2= z9$s=F^F_lOprCqE!9#XFuFyip!IVI0`OajH{D}Jef7me37hng@6AQO&$s*MuNmpT9 z#^*57ZUz~(W8?y^+PZWht|rI8v2(QcSI`kvrL+n-eHQ1dv4?!*V1Q3chyy*bU8L8w zzAoUyrMPNhE-he~*@k2y9*LB&+X{b+CnfIJ06+kad|GB=$=EH7*s{PW@g60sCEZgR zqar1172z&OG>@dmHeX9I(LLg9ThJ=L9fu{lLC*FpUgB}NdnX~Xb&#m7Zi3_=*>GaU zG*8EhE#21HPofE?^f?w85bFC85}GNT!!cU>^1w~^e&n?NG2j@R+Km^}OBrZssp%01 zp#C#7VD0=_{i13TzZ30rX=>0!35q_1DjPG+z*lxlZi`1k4>V=UOGEJnZ)~+@^1vR9 zYJ|6ae%o9CbMO8+ZqL@Q6$fdi88~z~5X447fd1oT%qx?BWBM>BJRm<8fI+E`1;i#| zb6BlyDi1BofEQ*j;I zegTf6wf`Oq$rMesn39|UCt+m2R{CtpPnE9(*;DE-DN!&94m+dwYC%(FmO#lyo|%P2 z(1$%8@XFA>l)Z5l5#HP|tDLaLVVHXYSy5dVf#?{``FviBP4<)bh==Txq+OIYe;L?l z7W7So|eWEfQ1w8#(qWCAe!giM9{ygU24 zMXLcq1~DiBRtnWO!0Fr|nt6?l7v^ z8NjgJ0|(&oxMnlt#nb0$@UJxR1YaEEr6cwi)Jlv(wR3nml~DT8K*3&8pZUY@No~! zrefIeLtglyqQ~e!$BX84d^X*dbZ0;e{+Lf7(Eu#&a7NJ)%1gA{Cf_IWc~5KHzPimkJiHB$b8SmGx%1Uw=hl|6m)~Za4QjZD1|Ph-PvUQ zltZnofwi3DX&De`E>kd3jT`cRA4Ou&Q^~=HIYGcr2Azz$Rh-}l0V0`?l#$KP*zmmF zcE+m+*ng=YY)G}WmSdU#gBud1;3&X6L{xy`=0yoT?eDydpR!Rlh~JOSfqKB+ldMhz zLjX0$bs^G(N6-jkF7E$Jj36PISsA)}+ZZfIUzkz|AyFv^K1zVVDVYC$*Ujfi0*$vI zYXr^8CK*iI(ildTnGfL2H?BCxOjC01`wipCGS-52or3_Lyx;6Mw80`K1lBsLwF)xKqrYp0;K@VkXcHB zVtBoaf1sIg0h<4+N35#oPb2VXn;pqoGY3>Nv^=*66uNWdW^Mg(uN;x zKDKN5C1hNML?;PCpiU(KXc43=R47{jf3#D%@T5y4Awoh&BSO}n&2;I21S)(QOn`hE z=eRp(ZfPNKbUXBnr1*z0e3h1dO_HzBl+oFI1JZJ0$r2!7^#!5fKBA zSTMqV1dY4LZUBW|(-ABpa-Nb@$AzpOM*sgIYIozGhcge_o@wtl8}} zIffi3G7F=)%P6PqQ}i^bFhZq7EelAG=}nWL-u|1Oq$a#Pb@Ip1Q?IUS?uK7o<#D<3gEg{X;?EY} z1QR?oK1Ia0rX`TPyt&>&+e>2VQC)21tz`SE-C-H>Is9a&9zRbLEQyJ-oCR#8h&>jq zjgQkSud%9aUKbVSd8%O$%Sc>SSOl;NnI@hjirv(ustyuA=j@;H*G(chJFqPfl8-JUEH5tu42_%;I|{V^s37g6!(=+zkY#60~{OVdXq?N6xjBMh8tWV zv1widw4)$Spx+}X0R|NtZZJ3X^E>2zJ2gxK)ALMTSm^qN-0(J#GlBV`@4LY6 z$oC6@`cFy~MlEH|Qw5wp!2I`IVQN}~7aQDU@w+2e7pFe)l1XC{*_6RDAcFyazMp*T}2=AJEZ zc_yc5m0TNVtWF@tFbv|BUSQ2cf9avU?VjlGs`*36)WY2Wp237_Y=Q7X@zVTI?Y67? z&ave3m?n|Q4sw>2frzs_ng9;^*|H-uY;%HZQn{#%;F8RYkn51GFS_Xz?NX3J0)oWl zR8Lm^l&VN629$HUf`V)Af=N2CM?&tyxoOO`kh|Ltv;fnYOr65@?ino92x8g7n9R&7 zT}8#uWa~wGQzjKHBl73m_{gFO%9Qxt=f`5rF9Imo4SBMeDPqG)ShWeFYSlKp-N|~3 zG+IjCmG6ckF7{TQBbh16#oz$angs+vOSYOafNcHIRGoL?W#An(DTwZ)rG*J<#&|a9>5%M9pDk*BU9!k?f}@F9tXEE z0I(u{u^Cu1g@PYy9QEwOA%GUA2s$r*m`dGy*i8UG>G0Hd z@-6ZZuKmRc;akl2e82Y-6c!5k=;{j(4Mo539>$aA>`2qNuRI+dJs8{C+PcNPt->x4MR?W#AgA`=TzlA)mlGUm zG}6W?^1a^Ys&Ng3v#>!z(JE;Tuz&$F^;&|!Ue8@}14c&nVU$>d{Cv@7rZ=OL(Bs6$ zd_6M`hG-A0C^UPwQbN!p&kGa#1edNpC6xehCJ&8lU?4h~g%<#T_C7sw04y`4M-uBO z;)GEo8Vu?iy1hXQ)siFuhH>> z*nlifg>Mtpd|tR&44SW|3eT|s009F5U;rm!tuyYM7L4JA-Obi;ILv~fOlSzK{Sh4* zL=mcpaUdgv>;e`IkvVTUV_z*f{<3r}3KOUuca=`E){ae2q$9xJG^=M@&!#p%@#vp(VkbFVQLK4$?z>5+*U&)Eo<5szoPC zsYahXWmcdPv!KvTf*(4HOhI@?7Gwu+ssK^+rfS9DPu$wSeMH0v(F1~B4N2G$p z<64tjg6O?^tKGxyV7Xy$F2q*wE8HRcbx#1 zS#`tg6`33Xn$nIn1#udIYolM0Gb7QFli3%PROZKFLE0ayGKds-Q zekQaK2R{uRYV|pD|8oHPl&G}t^iUan1*U=!mDl1tDIr_|BAx@JYn&x8dZq-s2 zNd7WYaQm|`m0+Kt90?|3fHv5Glfm>*Rfp<6QdwhVQF*oQ3lx}yM|GU{CE3JGK7_Eg0@M+d3Xh%JDqD53Mms}(C`ofB(rbhR}p5eF1IRT~Tq z+GUz$0$&(qc;?s@Fl2dx*=F1x&Z$LAY?3%0||TRlr}3tg8thfe~BFI5ac&2q&b1Q=IOu)?jqWHXvC_Pv)$$g9*F=tJPKqL z<2f0}$V}qeUgSltN7TsLzEl`f+)C_Xf$>Ku^M23=eseG;r$$VbrD)V?x`DERx8=)0 z2Pt8EIu(;)G26P#LYjtel7k&l=h!|e2AvxA=iT`v+f!VRfps(nSXB+&C>ExlD3tW4 zfQ6^&B<~7s#cT6v;_YMWM}T6Sj=qE_CIdTLSvOdw+4#p{`O&6E^^yio=^M=;7}f zKXRHy*C|lh6uUZRjEBJG)&2`j6%eElKDE#xS}c|t00+=&tR2D@{O}vO4g$#|)6PpD zud`PeAT1T{LaQ?Jg=%%m6+miR9Y~y9 zI@k<5wDp5QC!w>t$ixH23u$^8WxUc3A$rROa#`8l(=9R*n4%3*NuH8&BuEIjb-%`7td zwnuDe6lD-1lU-1s$s5HSh3VN0+b>>!wtF+;dedyqGr|QjWNfj%1x#z@M5MG9bVwPO z!V3DPO!FqjgK6EW(@;Bb%%xks`4SP1NrLPv0~Y4##*nhhz-kuyz$h5mEFI?tlLmm7 zQ%?r~d?lUDiC03;v--|-}7)mCc}mD8q+h6_h=qW zK;vFcL8weD1FJ!#4lNpSBijF9Xx4@;uit`%)MQmr$o9C0#R~kkc#)s5M$9j=VK#`0 za|6*@HL;pE%(f0a4ybiU0b#_dFk_0R#IVa0rZzB5ND-E%5^aav0)Wgr+JV>^{UA{r$^Nl*8B(!1QBxLxqh8!@z<$ zS9U)79lLRG(p*$)_6S3+m~`I&UQEhmiAkgUV^fy__!7l2M=^9gS&+_)5i07Z9)d$it|l>Z}Q%m@n(k zkzZn>L7=DjIkH+&Q~1?$7g!g*nifPTh7ejr!RVE_vHde8yhGorhd@A7zon->>6fbUE<)=fii*ohPDjG1Rtb?Bu*P-AcU&^-{p11W=)L1g?>2C*T(Dd#N+cG$&e zrd?W^0^@_QrD_eTO;)k|6PG&4oHj~ysVH{)|!A>vV zVN|x#h?E5w(Hk>H7Gqy zb`17YBCps(regM78O0d9WzL2l-Z=ms6YVpM>Lid1w!F|Kn7MJFPM{ps#RR0bl!j1pSW0%8r?JtT|M!6MMex?RC-76at%^M`6(72NghS zxQ#k!P0kbXsKs#2i$WB`LrTc@6V8_8>kpiDQ8os6Q3Ql!(+qF_CMI8mV~IS3GnY{} zyjVlmxJ8U6M6oOa@Hda$4JOvzjDPAwW`jW$4X~-g-G0Xp;qQxxiPG62Z^V<_=X=GC zMVAx%kx}1G!dX#ZXj^t$Yw&$(H68^pIqqR%-&QI64iR!*wY-zd=g8u{0*!q)J%VBI zwQoJ)3TLMxvm))9#58;u#L2jQwl8NjxFJz%tw-Fku4Mr@d@?aqNU_o+f=P-H4G;*-%V1&1n68Bfj3w6;bllHv_#ZZz&HCLna-MbK1?P6N%s>G zCRA|J!_UV=D?#9(3pygf#Hg8UR5@GF3zVF&V@`Z3VpQgL`H^ZTW-dWb7QoXJ-uf(jSDOxK|Bg-8dgsUb&x+_1a> zD6Wf`yJuhlrYgetSZ%#BCqqtez%kw}tDp%ZnCGB154D2Y!WVrvAjdU~L+MCgS>SpX4*Y33ZNT`P-e-SLs*T5N28=*Ix{?Vo`BOclT@bJ@hwS-Znb z2OB}Tb9C$duilz=4#+<&7~qBIPpN1BtT*}x%vK>f7=xq_KxOucCJ+<@fQx`9(u}x{ zHcdD2Oj%%3Uv#b1^zZrtwRmCRW@?zthO15ZKBlJS=Yz!RZKbsTIMsFc*&l+sm&_-c8E+$c4ggd(y_OW2Y}Q4u<PJM;be{FF|7i;c_nqcYwJ-eUKeK!1Tp-zbD;zRDprUm$5B>lHmDW^`ro!q=^>zjo>OMpdGNM+VuX0!*2G}8bpUcLR{hj-UXzd zC|flcFcMLgW<9Em&axxqtb4Rp6o!;!s&E@3I|?-}0XYMmXU*wkX)dct$_gj3lna0x z0STnX4GGqyy_MYIwN4)_ybc1?hD+~jysR9|a5m)*Jr4h`MRHF6g%o5Jso21M1NcFs z*Lfzc_8l)sY(PWL#*r}v=@SrM5XX+zmLmGgOK5gD9_u-24IXPn(qs2lDzKC7Hau%t zb*#P~oa$4Z)k_TQ3y&#M#xRQxVlSP-FTA zDUW2K1M&ssPILu5SwA?+*IXa%o>l=1Lo!$I5P&ky>*{pDZxTN@P_k56Oh32sF|}0M5Alk2ubn5HUpzoy8g$Q^vKxnhb z)SxuRq)UJt#$%=r&_OBc3^X+~GcK+9IJA%1lPf?d5YJ}XLyTfFI~F|PnO@~7Q-?;L z#NgHH+zr-<3sv?Yu0cn*2YX|QM9-A}85v#3mf2RH?JCa?8-?@m>fj}u47yPyQ5x#T z&Ldcf_sioX5GlN-0{T<6bi!8?UWv%Nbg5Y^aS%HUI}KNS1AlWr5=ncRprigCP$(3; zzGym0x;w5i6yuC2&RBcO3ANOl57E{F3y>(?f0rcMfUp$9%a(e%>rwvc?Uh6I~yW3-Z^m8d^OVG~Y@#ulsOqB;Xg{U=w{*scK`Mubr( z`w32gIL0ahfHAOuL~foY-T}w7C2IueQ6$cJ5^~hgpcZPlwl@56&mph3*VN$dqCEtX ztM&Ezh;&a5bRsEAz*eXgY?;bNjSZ*OtZWRsjsMxd;%OLDmSL!gr;{}@dcutjV9i7r zlz)fp9RRk{L4cbhq*)y!{DKTHOCPZ zel5G)&n!}`r$K?R`Wj8_VV$#5P~KzqaE>+Zlx))Q=v7Ktx#$M0f$L6-X@@908b7PA+suW0OtwioNR>CPcK@P4y>6 z*Tt9xpap(lruJvSnGi)X)FEux_b5@6-WY3_=W8gfrdGT3#@S%}J%&|&4oLdlwdh!Rm(~rD zFe|vNpxwFMJn%!w#)KABv#N)Y>T0z%jH7qqM{Y==`H!uM)A)z$wr^drI0T6C z-GHK4hu8M{=(e~TW^{kon`*+ADTcH{AHGd76_JZcj=l2hQk4Y8!xzPi5CSoaWSEY!gjiPOe|ooEtE+BVtAt z7&1&b3scB9(K=8QFzGG;m!-+ z8cVh9s&a6UQisPE^OLxR0EXH5k9q`-F+Xsdf}Glf;Myapl1E}y0hW;w!0V8D7B2(D zp_XhYM@lb(I|LA1GL+?@%bjTd;oaDf%WImnX;2`%WOKS38O*+YKAI7Pkav_YrlH=S?D+F4nvj7}doQSm;UKH33ww9x@p zN7%ec_@rX*ftEt}N49A+b`MxvJ0wtCmZM02@2-bzyM4F$f)fht(LZOQO`wDlkr6OV zC~}S%RsopIDk04mtbqB-7ZP!W8b;*yur>YNY!<-!nHX?^2$jgb-VT%nTtO;~f1D(G zVMyQ&C&Wq1TMr_pinzWsT0Ius|WAW(SdH5X+qx$9wCO! zxTfwy^2^}ayotygO6C}e^u+Sq#BpLPjb`6OizK=dAZFNi`OGP6&yM<|C!9(}F@w`2 z^gIKUEOcfh4*?}Dc+veY0F606r#_Q08H~U@61+JFNIn*-Co7txt_9f=(uX333&I8< zBBl+Hx1^K}6(CKqBfgCamMpF^0aZ1^0e2QJDWE_sPrUj@Ao@b3h;-Y)=)x0YFd}Hj zKUl{70K*cYN~`X1+*hz)r~X>C9Nsf(ozzea^%apw*7t?2u!yc8+5*gC0>- ze7bS~j&a{X7+7Hs>HJcOvZ-B=9)tyem>xdhg+J0n(Nv6B;SwVi$+LI^!AO`M;|?9n zH8J=AI+15mRp;Vi!zlyo80E-1HE$yF|wnGk^6u|ZL5KYnT^k{0@Nyup>m@nB918?=*JQkdKA=<9@!F- z2lVU*pX-OU0FW$Q73Z*Ky*eg#&M*5mX%hf!W}}=9d(l|C4~07$h{fF7jmG(=a~h89 z?SzR~-tnRwEn4iwO|)urp>7Z~G+{&~gBZvPg2G|@^Fht>Tfjzz6O_;pd&SYK#0hxu z_e5_s3r}0ga6Sh3n5{8%=;YP>b~84}(|5h`H?T8-SJ_e9cssIo*0ZR-&-1@@+&C zPrDG=7f1F6Qh}Ij3vCujpzN^=qP7rAC`gykRW{{Y?LC<#K?@3scc-~3<6(2;>rS?MUdvkwew z;vAfFY8PW+oDj28Uol9>iy8Wai90?WbTPe=OitItufPK4q)_K94CgR@Eg%OIYMNmb z=~u-_$5*^XNO5?aWOX{k%R0Lg%z3B~+I1@47JabTe90v1sa8Yoj0 zg1W#+U;!0^lAEjsMAd-^tHeeK0RM#nwUz@WM2TctKMqXkbRtBO-zbieB6Ua-=_dif z9Tr%UL-h}jLWP16QdEftGz50GZrXYgBfe0F!7|Yu42vtxZBWbKouAKUGA)MEtOzFiTwYv&W67+y1J?b(ir@Zt1*i9rP*U`dft&0oMgE%lg4$FeoE+IYeBilU7~Z*uR^7&ED9Ap*kQTJYjfBXI(Sjfc zqV^~?0!9~@J5=s$cuAz&L`BahNIR8vbVd`UtKkX|yu-s55S-8;gaKQa_{|H}5Us1! z{UR_vm@yJv5Zb&G-r?R$lId(e7kKMtzns-***L-X)<~(w2?wo|s?1FaL5YsFGZ4h2 zEYM>aOcUj~A9#S5!R<%JXc~iO6(xQ%%ZkG5wVsJjiE-zr=0a`@mEFm}#DCb}9EZgE z7AG>rcP434>_Ci(b|pcGelB^86P^*Dwbvpl0uG1cW2DKLK#ajRosLS)Qi;rnTc3F3 z!s!F>Sar=7^pwIJ&ua*CKA%HQQEQj~-k$3Sk8XxC6fG_9sOMEq`1!eI25XUy){#I?-!w9wh&z=#6 zw&vm6+1wNt;{~pO5xs4e_ISkq5G}>?ewaxMJa=kH!>Gwl>4fn|;XKS!eItO4^B|Q) zBXz-vVj0U%&>TFY0o_~VDNK!o3br63@Xr~&aF$Y(&R+x~(6F6kEgOCOlY0Pt_AL3H zrs3YPm)J2soD%}ZEG}-FsAU<6HR?n^TM}o*8x3N^IRoZ_`|=5io3p9w9n{b zTT%m6taK(&Loo3N2~PnX(kwmDz$fFJEFQ6(qm*&bIm3ZM!1v9rkc2OEn$fAv@oriY zagp2BBQ;9QjIhV6D}IPISF}J|%Y9_)aN-B@=#iI#_S!>RN^K){pJLWI8D+?#!B_#- z-1f;hP6RUb1^W_KUTE$L@ft^@nA}Kpy&}<&%nqob2MdFfqIB-0CWK8Ri!i=cHj9~M z?c0{b)6VQyaTd1moL$5mwN#H*LFXA~xJv_!P$W@pw!Ni^CteIXrcM(XsCDREDAgeY zSi11K!Tlc;NRV}66=3Y};dg#Ft*}{U5<%?Clv(MSHHHGMa#DZ1im#;qdAh5yYyN}6 zXT-_Q%9ROpbzdDSb1iGx31;Ni;aY@kF1<3zaUd$Q5M%JR^2CaI;gbwO&awLY%vE3DhP)%sYQmRi@fUBzVb{IBcG zWF~yH-Dlr@f4_Y>znrf*ANPHI{;%u4?t>r-g5btV7G^A3wDjubckTb7Ac%8uwrugj zD;AlHjc?+(AIE)*d#<^5{sQ>o{-!&h_=k?^IQ}*6`Q^=@y1T;mzZ`!QgpQx$_ql8Cyk-5hBe8D?!UBsR zNULwTY15rJuL!~ww6)xF`_?sI{#^1l9N!}dC(f;1ebXxOgwQRB!YcgUycQ=Mx0=3% z~)(K|z$);{9jV-*nHNl36?_h^BU2UvbAx z>sMFYwcueKufXrgJ2z~)+x&&-mjuz`L3`f5^RCr*{^Q|;20^rr;djfH)hpK=S@(%n zLA1%Z--JJ+p77JwgD=tchcAC6pSCaFylj+zvEyI~oe?C#iZk2s_Zi`{INB-f#{TEA zNWy)>H?V&gizIwgIEDRZgwxpnq3|~Le#9=;z-5Roq@8mpoj$ z%J5o;(AjWz!($CUYWSeBys^9SQ;kRC zpNo&oyt}Ep>6guQ%`2LJ(^567d)8miI+~c4=u3Llm9Kvssa5Fe43hm4nBPd&rziC1vemRC`X+kUS?VH?dh(aY6NvOeM5T;|1(Y8jsZzdKK-r6FV@#X~jJ{wCOS}+%K z)P^M=ZMjmg3D;vO5SC%F3j1$g(f=3F)6)~Lb8nB+ zI;WpD?t{pEkht{*P_-3LxB-iiHOs{9GjMAR+!`~t#=@;Jb89SkrYKYkk~ojwzDBqM z#}T~!YuW@;z}N5s~5CciX~s@!(tQu3QK{|kHyYBb1=^o=9v=`yk2lK=S1e5 zfjMUo4#L_PVQs#Nw;U1vC!U|g;u1!L<9PlFELP!r!qa#rao5S*buxDiuuZ4&>l;|y z%*#CVi)8IStlwZN&O_@(!3!#$o_G#)dJ(-(PCO4@zKJuxV459EQ;sP69{vvHP^Scv z!y7LKl_-X!3SEkEBgz z`LL(uH!H0UmJfyH!@=^Q2>*gbg!aG5ZIOhq@Fle7Gu+P^!Yup-e}#TcE`o>UMVA?t z23(WT&wS>r$efj!vj*m=%skaOA~Ht|%n=iFL}rf2OnDhkGr`u}FYFP%AnXNCB(a-Y zb1(WP3QcHD9G2p&E_0AQ-G-dzR=vpFAibiNot+5a*RvD*@TdQt*=COPWBn+j0obPg zh&yuaPVf>O3kjh~jx`I-;2815#1d|1I#`$vc}xc@b17fw!D16Wfu(>cV;8Q);$ZqH z!gW}jEcq^$b~j7Ahqb;ihqpy6;bxX_3)9oe^z;hDSPGb`cBZPGscKL2nXExA_`8lN zS_%CWAyEQo^&0fo1Ku*_a5lqHD@&%x(wMPC-M}caa5Wa)Mv~pvaE2sJw?rnEF%zCc zHb4SD$-@^56*$Hos0)iS`4&P7bR{iOT%F>p7cvqm<<`ACp)VQh#P>rciDz$4ypmqt z#__p{x29MkKl(=+Ouj;5dt_jHB(publqDh?l*jzAvfasNPS}_e1#EZhY?27R&O#>!gj()D(SXhkLPG{{cZQSYkc+?6cg}+5TiEvGvF)+456ajZ;(q~C z#m-c5FjaJVO!c5&6&}ZP$dBf;j1+M174E&lz1O{IKKm~x+b0*xj+5;ZAvjTpfphj)N_e zg*73MEmJ;QCWSSjfHk3jZBhZ-B;xEF?0ZBZj&_}4xt|GnBhQ%iu)2Re4Viw5Y?QDD zmj6Oq_2>L5c~m1ywTY$L%pTRkvYp30&tOFIs5Z86m-DN6Z0+(`ZvVVr6=7{8NH%s=4LCXb1UO{GQ1<3rZ2ges^qemO79n8Tod!m%sjI&&!%E3!njkB66vOixn*W< z$o z61L2xY?*z+C$W^VefBeoC}-bQ#b~jb5rrO21lXII*qd3{n^}afW2s<$&Swd+v4q%J zLV}DmbVTiDt#-42D`5-oXAAFV3vXdjiQ^qrpA#(wo_oPC-XeS0>2q@SmAWR*yh1N2Kyi|f-ef3X$* z&&v$iD+f!9!qVboX>qZ%xLH~}EG>mBEk!IXUY3?(mWmRV3O`Fld5%<+UP3A;wz^mz zd@K)6wi_;%2N%mjagGeQaxA`|`CbnCP?Rf)dUX6LL>}Y^1aRayBIFklQ|Sw7qpp!e z+hgg!B(4~sBSx-I;cN!kXSNxeO2-+Te-7vg=W}>dJ4KrGh%6W16M8hVCYxB3&8*25 z*5N$1xmMQUeAeMiL`GQO&irsNKNRMNllkFdez=(*8GKLCZ0Qt~Pxji#I%#H|G_yA5 zu{K&+8*MqbUq_n?Q(s3{X4XADOHsnQSCXT9rA+Vt^O&CM0RJroT0i#G#23yo^j7N|9Hi^PT+r5PsKvhrT_OKGM(AxxtCIaV630 z`?&L1>P@;LNA_l2)-I4ok=dgd*`t`)qnKF^Ei8w5EQeP1DETanHkQT$mPR{Eqk}z) z!XCxRHp0a+>1LVquuK-ROct?BdRZom*+!JGjVNW0;$x3e#vaAb9;KXZN8lolVq#xj z!Q3>n^yabj=CMZ!vJBf;h6`AR9W29@Y(d=2Uk}T$hb>4cdz5naDCKNT@>r@pIo2fC zi%<+@02X=zNJSEU$-Hj|B}BxZ*}NCYa%LgkkhRbHgS3R_aOv{s>v9>b+&Gf5SeZDI zB;C%mnTo_NowL$o`Ah_vMPhoqXh#c0AXiB^$NkL4%me6C#$J-|e3^TAC@qO+Cywy% z89jb|BA(ON(o0ywi}O>2+AfuAr8puJFH%Ot##yQYmQFiMp@Zc{Nn1KSI;7s)8Bl}Q8<7eujC$AAh$p{Zo&wJ63$Kh5t^KfoAc7qkDfE89I%1qS!Q`QGL|(lIx(lS z7L>;|;|&tGS%AFK2!@1wA)%6b^jidlC^jKa&$&-*DI0MP-f9i@bKhTdiReqGCbdOo z?KCo7Ox!Lrx68tMmdAQ#WqReach)nOR@MeR2W{iF>u6lJf0@XNvU+w#Rz|c~6s|xY z2xAMtRoTo>Cf1;BZo3`G{E;qEu2y1uVqkkBv)wSV#W1n%>(QRXx-7FUn^}vEti?vw zRwIuyh-{fDD=p!v-~4Y+Q_5Z+M!)|~IEpMYMzzEurtf5i81f&7Oq@n;t(PMrvMiYe z(j&CepU^w;Ca%cFN0oSrj8PIjccn*3gd1h%iGgEynKN@n)-DsqYT6;QWQ+c?xSg`= z89iJftiTh=E)}wEzBqcOC;9L>gHl^H?Iy zERi}YGN=6qwXO@T`>(bq^q#Bmo(Gr;lW{V7uFC^afcJ7}pfE=-rGqqHlCc`(X)^sL zJ1Vko&DFq)0* zS&HAD8+V{jlWNn(NTkx!l(5cnHN5r*hgR^BYBei^K@U zz}6MD8d&=9gu1D8$3r*LHK%Wva%S6en-PtzjhtmEC*Jbi^&M64+Vgx|> z1|!qM#Pl$;_t4|gT)Sgot7~FPm>36`a^g=Km(gv@g{Xwa#c6p{-{!Q8xRo6{{YzR# zqriVzo2WI*aP7TJsj0}4{S$eqoVFDFMF{D__g@|x(fdD%_g_p6#%PdeeVgUepQDC8 zMn`g+;nRh!xjcu+)(;@|I)xTJ&J>yS+@JzwcQZJKwz+h1rRk#QQ7)%bxn7H~$K|x? zQoc)QP3aL$s`1dH z0yE=iUH`t0`#Sk;xf%>AFZ5g2ns`}D1{j-2yMc8?Ysxk|WZsjf{aX1#%05NBEpnM9YN!lp3xDX+d z#WHdB!_3(a3tO)|&VFPnPH6Pq#x^%oaYEHL`iK_Qu6+~SqiPZzQ7W9T(Df%1pX)Ux zR6(MT47oTqb8~-PjEvoB`=|Gvq)q_kGNWCT$9yZj?1P3;7IZ&r+A(;u^*Lka7h8Fv zWj#Ny92i@K+`?~?#p3(3`kA4e-hzdEN7mNScw%NeJ$sLYt8|}2nkwbQav3fzC*l_KDNLK2X}%e-|Kzco82 z7xKt8aRBZ61t|QBiCT>E<;uzBdGue~Myf5GIudn`q+pV68Hv-iX&PUh^$N`Y%UrvH zubqxOt_UPbV@#dUcdAv&ERmy07#4$JdDdOLybq=FGC5k8W{Qg zPtoE+{UQsM$$d@5FMrO~tzyn)^-CWo*bgf=f)>;IEzl{B{ai}_$EniH@0qmb@O_!~ zX65hFeqasXnXNQ9hQ3maK?}*`tDxsA(0~1iylURs zKwxJlwodGT)SSbJ6(k_%ZI&rdq23$V!|U}y2Cfg1*{HM6*S7xp3qd*tgr;% zQ?JzVZdNk(FuzXxhg)*F=U=G(WDCh=q2hRwE|>1>0MlnOT7w*rCn0M}wJr3FgE>zy zPodVul0dQ6R2jICt87~)pE#9D7t%f3_CI;u6kM0h^W>u?7fK+#Jy*8>^mD16GNX0b z=g#|2KQ|YLW}mwp&%FSo50{s&q4c5nHNN zp6ru^NUR6%BA~Mx)6e~@w@}tPy#(A9r9;4G|^5|oh7mv>8R{7}_2sY05 z*m$f~ADy?MMU=<-=S$G}G`!Kdobksje+a=GXFALVo)owu$X#YQO`?C>VT3XRcU?$?{g-cG$i~pjQQ=2bUZ%$myXD-?<)BcO=$MwpnNZ9zV${{()eYDB$N+c{cnzd&oqhZ4r2dahC4>XjHg zHaVoIfa|v04_82YAjoWQ$D$}f?j5bjXhRhn2nUzB0 zh2|XU=vDc8^}UgEo1{lH8|2a+_T4GyI!9taed<#d2OXby6?r_$&1Cv6L4(QGirk`1 z&Xu^FJBx&7gi^&0jY|^R6fq0&qVb;`44Zj6Z7(&ds#{jFv8e5VEzDd`@$;Y7J(~TH znR%sq1j?i5UBZge{04m<-o<*j6Ro;XN-~~Gw@TTpbf#^3U-Za38wote`b+ozVq#5B zKde(YuUAnMou_hMpMOXdvSzlL8J-h`LuliLIWCg3xA4ZSjODhD_N}1Lfs5wnmcctu zfEwf@3}}N1@5{{CH3}A1+cR7G)K`h0(SJCNSKtG7ZN(~qT6Y!~6lcA)}%o{JWlfSPE=^E6&} zrq4XXXJ}2RM8^1hW{+k;>*uQQgoTh%l6!hCW=Rh-kNIRl{apSXtZxbzbm z@odVa{;4O>HS`1ty)X#dgu8{!I5t3+3qeznM__3#u?ao?HO^lN>i!DH-S~~_JEmSi zI(#M93P@OIt}so!!Ta5~?;iO4D$Gr-!JNZsuou%YFEt9Z9K#511LzS451Zi0S|DvS zi+B!b+zJb}3x0M`_#EarejXZ`nJ4%~VIL|h9>na$ho;P<$<%>A!CWUU7(vae(9f&k zF)SFtJr2x#0vK)vk5A6R6_@Hi(X|YJxtuXDjke*e0d>negwNt$J2-s1@M-=dZclPn z?hqfqyJh2$5%tYtK;If(7S@pHqFJcAz(zhG2;b@vDn5xL{b^o_XW%-+20s@4a#S4fTz0ys_(zmR~$m@wQRN9{ljX zYz19ScM4mbTvKmEKMk_cWVYm4^KAuohvIa(J%vTy;*wHdnZGo0?l@C1%f=+d8kUeSXIRd<|l8=apSobzi;Ynx0SeUc2yC^~^v2?Cd{% zS2*=U;jK5`{M9?c*4KV6{LL43?Y)2B0}p=jk^REMkA3Z{!m~fxh@0-^$AI4+@O!6l zm#_u;`FV^)?H29OgS}j1`Pw>mT?1?s{J+s2U^v>Y`6w&p%v$J)UQ*D;QW7 zRZVqTrTBTgz2fr&13p#2W6X706`yLKJY}hKIV%#esG3(-v7KJ>Lp;AiHB?_2s!-*c zE>-C1zkl`pH&xKiEMG8qz3+ZL>eY|vg;u?FicbmRCHZv~|H$33)m6k)b7Y{uqGEAq z(M{_r`YTqg)E`0D70{dUYJAdR@%@W#3f*6Ee~4cfQia}rwH;TYfAm_leKj569y`CO z^-OUv=&Lw$KgfWau0-3eOScW}!)1=TP{o<_%R?3YS6%B1s^azi_oG8shVBnl+<)c$ zp_`~B)E!z=dlX`W3v6&w2WZE2K?l&#(4x>y>sI9Ugl=`$p%eG-CbD&{3f*s3D|-6p z`cC2(Pu;N4F1B}ch*up~0IzsW7hi{#SKQy*A6kjlhdO-Nh@lQpzP-0U3H@Jib4OCF z5V27!ZdOZHmvKw+#KJliXF(UNq9moT^sodpO0f{;Y?bjkSRu1euVEJF+@x79`(2}E zGX8vS(jZ}1&8O3>*E7v?EJMF}|jCeNE9#{Clhef$=!sjWkX{n7~9S|Iq~z0hePqPpTE1!$HW zQA-;6O!`n%%k;L}MpcWV+0oJ>+o_*iT8#Y!gyn-&W%A>>iZciCqWHr%6RwphhZWPr;F}3xK)?ynSwzaf^ z{;s^yq|HT_*etlDMbQe;IbYuBaJ{b(zt7AYRcFSu`n*wXu^3UCOHZ_&KEG2aj96v0 zwO)1AtF4OG;{Hf=DVojw(TTQa&p$xFsx#|VU%fh0!L1*uK0G$>BO|UImRoJ^$gq*u z`LxD6hutkM?95b#Ju?fjQ?Cq{)%$Q+6|bv#9i=s0)5O={u4cXq&zzTePDkcB3+S5R zg_$d_pz{XdJ2qFLuYP7rYkm5k*sjP%rc^Z%m>f;!r_5GuFV*U2LJ*4*#Os;OEkSp% zCOi|H=EnGJ(QC-=l#7KPlR0PzW_EM|bqCXu>JHY6)wum3gCrJ*Qtz2WvsmhPh1`l? z@r#H3E{F;3Ns>V_q&^5?2mewZ1W1~L&OoX^pj0bLwKJG{Uowb?#KWOfpE#;iD&l@$ zxxZZOm8H~CeQhhT?n-5!OYBxPe+?v_id_CfR-6kBFu*lV>EwBk+7m^*Mu@=K< zvcp0$(J?nKl1%V9c~q^9X~o!-Hztc~>DOW(36-M4ggUhv^Qfp^5mO7#XmtgnYMr9Z zgS-?sYO_hh8`as0mJi8lc8qF^u&pZuNsS40o-^sRbU@wJ*{-Bg+dzByPPH+iHoLS? z4Vi)34yQ{q6eh?J%oAJ64e`e2rkV9pxZcnNb~KS`C~Pd3ymrxC4~t+b^x&Y}K)fg< zd(mX7gq=7d7ux)--OF1~KNYxYaCPTrZ%!nSf@*>2K<`42Y|n4_O81e6qdgni`u4Az z_u`1ZG!U>kty`Z61{V7*g-XGbJ6iv0aYxuUr*G@PzVDTO*JM)jY>Fw+UZ(g4Z)@q9 z+fW?pT(N6;@}J6oZ8H5#3K4ycLf^!1%^v_8xKTkJg+^bEndC`)<|UGBCBj}|98DTw zdo;gsbj0CpH5NoP2X^CE@owA*vMyoc~<(xCw6DSBwd4T zsmJLWHaaS%Re2LyC#W|ZjJJkyAZU&Vj_PN1bka}$I1a3yQUM1f+ViA1$XMvHOQFho zsl`*ogsuTa^F-amiJ;_kQT!8E_QeLixMKO<8)C5=_AOuj#evwq_1m`Gb^Eq0o5VuH zFO(1&=dnspwaYb4I)B+~W&6P6n-?zJ{P@7YfxA08?mjRu^tXq;GIZ$B$Nk2`B+2Ld zW%28mxdyiVzKM5?e>A>^7-gaG2O-%&gie@8lLcht?QyLLVqDlbQr_NBP!Lh4$F*|P zs2XYH8wiDUBlA(P$dN(ic>UL3YNJcVSEV2(s>o)3&GFg7HZr|k)-l915c4e*^7Ul1y! zbF-yhY+_awWmLls?iR&^O)c=^X&dFtW%oR(#Tl%$OZQbTTGhVdvkNzWwXb1whwQLN z`V&hwEUMf)B!0Xj4{;%k>)__)C839Q z^zZDgwG~!JORY+6TW{@#J5Fp%yCy9T04h2jdjOZs}}%<1hbQKq}>en)hmD=KXm z5-Z1ESU^OH9{ywM*^{SI&wg+?O2-R-JSMUoxWxO7XW$ek-#<@sHO-Xj#jxIna>-Tb zkzmod4Qn!Qbyd0mYoY^J*4JM-5JdxA(^E&Hhd&VKoH`}W{$u*3KN(BC{*|HB>tjD& zh&I3mZI<3P>@_}zy?lHdiAMDo3P}giw$LIdfIG&RS_P>O$5h)H%>^(v4f5@>!SLo4 zlMOC3LgEZUAOwk19ZpTEU?FR6@tVwrmLjjY#!V0{Afma`MK{i)>4p}_7)db_!LuHJzW9R$CH203A8aOgc?zGwv&;Ly%ejIYfYXU8_bgbH$cm2C+@51Y5bVGk8iCSCH$ibcrj7o2dh? zpp(4n0qLtD+7Y+$=|Q?EEF-R0hUEk%_k+*tZO|=eOzjOLNi;il?jb_bAa%4v2_EG zfl}?d!&9ZWLhp!=aNBN^5r9*h`f<2T+JiP#3Tl2#Gnhx|k6NS&Vr0Z@CE%M;E5bQx z3sEo9tv-6%_}f@5QX*DsL{X+&tu#uy8JItY=+=QeQ5NxMpueapy4LEbUvsjyT?ptm z=R){g(2nP?n>a8109`eN<&;araUIRxUMgvHpTLlmBOUBU_u!6EngoGo75GnS!~7jTxOdwRcFf0i+qUoTnE%l6qes5`-6Ka%NP8dp zcx2V8k@F8fbbe&@>XGvgrQS{bPIQYdEbi31==0miC-{spWcONyB&K6UGzAXI(3n*6 zNrV-Mu&5TrROcDZU>i*uoOIS;hG2W4w+1H!1o8(jAZ87H4S}Vg(^xOQEeZKzm1L9+ zM9eHP4we*}MeiTrSl?$W5FFv_@D027zsyjx@|-M$EQ~`&!rc z#J>E%+Q(b1ZcEGYEvuf~++N+i>8jMfOB+f0#&-F{BOUi{+d6;e_9nltE#Pa5F5i1o z$7go!?Mc0(5O{{zk*sf=ST384gtw9c!B#R3a-&)h(*p4P?wD3WZLg21)-zfa+8)zG zo8Le9Of?5Da=l%ZPHGXvHPMr*qzoG*8No+X8Lo>);Gl7sbHaH-COR^rB4A4uhGhTV)e&Xdyg3X8!S-B5W& zgd8~#ZKEsPvVWj|=+5>d2crEkhxqyN6S8cmwWQWteb)6~UJ)61>?a!|%Wvu*nA7eH zhL-NRW#=A~wOE>mFark5IsQGVYvbc2ZNPALs;}PS4dH+l<{^|9+FF3W0E)mchDUQ1j|#S zu(J5TAGLKq_$)D>|3*+FG0g-%D={r-8cixe))Y5F6yz5Q)BN_F(aK?P%Mp(vEGdj7 z%M0nUa*AYdk|LBET^_VTplH>dP|KaF3o(gn*rWs__Lt=I`!VI56~+4J!|<4a}+V7KeK8yQOv0vKEiYE*&J-8B$UM7P)ofp|!-i0BC_Z zM6hlB#-Cx_s0rhKNt}#mVKA`ux!h3IQk>bb1_OZi7uBbC; zwXYm{{%&t=(aIf78=$E!0weDMc%f)4V~SeUN&RKvh7!OZs=?Cdgrg)J+N;74UxzV zk8It!|IwWtYkTH+y>ohRl^##@bwusZ_ct5r@<034ji&)v1+~k*REesT{VJ2uNiy6EkFy zOtQHq4DdG3Ksf;d$s~Q{h+xxp(=Ki8-F;*kiCN$A)SExHiBqKTv3t88jQ4GZ+%2C) zQg}n$un0od*7}7v4<1XM8awQ*j$54;`^{f@ezSL)m!)tQ%iX|W@6kiC{$12(#y&EA zfii%xu`K#=;X|%kxdl=JL}5RpDvg@eIjR=%CJjC>#6ZpqlAKd8(dF=w;nAE7r_Kk$ zp1o*O0dlbS3Q2{UQbtWd`qh3$D?;kkQe>ZkJcmU-0Z>Xw*r^y)s3-g>D4NCmk!n^n z(fpA#EQn?c`8ke8?K!wKDZ5Hx3NON@P(L#KlNsEpShXv+dpW>W{??S<;p?QLPj<;$ zsOB9{6zOq!v^JTc+D9ygev@f@w)7*5ERP+QW$A@jsd#fJ7%xfvGBp~g2~}Igm3A6e zKPLV}4j5kG+;3?H4XY(F%}Ic`ESAaaPC>!WDM!bUq`Q?-$(L!Jvu{_T`PO=XsC;X! z__>?|-Cj-ULo>NW^g;wWYsnLlq>>H&vTPYUY%)pDjVF+rL#tC?vxmxJzSQHv%6N$w z5Q_rnL;pm|unV|2h!NT4dj47~gM})itguk#fJd7V)2fK`jWMO~N_x0_OHF z`_i)a{;+J@_K*wN${PEk_}Zm2pM8AArWTu1EXd`x@gcwWwePJRS~c5Bk%c6-dX;$B zEerO1(eLsn&i{4_`_bpY)G70m#s zRKto^L~idow$?LYc#x9zp~H)j+F7i7KpUd)K3(qTedGOqB?M?!uU6D0C$*}=kJQjf zVK`KE^%4?zadMAEzizS9^&MwXg*ldJ>tM(qLk<`o0+d!DFKR zM;kkLKezL~zB!LA>Hbtt?ec@KZSDHZ!pHsH!GV3NW~QD_{p|JBlkeWU;_zF$mLKah zxlLWq4GyLL_@hnI%GGx^+%RV_-ZF4t%OX+Tmip~WL(7&PNu`eM_~SEMTf(8nzPmd1 zzI$|q*EMeS+HO1i;!4pY1`edor_^Id{_U}@V2LubHc&ZmLiD|~X}vcf-DmIG^%U90 z+KDmwF!DG>7{mXZki_&sWR~smIOlX!b9_YcdSqnZisPCB58=SzL@6`L3C=k6K^6<7 z6U-uubh_$XT<45kQA;Jti+C7e=)5Mf?5I|nH|L?#4XC*+ra`&L@2`X zAq%pXvJ^<{7}9xpF(}rGzqL1dyfM3Y&K50n)jIAS|N7lZoy!A+Bo(Co-FS+`^L!f% z>6X-eB&%Zv6bl%Hmw*+PKqkvjBhid#DTz-RMYIZNqKU*a4ykNz9I1;Gn~>S9Bm2_A z-Sk5V>l#(RqE$m2-S*MpJa;vea|UD-ikk;mHVZ%a$+{X6>I~MnMRX! zi){8Ux~s2mb60Tip)DI8vFH^)yFinNkbey$FQ8+mQqY6a+^PxeHeq-wWJIRbhMdzh zrbZ!{UI-_H9@jF%Igy%gp+u@BUr(g|KJv_bT?FzKwLljE)5#P6`nglz#OZw1qzs!) z7Rsa+D8sgbd<1GZ&IW3NW-cHVHkobM>fTGxN<$!K1&ul+g+hNid5UBpjWE)Pf`OFn z0$r>Jm{@V_!=ar=!$^+$S{4noZaw+=D|;V2edmhDo0JmMqLb_P|GTzQdil5*d~R*E zt-2v(aoQ~Xhu{Cochqr|ZdiB7mez+pcuH&)r^{UK zf&X*Da31)$l=6shYmi^?7v&!jEzdAIVs!~3gxyL=91$cEt!}hBuQBNsDB5x(JBKx; zE6Vh|O*R{y$p&Q3ykzi@&W&%CEWG_t8ltW7l&wm!hYL~;TgYh-+r~$1A;mt8YS~|! z7&APHwiTl;DT)8gAd=gzqRDoZT%ujnA`q4=Mdtk&=}xD?^x@r?q*u5dC&UkFo3hxe zU7l$dH7AbW(3U~y!OPHtI#ezvrxBfsbM(Lt(@@YjoIee!AgWQlLC^y?>%p*M3E43e z3(EOoS_s$-co~-PQi{>~%v@3oqsodwrjhjGpHDq9MK3O+7D=cIW4lPGfU{kY-lF6ys4M66iGFHO)E@Dscs4>Ay$`n9_?}{(gvdTc-&Q@bDkTvSK35d-9bn%j;Hw#Sri9&EF-Ar@wkDP z9?6(&1;6|y{hc}Q;Af-XtrPD^J&LG2j z+9B0csh}AtDT9oK&8bQ-5iOH>CMRNIJv+#-q^8y6_br-M-Q7`}`d8|fIFz_)+x*rW zq{Kpt!x8CSAX}kr;rx$RE!)-=02qh6M_1(|+*Ln9Ku%h!rD=w^VCK`sA9{$v8kS3I zcY1&^FYTIhyZ@$SM#2NBfRsgA?kW^DKv@70IVTZ0NNg&AOJTYd{OYBj92j#!1{Lua6iyBy z3*&Wa<~(d2F4YG0li{W`OMuc$@pRfhGb-y&!x?>aHZ1DZ25P6R$?I*hi;sz4w$1W* zn(dvCUr*RJD|MUQZ@2p#sSR^;#hDW)m-n?zsz_-}=h zK2o>bzUtg9Mgp){cj7d%Mg={^1YhKYYC&&`&>Mw-3wndJpk@IoW8A{pCr(v9F{67i zrxLYGr|hVb2-|HjH;%^JaOA1hS@LmAemSSz&wZTW7L!Z@h8P#Z{JH@|Xuyk<1({!c zygfv=K?fh{gnv2OYlTk*0MW{k{YxkOLr|N^gg@K6a#0_gW7C$+I_OESUEPoT>MKKU z@9*y3|Mt+(+mCcV+;Zo!EnALmYH8VYbjy}wceY4xJ}G*CvT@^2Qln2knfmn$8#lfn z7C*UX^zaQg93I`X=QmFd3_LlS(WwC1UjjMq6_QALMsz%Yl*)(_@Dic~cFyGh>9>z!Z!ynUf6b6n9gBMJ9&_tl;VDAE@5??A|5)`=7f# zwkXOXv(pm@gacjsHZN{j^YF5!ULSa2HJKW2J95v?@7~oc8^@m}o;*jDEG6CdZCtkX z%Ag6@&>-wey=&}B^CX6n;Y)F425Zh#t^g}1%Q5bRWbHI)Y=a&ZeBe11AkQbO(~z={ zA!YCSNLK4kO2gA4buj{Yq87oHqqYBgo{9+ljmR?m1-xBuw~61&xBo>v{`j>}BCs?x zw<7J%b}&@v7LxdX%OV)m)R`TkY@?12!r(9>+6rPXLL*{t1?6XDQ;8D}8NONb@_21% z`XzYm5Hl8{DI310)hxQ8eNk-X(~k}$2DV~+=~Yi{Au2V-$D)gNt(y1j;Ye4U9g^`m z8HtJ7RY!LA?7H=;64N+_Jf$NRn``dUO-l|uA)C%0VeJ!zO%v}J-bH^BnEaJ&q5jN@ zb7fH}d8%rJ0EU)Qga9%uCU3Pw6qie?~J%htLs~cvW-qHP)RVT+5mbNcq<#}Y^f7jl5AO$t~GjH5+(aNegG`W zRwPl>U$coTk*>P2b>$ZaqJi$gRh>ImCVu~`=s?ecLfK($7`iH3ht$32`R!W|WJ-`` zT(iEtwZCgY*w@;>ZQ#ilEjFhq(B@Zsdv0s#ZHgP@U-ykW=Tgl9{&Oin;g=kBf*4GNvoY0FD4kEySs=yGR9;RiQl}DDXvL<_| zL!!92Cw0UdEK=$eu{X6vf$Y>u<>FH8c+0)1BjP?+#Ep^(gDm}k-afu~>_b^HSf%gs z(KTc5(Uy7DfHti`o4lBef;cu;c8X(a5o(Db$dpl4idae@E;OKfDRI$FZrIsCsiv8B zai_SANEWrF8g&KJ2{rZyLq5HJY~}dtw55VV{tt)bMbK$CrsHrsw0s~M3mH`&`SM`6 zkHCIDy&Y9y7Am5)l98g3FGl$ohD~d^-!Ol?i5_h@oIiFPRKUNnYQ-3{)+kCi-*NsW zYb{0_=|gU7QioAVG=>yK6P2`3jWHDgh~%7HRMRpd;VU30C30erBX4xXt{)j2HMeeD zvVnB^?Q2A?$WDDA+UUKh!{()S3``16eeRkEBp~llnJbf$4TDYTo?z z50Bac_z&Ae;X&y4iNf*R;(LNd^3D!s!!$VWvGLk+65Lp7MF+Q=HFyG+g)_JG=jYG*f!Yr4qx*Os4x5-h|m_;$aC5cIK7+FS%YawOmZK!KCM#>72^__;Q0wW44 z;f7F#0n-}*r2`6EHcO*cg75)F8Cn3~RUecNJBN+7LK+7Yw5l@5bV)*u(C`GFiX%rt zEu?{Z8tJ7$!XoeF@I(^_nuWU7>1e&V#aT~&d1Kqguie;fA3e746A_0kU)(KQ z??T`4B{eyL8B~R+ue&;}oF(XcKJ^_n30z-?t`?!INJSJW8busrH>ldK9M6WM7rxAjhOiqugYLIvtvDMkEQCsBT&J_nXwxwQ8{c7OoHL+Xg z^zOfN;oip^Hmzt67@r|U8$Z~wcFvAdyHoF_ej3`OIGQ#b*>d95;MF^ChHP#H|Lz0- zf>e3LH3UUepiDimlbTdAvyjfyLJ$kBh+>Jdglb3fG`|GNQ`P8FEje5OXeLTiVyGxP zm{B2YoxkJnw=daS>#)>rUp#RCK=hT7){RlCTaNGQnGjNcl&qVdduVBq!*@lYy|8W5 zW6NKEsZjAO^14byV~xF*rgp^yPw{)aIn@EwSw|(KUlNz*?mj*zHnmU zwovVkg)8>n7!yC({mO$&iX7r=ME3KuJmt;Xe*EaGryW*XtImsvTVlG@@>p;{e!N4p=KtE1WbsY4jDt=g9&ORbL63 zvlQI}Qnfo(4^ht$J@T1q-K0T07*-mv% zj7jH=?_(C}EImzQO!zhi^SBLGbq;5Dxf78FvkE4p%DaN zaX7C`Ql3T1Kk3IZ9yL@ic1lw6$ni*LiJWh7%?ma4wgkig(LeR3En>6Q+u%P8uc12V zhEpf=P2q+z+3KBh+tNNON;v)2vE_8B;h@!zP_;KD$xYx*D`v@lQg}f~b`y7Iz}-4Y zAFh{2lO?oMj!bV5bpTLy+Uwhl&n*3EtT)pc7_2Kke-=Cp4A+~AHK zgM*)WcgX{lCEYDO>mt!dZ|(k@n-h_crO<8-RD}c4Rf+!34>S~2FNk=m11_VycXQ9q zfw;fz)`5nOYWvP*OXf?)=7gbR-IpG`ZQX+pviyx84Eg}JqDDZ?XBBuznc@QCoG)vX zgSt@;a(-BILaWG7c!QvS0rbd6BjRM(CX<9T+E$eIDq&~Z2-5ZR3Zui+c~ni!Z0iLUzqsqEC%p?i9@*bISGHIIVuRL?AMV@G z=5v}}y%Z4`DveB>H;h6o3y|MKX)~4iQqG5LOJ*qC0x`t+_a)Nh%`J^y1U&#_X<;Kb z6!`~nOE4U*P3;knS64+Nx}cqB^XC^oLS1F5aQrMIHMshbiFc)HyuXxUEE*`&MM@vA zqc`h=bCcL(YB@r^lzwqZb=2i;P^@{9e{mqvx3KmVBPLK_rlqrKuFqtWOJ1&U;yos(AbDlcLs$6jU`i_B zGroohBdvS#K-03V3&$Vhqru0&+_vfQ<>MdVh@u0wRv^(de4`;*LqbuMLmkq6MAEORX9pF210PUw5`%Kc^n?W>~^*qs(AU3y=+HsQy6O3cmM(qh`AwUC{P5DH4?lm`b8r9Z zN6)>D(t05EREeBG8_Q9(w^B&r<7E*IpiwO*(-J^I5ep>a_USlX786mDL2#1d5_163 zSi+$SgLkB&wGv9QTd3?u%jaCtbO7U|VhO{>0=?)sGQhFj#rbw%ddeJTU_A0_)wT?d zzw(PO4K{3wv3B1ZTfMYr-)*frnos$S|4vf2uVW3N`Q2yt_c)bQA<5J_mpcwn|NU2k z*8tR`zuQwKj514r!LCpDH-L`0sK1ryF9ZAzFv?vP;{0_PwwzG0@W$w$;OA*%~%=tUtN0 zckiq<_bpwxqqg-EiM5a45*N?ye)W+alg(+<&6hZ8cQ)Sh+~BGQmPZTihM>)I#g3yH zlOi3I$%G=|SPo9IYe!z0W_Dz%CNQCytq9di2%5K?^+GMsBgS0q;2@W95JfGfw0p-` zi*5vJAKq#$a+pkt+q&nQxhk=$w)<8?s5}^uMD3^J@31OEmnj;KLe3g!fG|cBjz>Cg(Ycomd(lxPU;+eUk#za~aNZn{e=2G)n0 zi{V#9E~U<4$yG5OzfF$p=FE~M+^k1p7v!Qh+I-P{9ozOrI+w-btCz&S^K{Q6wN_VT zuygy`%DLTiHyjGWQeNRhg15FTVU$$WTV}51MY`edIad=j^tiTmn zw63RX>(VIVGqPjRiBW04u@8g6$gy)CfFemo{+75FgpsF`ud0|DV7L#&g`k*fp#&{R zDYRmiD1!Y{W-F2`VZs?aUk!V5OtVYwu!uZ8DfPB5(&F!IvYWeZ-uxf|{nvr%pWU8% z+FIs>Paf}&&kb7LP4m3lzbGBE2DzO_!K1e!KU_yZ1Djd_+DQh06W02aAh^THgf&Eo zj8!IKtrgG|2X1X9Tugh)%%QFZM{Uu3h)lG9N6*4_wYuzgpIEu#$o4Mrlyohr^7ywm z?Cl9SY=*DW5pu&7)wdoeS~dYH{1I(*BQ8&3yd8;aY9A%8Gx$$YymXltxo7{$6VH70cfaNHzIx4HW>L#1 zFKyzy^oiDA{{9&Krr8}9nj-5!eOHm9di9KT8D*@$Lm6u?J{prwS#y0K<*e0UPR5!` z36QB0(^+~3Nd{goMCpby!}gA7P{Ku+ULs2GpnQnP@sHJ&;ow;6!|G7DB2AUg8}5+| z#<7PDw`YiBSTS~hz!TLro;RG9eFDv<1bDK7BRm{VOep|yiZR1Thi!S{BvQ-S4cCe- zsdw?R>40Sa5UQ*dkBO#8b+9`12XSU?xH>2W#eXBXRxthxlN8qXz2mQDpj$8{usl?v z<}f1)$iix+WJp4&`Xw!*vM{xfig-0MkF;NU*kUH(xqWn%$6olo`L<(`R{C8rsTE7P4>hRr0`j%+Az|)MfT(-sSzw& zKps6onGxE*C`sKW-IPv%zi$~oK%obc)b9liJ9VI4I=0n{S(*M!lKM0_G!r#JYF&)t za0+~os}|L!m>T10N)+i8HYS5HMA|~I7Io4EjaoBNOaWffP|Hh}r)i#{6~n%9JqSVq z%P&&>bGZRq*r4?38eCH^t(kLOyyVC~lAQFej4RIYf_QvE*r~*C{sf(S<(nn(rBaV2 zxS(%+*VkTtp0eEj{BYmkK+)PS-Lly4Uwq4hw-yZy_J#Gl_wz4*t!sVX0%T~dsYBvJ zn6q2}Ih(8+f}RmN*XKV^t(p+6b_@rH?Dmk$Q;mfBUZT~9RGOsQWJ-WP%k*gw;BYj9 z9&K@Q3G}g?QQeJN4D^A=XNr_yv{S3pDT25VI0YT%DJtCYbR^YS#6%k#rtZ_YQUUmc-fG>&D7(|Ae3BzVf zVG&s-@jLXfD-S+#m1CzwL93K7{0rM&w%XUc_@C!eo`Vuv!~~L z0Lo=PxuftWcZyLM!lgO*5|?I^(@B8r{0uX`u;WV)y6UAxQ@*fcx8Qpsm?Vmg;+bYR zJz1kKnj`0*k^Llc{FNQ>>VpY0=8pP+I(r2gweyqL$502EDIH~cfil4f8qma0Q57;{ zNYm1^v?>U)Mw3Yp##F$NmGZoE0ftPqxh50+`1*&p5C!s=Of%!_A2s2o8tH?U4gX_( zVs6JBp^LK3v5gD-bNsLULb9&=!IzfV-nZG_lMAgECY_Zc<7*bl^e(E8?)HnWh4~uAPy-f8CT6NJ!vg(5?L~XNdYDI0sss8uhCqW%H(jmUAGhF7Y zM$PlEpEgMxWCawZ4G4`Pnnsh4JSgU+%KqwBBkyPGpCfTlcP4#_MV+0%L`jg{>>?^V zdEzc-Ub9(3s)**~EAsi?%rK&E3^PYzy|^R{Gk{#l14?0h-Jwlu@2^FrbYknGo;wx= zy^5%kn51sAD)F$?LHlE`nquLmpj|0Ailb9NYi*xfJaBO9LVRv2R$1a{=-awz;m-M# zrY*NNt!-X;G_056d1i!{uUrvny0r;OTj;`a;YE3a{5m{io3KGpt7BRNp!S>?eN{zN z+mRK+7iwVQ@P!(fIIR?>bUwCqGU_@+bABzM>t^S$%~eU?Pf<%cheOeq@QIrF9e4CbqrG=@ zbllMs6{Clmc6D|Qwj2#btw*aPk?=7kTB5cLcHtq1{W0Z8Z6s2QWSsc-9d|BmXjpn@ zN5@^Xy^CeJ8w1-rjYkoq3<${zLNe7c)fd-lLA9brcu~M$Z3Yeqt|LeZol&P_k}vcY zPShWwbhRG^-Bha{^3zc$jHCKSj$QneiZJJ(v&;y+sEYGf!7^G=X!6tpvO~d1H z2ZqP*Ri?Q-^|sU&u@|#|*NTtQn(NSPsdW~MxS!Wc^iRW#ZB}en|$zt~wOec2c_n9&XXe z6X(u9^S{}y^eXBnPHHn;AE^x|amjFjgTBUPr*#tRtm&YnH%f;cGa9Z~^od@5zJ%`1 z#7m#%3cE;pv?7 zJk3#SOswaRJ7o<|+QRGME00N-Sgp9C3gZx7ob&ReG~6pf&GuRg?1_h0Jbo-Rr@Qvm z?iEdi?Gb;d{f@^5);-YaRubE8-0`<%Gq0!><$-PUqyC!t+m3Bmd1OKN647E0l-L4( z&(b9+Z=KVd@JFI$-pUnAs+(&4wnZh0wyxT)yBqy~HM?#7)sYHsuqogTE$y$JRpqnw z_}AUiyR9K`-Ry<8FR2X}EQ!vtK2yHc8j3UpnmUSmEl!JfDfCVf-jd%m_>GUH=Z?~M zK}zHFu{rZ7|<0Yq(WG;9)goB7bh zN5r#>4_@C$P8=iK z_}-T`7boIK8g+5fD4o=!p_2rJH=$@Vu*-$D5YnqyNO=N7dC&4}yeeD4jM;%RqA zHLj>lC)F8>T8{|~r%rv9TpfK6E>=GS-mXa*p4k+Ktl}^$t4W;W2@J8BaB;)+v6)RI zs(Q^Q=Hor(C^3ej9r!dJZ1~(OAc7s3HRXH?)2@YSi8h?3+!ZFar>Ev&a&f2<)9o&- z?DeKc%F;d%qL?$J4FtD+!;i$0BS*yI=QeD3F7@jpM^f+nXv3bq1HXFk!CyVm*Y^Z% z5A=PQxb>lB-F>yP)e*Tmw&(K?4@RyFDNbwc-E#*XxwS?5#X+&;C!06@G&OqYQ0g}? zY~K8WSafJ`^w{dv$3_PSe{*crs$;*|v+~fE4yP>?_1p4C9v%AILYF@h@c3IdJr2== zZ0(Si8WiIRVB`qCl8$+GS|!+2s{?*i&g26jITIT zIrR!#4i`$y6d;m(`6D|fUro*>IbnU{m25!XO|2YC^jdtMf`Sw zl8<3c+D|j7n!fsIaP!Pztuk#xYSVL1^+8{Kj1g}0PgHa4c>am_C(GB}*1A51Pty!` zKKZwEjxAA-Y^$A*&js{H{GSMI-(%?8{Ux&;Uh_$}UFj^bx%NCV{xhq0+n$EjfYoFX zL$aw4^xG)(%QqX|<@jE3XG8dK?*2w`O?5b2oBFzVV|BPTeE-x#DJ1@oBKY=Hi^(KD zn{xpCs0zmoW6~&ee}+KcD!_Mmk_G%VM=O0%Lji}*XhsYN=kq5w@-dm060zxl@X66S z6dVCZ89J#*D{38I0Pk{;c3vT;BOc_>^N`E=fB&;TQ%%J+_}KIRDehaq+p4Z~_c=Ox zSbjKl^qZDW_A@OCNCgXop8^-+%3MBpun3Z8~@EI5|EK$SF4@?Fr%@cRqpNMo7!?@5m^T-5T2hfm$JIxf+wEjhYXekCLxoHC-@%L@o zj0Ldo-?MWx5E$JF=kjRaz?N03w$LFx)VFhu-@j&OU-GIF+#!Rfpm}H@)Vg$%NQ4Or{8JeXGVx zn=l_5SVqQwNls|6VNJ%rxNT0Du=~XQI)nZgPopFu4MJ0Zp@j?;Y{SA(!IoaUM51Pw z0CtD($jWvSkWiwG*0^Lw3=>bPDa0B^Mte$5DmZe0Mkp4XWzPGiMz?%oQ_ng;3L1LG zdvAGg)8_rcw#oa%8w56be{{I7G{0cLWiL9of8+5@SMCL$oe(#nn%Ob9??Gv&vT^`8 zsg!sDPJ7cCxdtxy8MweYA9=zNk*n9&4 zPmkLs6$*_z%cg#42rOOWT6WoprwFbxAA%Wwnha*7Ow3SR~QYB6ym(m8j<9B$Ta!f4rAM z_>^EX><^lo3xL*k^vJ1;_|{-@GjQ_XAN#R$^vG6mi{i9~?Xm2f!ST;cl2Of7gYoHi zb#H@C#c(MC&N=9_(1xQwk7 z8YfsmO|*V|;Gchg%->yAz3ssRgSvcwq`EpHSq>cE8Ti11#E~Pxt#_P7_74YS!&igG z`-NA8fOtFF19?Up&Xz( znDnqun#fn@DG3`n7h#T(A?Py|*Di4mtsPxb+gWMecFnN4#JuAZcOI$UFy*ffmz#?M zLBHE1nFR9*aqFtBmmuDQ`hOBKz^;#>l*160XvJtFfZmEZ&|5JFdMgXWEC70gD9~A` z$prKkw{UgAQV6L~4kpvVnWtjDxx-e~J9%hkBbrf} zs}0h}lj<2@Q&L+jZq4;>Ve`~c)D`dw+o$e=f+jpWZ5PRrY=fQhv2e}CEkMpW zQBVOW$%MORFuGI_mrm!6GucA;>`ai}-w9(q(W$ou$x&17y38Pm`pYbp1r}$?)S7HO z^r1Ng(0f|^vblQltr$ogvo}~AX6^$yrqcF=O4~m64JG#_)*F@=f%&u1aiXO-AD&VU zh79`8H5-VWlt|l!>C)w)(dp{J9O+kS8W$QsR0`C1q`aoy)gE3%z*|gSgkT0GyIuBl z;q?|<+*s(xJLNEimbEXC*4Sdpu>#K~^(8Y%tsBa*NY6v(itI}`=zI)3{32X?F37;u z?5Glg5L+FHEe*?EAa!3TzPgJ@w0am4rE4{()*|q7#(EFVdd|HCmy>nt*~3?xeSr+T!JI z#H-G)CM=w>kIko02>mmtFTS0d(dW@VChth`{L49bUSu~;ZP3NBMMH2+pFkKY8AuNPUEq_J<VYtju7OvPJse4x{!xh4_<_= zm<0^T$-#gc(qKSPGC_qIU_j6}X)7-S49JxN19AZj$VFg44fGpeK-hu+7*K;t^)zrW zpb0P@cjqH4PW9}nNo^@SAcUDal(2z0k%3D5kzo6)Zdcg-b`Fdnqr+f$&0zTO2?Z*M zLn3iHROY0^EKsBc)8Qk6B7qK71hz-Pr8(%}6m(qQ(nG8am+ z^*f8X_m6Kx)`8Zw)%cB1nP_SCa?<0sp6Ygl=?}0$S(kPW#%iN+Un|g6u;2nfx1*-E z#Ybb)CJYo9i^CmMAd1RD@n`BU?$#{=suvj8O+G^8eJOH)%HcHuG&{=vHR}j__y{9WP90%v%R%w1#G28H5mj>L)#*Tq z$_{K4Ac2kofJ3+pS>z&I5`vnNMV~p8-qcWfF_d16%tSN&#w79bNz&{kdV|=qg8;8B zh-8hmSQQf^hrCGcN+5a?a|C62oJc0fG}v-Wktu`U7xWqo*zoil{6y7*$j@j4KDTd>Ides;38w~yr59`9hLCu5ox^sxHIsudr<>8^Sts)#Is5yk1JCOc8Q!PkPF2R7s`ZGB#^pKY@FNyBX1>OF1ZlW zBG>6O(a>Ju4@2iV`^GxM7xcMCm*v2+ySlHZXYt~mo<9Al%KdAC>-*g9zV*RX`zt?K zMsiy#u`lg8cTI24nl;GU_~rBmhL>R%I)QcrxJixxQ_ll!Qutc2#!#ZRp`IYN01*xp zFn-BVz<`BQeFhaaQb1rFKe`0iJ1ICYJ+yQv?hwPSbY54|JEut=)`7QxBkgkO4(s6M zfJsZ(V02co!Op%i`RFeL9-nYrIBQBGb4~tE1q%D60u)B2aDdOJ8zme3`Y9WSt6R?g zrh%(l0@sL=bFN_4flav9+#5)EIJam(?1s2}RYB~cV2~CV$bi_SINlYUPqM*w{Wsv* z$x$G{4VW$ZDp-vE_JJi_K=yWlsanGQ1GxKp0PnPp4$n+KNTf{^=R?EWro@626K42#$gzoVypZRkB>&v1QT5at(^oucS7{Z5L&1%;2vU0193^cMmBs2b<)z zSfl+|qkHCJw~6W!DuCz0S`9PLhrWlgzYkB4>_SSi?7)I6hXD^B&$kxAIG%?dGuGLe z0Rg#)gQYgT>Ix5KuDChI{+MQ!^=qy{F7Sf^iHj#N9|@Get)!a7i{Or@plC|x1AZlk z$*>VJdmeR*U>j6(OXCJ_XfmYcP`?HYPn|dKe^;Xs(Dz=CBxBz~zZW63v?qZtwv%m> z^2YPk_4+jbdo*9H^8EWRXunvTegWTm3BK0`EyJrOpxAkTf!A4bhVUD?4NrOIaiLJB z45e;1|7JEKoP}%uJgYTHPJRD-+C~xIPQQkBtpR8Sm16WGP*K^xC`HRC)C5{3g__iZ zNtHRN4KsmwR8r>UCUB&(Ri>N4V41C*spi#a+3Js)WV#v?F3-o#sVM) zgE1*vojy_gcI|naFG^vnUb1Pl>f6w%M%~*wZ+VRato}N%%OzY++cQ&N5MM8FK1(6CwH?$4eUHt}z0f7h(UEV218_02#-*`U#jv;cl5(8x-?K=!dPDC<&H#) zO)hDr5lO)X%1v+}%B_edBXEp5FE{m6sgW59?@<8+b6R{a7Uf13{B&-EPvO$6po4}i zHXqGJ1&0taf^Z0fC@7H)^GF z*JW8hK0>FH3k%8KVEvhXkMiuHwMALLGJXrkS>7;+~N=2-lTAa|5h?iqwZ z>UM_v3FTx1yqs(+94~3)PFpmN$0T=p zAb0$2J-sAlgh!~lIMo!VJNi)q1l8$9yA@1M4UOE6z(Kid2?UMLDmRCf#bAE)&z$0B z{vq3zTj(rkn-mpk0bKyiX6P0(mDl-6cc)h0$W&t&M!Fu2 z9y?Q~6;L<(knRO(1iBQ<6T7hCTu#^vC_U1ImrPS1cp`#9$cuQUK0p>B2@Sfxp^tV2OY%3C;Dn1_nO>V}XPz#NYVk`0A#-Bc?S zCRL;fK{$L!keWdHuMv6;6`G{%KXThqC^ei;1ld%gDmfiZp2N2dFDG2vYref=)a`OL z+%hsk@U{m}kF0YwxUOvWi4R0>znH*nzY_WKRsy^A1)duhEJr!g?NI-2gW;)dQ-4dfi}eyQDoRqW7DZBl?d26& z(P9;@s$x2IPcet@!`e_Vlus zv+cqm&1yGy>-E0WI;W+5dv@9fxehsl_MtTGQPFOG+Rt9na(3i+wv}ul9m-t86rM73 zYp9P>U1o9>MM49jwjKhIRAnq^a22WDqyTo*xq=hB~MQAMqu4S6Y*Yj~4v9|w?w>VO;sP$U8s;K;Ixvc?*M`$v_( zM1C8;3?gHlkTE&JAdDi6WhI6xiQU0v1=cRY4)PMdw}RS1RmcDaN3JI&Ag_#0N}wQH$tyc0Y3irs zc1L)rC|0bxY2TikR#jj>P>uH`P(exmHX_)rQxJ2MbpkmVs3SvZLrLulKskhwLr%0J zTwxYBA%X{~1T(v1^RZumgeJ2kOJ^1-8*Nz6snBXRZYR-7i`#jUDAg9?;Xsv2IFOI# zSr&SQY_aZn>6HoLS>jrUy;wx_Ns6%;&!zd}gi`}Gh-&pst(4UetF*};_&S)}56JRtgahc6 zcV5D!lDeVh0m08mN}rO2IximT>bFY+Wu>9gzqnksQ0ejG_JGY@xgf@q`h`4NiKqV4 zAWGl*mL#6tuVp|DJ&$3&cC!_Nq|$RS=$W3X%Q-1wp(vzO9bE+4#6tcT&tO1ZMQK^es`PC!g>*!U&NI5v0!Q~{30v4uOdmQw)dOzc|O zlXPy8-87%bz_LX60aT=lBCt7pzye2eg=4HQI65-ob49&Qi(^AiV03uI>x-h?+rq~5 z1y|JRan`y6VP~Y?GOz!E(Lh^YDt!it@M9WM9YeVQL;322{`AkMWrY?iXpV1~~<`hTL%Oje1=9)kJ_lhoYyj;^rY~n-*GTpBjG7_Pp-v?F_`WvWHHn}a520*qt3n>S zZ(@;+or{!!MHUKEPIM@D9T~vQ*zlGI;D339@S1)42#GKzr(`~27E^G|@=_=xat8n# z=NpMksSm$AA^7pg`-mn2BIgL)sHOSZeVe!J+p~4cp6$U%G!%+Pf;s7~g?QGzwc)^l z4PyrmjCBqSbaoC7lCH6B`VGSvAijFpD4^9&u{gr$eX&qj9)xJZjsww~(&>SD5xXFi zSlif5@Ym;r<+bq1L;8d9h1f>EET|e>9{74BB(DXRH-=(sE%G|h6S!dV$8hcgQ!9Yj zd8pD{P}WUlCu3`Y2DSoP$2#kTH`G~8kLqo4S1W*9K>5Z&NF>(Uw*t>)JysC8z7uaQ zK-D1>3sDrloaE;)21@XWQ&mpX$SEaDC5Z}4pfEzGhwCkF6+w90z~1{d5ASI>a_zd$ zb`rey+8ZC}=scMM6>i&f+jt6Ac+aV&{Xg2f@zx#PpADb$aj$djx^*s>Lv-!%-~A2o zh`3e38^%B#9`l=|B`GZKO_y%mIdteD!XMuAl}mgo0&%FvH|Sn-a05*gLy5Dh^PV+c z$#nTk{h!(#IYBWW2c~Qs=z4&mWMe&f!w8;iF_{z`3=e46v6g@w#wbMtiAHrg0K-EK zAi$n2!AE$IG6L`pxeMkH665vd_0Gl?e;=hPGC3Ls;XUoW6k;xy*Msl1P}ymcXGJgZ z33EqXG>LOzXje9yZEE_7Dwh;rT8SQ^1=2&SA1{a=w`tYmc?cpr zs!@!!JQ9NM=+hb=;d(LWktld1tYDgBZV9noKBI_7!W`3_j8?)l@57l_mPQ%k4(my9 zN_~@;E5l~g-zl|Id>rEe-NY=>6tlR9IB8utJF{fdgmnvmJ-;D~8eB3j6uK@rLj|5Z zkpxGV)OkgEl2UA5OSLSMDyy45J;Snl>Zx87(G)tc;;FY*xfM^nI@w|l>qh{FPww_7 zm7DMKa7gs7N@>%@pgJ*>plDg|{2URbUqmP3U^ zJ2DHfzM{-<0dS=Yc)@Sk4pahJhZ<=ys})65;p3vzAF8dZ6)Hwb8df|TJQTp8ksr^% zkCVd4P8G&@o#3ETu-K%caeQyF63r||Gf^wTMC%R(XK*w>1&A5VBoqKNQ=dZgwjj6& zgP0F3fDp0t*0|M%H5_d%1#lA{(V~*szD`Z9YX*k5cAj%Y{B#@tnx59;^ve|Cf~J-r zX8{p*DX&}HP80=@r;6f9juOJfEd@mZ@JFe^4s5Ogs16jZw8o7^z#2nKCBzeRyjUII zEGy?VMUwU?A=7KA>(4UdP}nI=WhCro+LyncMQz>m6uQuz!dgL?S_RR&gxXIz?g)r! zQ37HbV0E-}iKGU^RHGMV=oe}eThK2grQ(X_Q!}g#L;xd>C>a`)oDMSwV5XHIW^g_V zo2EM>RA`NX45XH+?`HH%xM~L96YO%2{tW;c_pse8j>H>y6i{Fmg$V$UN0{n$=&2L^ zQzULXLY%RmM>Gnam0;DI_h~Xk7CeE7kF?PUw!8K~3;yPAm zmFwZ_Pirwy3jw@?|HwD>KpFG^%!%w%j(|ncGq6#UMKqKoIiNQ`w13sVbRtt$G8;VG z27gjnWqvSn?NZTXc=7fp?DYlza?|a9c<*51K=iKrj~&17{$pQ`32*Fv>~pIDtx%e8 zX|U}1O6L)KuyR{%y&1)F3+xwOVTsr`ADX)UovAmbo>+C`xAw+=_`~=Ur%%(IQ|bU5 z1G4rY`$Z0HZFM8N722OaG!bmYMz)M4E9qp-2Dz>7W2Za|eef*wz_Z{d&q6@sS!naC zTi3mPJ@72xR^wT~GwxYv3#i-G4`a7FwOP$Q3og?Ay|g7=X-yQjc0@TKMu{!fg<%RN z_p8&+Yeas|QKW!RzAQe36xeYt6!6ZR-UAi(d=7kY{hC>x1Cob21vQ)t83)qs*Q+50 z07h0^YJ4TEqj6C1YT(PJiAb}PfI=wEz8Zngh?A*T6oWd7;W7i98t6q3H<=0nVMeuy z*!LtAlCvVJ1EhSgIWfg|Xe9kCcyS^6T?JrVEJ-SfbN8z;r6&G;{c5CswWQ`>a+6|4 zzcj)>XTQwal^}P=u%VrVM$nEInFGL3=K%$X|A<$l`UTuQUc>m7})D%k;{EJxtnRLEXK2`NsvDwEQ=a*se_ zmZ&)UXU!N$s?4|tW8lED*H0xS_$X+r4N!RNqOjZmk0N1k0{#))sG^jq%Q!J6p_FyQ zeb{ZG0`Qzi;X9VwkytiSY_C<6%T@MdTRGj!ry^$f&a z8ciTm8-`pxArt^I=N?{U#0`Xe6#YzCP0R`x9un<=I|aDtL@j^7D^?esK?&hRshRcQ z9rYnKBZsRrDWDvJMNT^3teWc#fE*#REF2sj4u+Q{&*F<3WSpt*s4t2ys~72YAOd%q z1FLj9aJaaeK`GEc!i7pQC^HPj3WS&vi=dR)=E8-FsZlIKJ#l#j7cQnUyWYi7JrPct zhfsRBB4I63QLH9wqNtWNw9^#G&#YU9;^-6`V^>Nc@q9L@G?7vzHpWn*tQ;ObmYcsE zSyJhC)*ad=P#KD2dxEv~?&|G5i*8vgyy4xm;(?=wRvmias{uu{M#JX;5#iq3e@=BN z#`+9~>qnluDt4K;%NKZk@`uZQ_ss2=LRaCa^jHsRHM}4htdLv{Q{eQ>kn%d#W`{8C6qf!*9pwk zKfWr?-#?1;nW(OB$Dsx#G z<9pK5d1iHmtioBPghn`1bpgbzPjpvUu!izL!~jWaj@wHj8mvvzdVz%)=9ABJQ0A67 z1oWH~k}Nrew8%J`KjwM^w#vF#+>>+zAOt4`>K_Qu8Z`^lKjyK;{Inh^;VLPB44T4C zo(yPzord2R1oL03W&AlY|6zkCHA8M^QFR>@mZIu92(-#lU59%35vuEW(h)k@>gw3} zJWpyU=_nl~MI%*LrxitY7E)Hn_%sEQOg=DgT^-T`m9e`AV;6!|iNsj7Fo!yDv_c^+ z8b#Y;olrjz2kkl|`=Dqj;U#hpxR_#ce85SLS2X}cnqo_2V;%AH-&4S0rZZxuZ*D;& z|IInrd`?El@L0^yMNowZTV)>rUDk_4x=*SFud5L6>Ly=B02jQ9F|yqi^uaDfb6G3h zRQ=LQaj;5seG4LAkyuNMJXI*Ngm}ta2=(q|J^T_>lD&awM|eH}oUsz?uok>vvBtt& zb5o;V)m%>0@12n$>E!F5kgRs7l!~RgMfbjWcmI)yh$0tY4@x?wb291pz33MP?tbI0 zRkts?>R+$!|72(9?*41y2YS`;V{=jVWV(XFecux*9=!Pv$3C8CksdF~M>s6Ehq2uP zf0-WvOkL1y?@_%KNVsl;Jz)=V9f)9Dv7HVWpG2gziRgsVX-OTIAfv%#a8Yq}HxeSe zu5R2};0Pw&mfKiOdQhg+Dw_~78|y}{p`FJOTdeVts#@-?qrgUr1H+rD=uHvZgoXLI zBfi7RD#4I<4y691a7{7 zSjc&TK66G${xNsZXU>Sp8*)Z_65O2hsBVb+S=t#-+>aT7 zfmF#N%$#gm#K|nG!Yq$0ZMQxoeOI?0aFUhmK^6m`9Wdo}U|lIRVbYahRp*$O0A;|J zE8h**PKH5T3WL}NgIFSi*q||p^^ySwaj9jZq?EviajP+i@r)b9dV{TmOkfm1pvzLa zRt#b$msv=IfEQiXL93J*Je}%-n#DWzP)Ii? z_{?UX#nNI1ZtwrV-@!#LN|JapFE*nZhh!jfWZ7cX(+%f*$_%8aE=Dr&Ed3r<%g!_v z6d}g}?WfN(eZ_6L-MVPZz++#Hv@t=c!HPPiLIaQ6 znk*K#^>T~LW@#){=H1j~l7z9%Xj2k(l-gtp@yKM%F5V_VX_Lt)q}znp@?@L(p3%06 z&$xUl_=e4=7}_LJo08K{$5H*p_t*d}>$Y89+Gw%4P_z9Gq8wVqY0t)|O9eRPK&wpv zn+9BKI3aLiEvPk5y|suaBmsCnW;`v%j7qAM+Ai6MX`-~rt`bUzC9_2s-vcV8+VqC- zCElc+u;%b1vh7k65L%x`o2uCZj3s6F|8H4aPMz_>?Mu zi@5*>)5J|h<)M(mII^)U4A%Lt5v5NZ$WzG+&huJc;^XF?V-$sL8G{N&OO2|ge|&tw zbK*}q&s8H<9b8BKK^VTudAxqe|C|1(jG5{d6^bi6ErMpMOb7T~MxQ=H4>fF?(LsUT zExN>U-P>?CwlTn=CiEtjC;8M972@NImzh5_^Ale{XFCh;Zd|-R7+Al!5$8Y7(wV2haCo69j{NKdY6L1F`eNE4Yu}T34S5M*eep_;+**#3D+QcndNTu*v0TWP zm^lFUGZ6LhSwMjm_wdhhCO<1Ch7!O$P(MyKl5iJjDr-SvX9B}!;K1T@gV;%Z2uMdu zD085f@1w#bvB74gdf~tgP|C!XA&_N2?6o1951YpWP-X(5M3I?403JETkJUk}A>!MB z7}lac#61SW9`N`HUo#XpaBNZo!(Bm0ruc7<0oq4#KUsbQ*mK3M9148H2k%v4|QBnWb z*F65JS6pu}Ox{H@`chmR^Zw_*ZMm=0QfU}Ey>psPeaCl?NesHGOMP}nUkw$_L9Sz= zyU-m(F{T%uqS`vOeRXzUX>GN$?&WX0YaLOC%Om6qhDyk}esPas49KHp*p0rE#YzCL z%t0Aomw{_bICgP~1&B{x#9#6)Y3ms|-v$S-m57uNgyUGgqIeT1ZWpS8px{lyZe!PB zafJ`NQ@KJG78MI?LKGhDV3z}78!Hp?AQ1{7cT%7MOqN!wjMk}o`h>mK;f6nyXsc>7 zMjmhg+-)lgDkRHBCYM{PfQFayRpc#xZUK6zBwj7)jML0gZ7FgTO*2U+{>Fo{Xg0U? zt-qi`n$2YaRvca{uK!IzX}-C%@TWDFYHN{0zZ-voSE?P80}|4Fp0wB}?Yd6BR+b7p zOyukf^uore74%SeWb!zYf%qZ{SH1(1fd#EjD_wv1TRa~|dHZ+t@4#J-eSfHq@Y^fJ zIw|b54V(UmA}tHZCe>ly%JDD=t-LA}Z*3xSw-Og3w~dm#sHip>*Dlz7vdskY)uMnr zCARU}V91Uly@cTAiGE?QCa-U~6N96tWUX(!~(d%?5kl&h=x-;FPnQi6~TG zo^<5l>Ay$`^u3o|!s4COcY9ckOhf?+?u+p%u)^&jDvW6&1Gx{0ew+v)5TQ9lPM-rP3$iDfRqOx>FL+blX%n?H1C7E&LU?lGC{eY@9>nNbX_)~uz7 zLX)$GZJ^0&m|F26l3yKtDBqe70Ty#YFew~S1eiLiA?5L6JppgXHFcPoL^0VOz@u|e zSE73fO-@ANujJ%f3UZZ);wzUD&#WY#S<0ipvA-!V!fU7tgs^ag<;y{kl0xtYmJ%sp zP@z@_u9{F1fC_jtI*GW}ArQA|23b?}<-kV^;;orXcKlJ_Xr)wQw)MI?*F_w{pPv7& z!gYn{aF#TBK>iCU zF{q8mzj7Vu=~nqswqr2l3qajvt5HWB0YykZ%LDz*G(Qmtemf9uO!=R>IgWwP*U*HB|o1=0b8MY2!rD*4BYW3ip%1Qi@n0a1$ zKTB+0>Gs>~L5n$0Ve@5RbN}G@QVp9gi0}(%{){1@S-`e@{!=eqRNVVl=0I>AeqOj_ zBe~Z2dHS&_C<(?xxFt*-{;gZ;F3n%jna{%A!9Lm$L8Z zR^v@3Z5kaW-ZsWj6_@p)Iau<8L)yV^lL{DYf59tNq1}(Ngzl&4!wGg++Qklv z-)F9gVk|+=@wo@2lQ=)b4&nU?-Mws|c#`?0yWlAD zu}*`;mg)Y8zSS|O?ormS^MRK43TB*l=zatY9hLT=#k)9uiDNU4RrDUT_ZE!LtA;m*j)C1#Sz;V6kn|=YuYxLhUeKfJ{A}U8jIwCad7al2u!~$2BxQ^1n8d}2O10QK|DtHG#1(e zW5LG^XX9FS$apgS~|_o*_(w(O4u8iA|q1 z;Sin$?bSoq$F}1b=Lf_5T8TM;zZHKCKKV737@7=YhHDKk8Ox1(O+}_{rZ@A(^KLb_ zm>)3zC4W=?b@`9y|3|^5!cgIZMeRk;7S|VFUYxLOwInRRvbI?FS|6}g*{-tvxMXq3 z^T>*Px2&z~+Ont1N6YUn|CPPUK4!nxe%k(8g;dd2@la(^<<`n)s=BMbSpCWBAJq)h zJY6f*F0Os4uD$Lb>OOGnaGb2~sQ+yJ&z%eyIMXoY+TwcC^=4yN<5BnC zCR5XAnx6DL-CWfCj`s`RC%x~rG`9Q(ds&-(&$O1d?rOcm&-}ywtNqWmS=zR?eK9Z? z_*?s9!9~HxLxZ6og`e!Wy0fP9b6q>So{uy~zTDm3y{r3J_q)+e(cdgO)zi{*Pj6N4 z2Yq+|Jni5z~+IUExBUQG-jz>} zRE=Ca@|Sb2TeW7@snt!ZA6&Cz%?IbMJNL}!(CDLUyVrhyUB|lP=M9{9X8m>Ni{~#s z|FInZes=!5W0tY*u`OfA$NqM~zy(ikXy0)EhM!$Hh<`gS{NjaQ+}O48Hyi)-vCBU8 z?xw`Yug0j7M1B)KEj`X8f(0Dq^jP>O{)C}o&8MLu3sN2);uZB;WJS1Bp6l2EutJq< z2?)&F)N4Jfz>=*zH{jhz)oT;0XOF7aHa!2Cdi^Y}|Ds+$$J&v%x`ge*zfZ6$@E5Cq zQn#J$U{|qqc(NTCGrQQucx4%W@50kP>~d&m7vtY{y!R@!q7B<(^*KJH9@~rU_}88D z^~`S>FxNeY(H;ed__SAN=q1b12baH&cit8 zvjX@Mi{KxzFe~sEOHf0n3}a%)I938Duo~qLYq1IKz_&TELF>Y(yD{D#gcf z@PjS^-jWd7(!pC80hOa@XAi83KGc5c2fr-A=I&CA-EvgvSpoU7l8vx)K%dpXJUthg ze`_(y=OJwMd^Uz~oefa_HnNX_Pd|<=;fvs}z8Ku`HTD_g*ME!M!G6#Fk$s-s%^S=?dl#t0N7?^o&#~{a6QKAd>{f8g z_dxw;+4I1^{XTnv{eb-e)O(q|#C`}g@$Kwwb{jjxe$0LX4*VngGcfiq1261^g}4j+ za6iUqAKQ!Zxe|PN6}y^UgIV=S_9^7T9b|`qa{4IyDm#psbRB#ke*%}Ef^tm6_P>M*l%V{!P$^Wg ze-f&N8le_$Rfl2wt^<2_1daPIzqGx*eVKAz(ypG>`@xWMKNwceo$5JC=Mer-J@e1O zJ%2yW{QWq0sIT+C!+n=}A5qWU>N)v&OO*Sd`nkcNdHmAt`>*)Kwu`Uap}Z6tQqG-2 z((?UR?4g_GYCDDo+j%>1=Iy|lw*%)6@b#m@^bIlL7Isd|G`c|+gwJ0n4;g$LoH5IV z=fq0a;o`arYhwoArVT8nt6v_|`If~D^~>YBM?@dL(c{K&jd~;DMnA0H80l>fsy8Ow z7#o!vA(p3pk{M6)EFua;4PA{7&d05}EOlFe+x+p=Z6R(8x>L7BxGnUiZi{hS)SSAt h;I_Cjb!)|~#h$vg;nte^-V0-;J|?W~JANr+{};-Q52gSB literal 0 HcmV?d00001 diff --git a/docs/public/fonts/aller-light.woff b/docs/public/fonts/aller-light.woff new file mode 100644 index 0000000000000000000000000000000000000000..af48bc0aae628cf9ca24382909384c79520d88ee GIT binary patch literal 33123 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

@@ -63,8 +63,7 @@ with a error-tolerant parser and an

The main exported interface (under self.acorn when in the browser) is a parse function that takes a code string and returns an abstract syntax tree as specified by Mozilla parser -API, with the caveat that the SpiderMonkey-specific syntax -(let, yield, inline XML, etc) is not recognized.

+API, with the caveat that inline XML is not recognized.

@@ -107,7 +106,7 @@ the parser process. These options are recognized:

ecmaVersion indicates the ECMAScript version to parse. Must be either 3, or 5, or 6. This influences support for strict mode, the set of reserved words, support for getters and -setters and other features. ES6 support is only partial.

+setters and other features.

@@ -476,7 +475,7 @@ for operators, the operator name, and so on.

-

Interal state for the tokenizer. To distinguish between division +

Internal state for the tokenizer. To distinguish between division operators and regular expressions, it remembers whether the last token was one that is allowed to be followed by an expression. (If it is, a slash is probably a regexp, if it isn’t it’s a @@ -533,14 +532,15 @@ 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, labels to verify that -break and continue have somewhere to jump to, and strict -indicates whether strict mode is on.

+return statements outside of functions, inGenerator to +reject yields outside of generators, labels to verify +that break and continue have somewhere to jump to, and +strict indicates whether strict mode is on.

-  var inFunction, labels, strict, inXJSChild, inXJSTag;
+ var inFunction, inGenerator, labels, strict, inXJSChild, inXJSTag; @@ -551,6 +551,41 @@ indicates whether strict mode is on.

+

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

+ + + +
+  var metParenL;
+ + + + +
  • +
    + +
    + +
    +

    This is used by parser for detecting if it’s inside ES6 +Template String. If it is, it should treat ‘$’ as prefix before +‘{expression}’ and everything else as string literals.

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

    This function is used to raise exceptions on parse errors. It takes an offset integer (into the current input) to indicate the location of the error, attaches the position to the end @@ -571,11 +606,11 @@ message.

  • -
  • +
  • - +

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

    @@ -587,42 +622,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

    @@ -635,6 +641,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.

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

  • -
  • +
  • - +

    These are JSX-specific token types

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

  • -
  • +
  • - +

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

    var _throw = {keyword: "throw", beforeExpr: true}, _try = {keyword: "try"}, _var = {keyword: "var"}; var _let = {keyword: "let"}, _const = {keyword: "const"}; var _while = {keyword: "while", isLoop: true}, _with = {keyword: "with"}, _new = {keyword: "new", beforeExpr: true}; - var _this = {keyword: "this"};
    + var _this = {keyword: "this"}; + var _class = {keyword: "class"}, _extends = {keyword: "extends", beforeExpr: true}; + var _export = {keyword: "export"}, _import = {keyword: "import"}; + var _yield = {keyword: "yield", beforeExpr: true};
  • -
  • +
  • - +

    The keywords that denote values.

    @@ -713,11 +751,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 @@ -731,11 +769,11 @@ we assign a variable name to it for quick comparing.

  • -
  • +
  • - +

    Map keyword names to token types.

    @@ -752,16 +790,18 @@ we assign a variable name to it for quick comparing.

    "instanceof": {keyword: "instanceof", binop: 7, beforeExpr: true}, "this": _this, "typeof": {keyword: "typeof", prefix: true, beforeExpr: true}, "void": {keyword: "void", prefix: true, beforeExpr: true}, - "delete": {keyword: "delete", prefix: true, beforeExpr: true}};
    + "delete": {keyword: "delete", prefix: true, beforeExpr: true}, + "class": _class, "extends": _extends, + "export": _export, "import": _import, "yield": _yield};
  • -
  • +
  • - +

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

    @@ -771,16 +811,18 @@ we assign a variable name to it for quick comparing.

    var _bracketL = {type: "[", beforeExpr: true}, _bracketR = {type: "]"}, _braceL = {type: "{", beforeExpr: true}; var _braceR = {type: "}"}, _parenL = {type: "(", beforeExpr: true}, _parenR = {type: ")"}; var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true}; - var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _ellipsis = {type: "..."}, _question = {type: "?", beforeExpr: true};
    + var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _ellipsis = {type: "..."}, _question = {type: "?", beforeExpr: true}; + var _arrow = {type: "=>", beforeExpr: true}, _bquote = {type: "`"}, _dollarBraceL = {type: "${", beforeExpr: true}; + var _ltSlash = {type: "</"};
  • -
  • +
  • - +

    Operators. These carry several kinds of properties to help the parser use them properly (the presence of these properties is @@ -815,11 +857,41 @@ in AssignmentExpression nodes.

  • -
  • +
  • - + +
    +

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

    + +
    + +
      var _star = {binop: 10, beforeExpr: true};
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
      var _lt = {binop: 7, beforeExpr: true}, _gt = {binop: 7, beforeExpr: true};
    + +
  • + + +
  • +
    + +
    +

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

    @@ -831,18 +903,18 @@ tokenizer.

    parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon, dot: _dot, ellipsis: _ellipsis, question: _question, slash: _slash, eq: _eq, name: _name, eof: _eof, num: _num, regexp: _regexp, string: _string, + arrow: _arrow, bquote: _bquote, dollarBraceL: _dollarBraceL, xjsName: _xjsName, xjsText: _xjsText}; - for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw];
  • -
  • +
  • - +

    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 @@ -876,11 +948,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.

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

  • -
  • +
  • - +

    Otherwise, simply generate a flat switch statement.

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

  • -
  • +
  • - +

    The ECMAScript 3 reserved word list.

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

  • -
  • +
  • - +

    ECMAScript 5 reserved words.

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

  • -
  • +
  • - +

    The additional reserved words in strict mode.

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

  • -
  • +
  • - +

    The forbidden variable names in strict mode.

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

  • -
  • +
  • - +

    And the keywords.

    @@ -1000,18 +1072,18 @@ switch first dispatches on the lengths, to save on comparisons.

    var isEcma5AndLessKeyword = makePredicate(ecma5AndLessKeywords); - var isEcma6Keyword = makePredicate(ecma5AndLessKeywords + " let const"); + var isEcma6Keyword = makePredicate(ecma5AndLessKeywords + " let const class extends export import yield"); var isKeyword = isEcma5AndLessKeyword;
  • -
  • +
  • - +

    Character categories

    @@ -1020,34 +1092,35 @@ 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 are only applied when a character is found to actually have a -code point above 128.

    +code point above 128. +Generated by tools/generate-identifier-regex.js.

       var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
    -  var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
    -  var nonASCIIidentifierChars = "\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
    +  var nonASCIIidentifierStartChars = "\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC";
    +  var nonASCIIidentifierChars = "\u0300-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u0669\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u06F0-\u06F9\u0711\u0730-\u074A\u07A6-\u07B0\u07C0-\u07C9\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E4-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0966-\u096F\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09E6-\u09EF\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A66-\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B66-\u0B6F\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0CE6-\u0CEF\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D66-\u0D6F\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0E50-\u0E59\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0ED0-\u0ED9\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1040-\u1049\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u18A9\u1920-\u192B\u1930-\u193B\u1946-\u194F\u19B0-\u19C0\u19C8\u19C9\u19D0-\u19D9\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AB0-\u1ABD\u1B00-\u1B04\u1B34-\u1B44\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BF3\u1C24-\u1C37\u1C40-\u1C49\u1C50-\u1C59\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u200C\u200D\u203F\u2040\u2054\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA620-\uA629\uA66F\uA674-\uA67D\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F1\uA900-\uA909\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9D0-\uA9D9\uA9E5\uA9F0-\uA9F9\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA50-\uAA59\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uABF0-\uABF9\uFB1E\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFF10-\uFF19\uFF3F";
       var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
       var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
  • -
  • +
  • - +

    Whether a single character denotes a newline.

    @@ -1059,11 +1132,11 @@ code point above 128.

  • -
  • +
  • - +

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

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

  • -
  • +
  • - +

    Test whether a given character code starts an identifier.

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

  • -
  • +
  • - +

    Test whether a given character is part of an identifier.

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

  • -
  • +
  • - +

    Tokenizer

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

  • -
  • +
  • - +

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

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

  • -
  • +
  • - +

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

    @@ -1170,18 +1243,19 @@ line break). Used to count lines.

    tokCurLine = 1; tokPos = tokLineStart = 0; tokRegexpAllowed = true; - inXJSChild = inXJSTag = false; + metParenL = 0; + inTemplate = inXJSChild = inXJSTag = false; skipSpace(); }
  • -
  • +
  • - +

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

    tokEnd = tokPos; if (options.locations) tokEndLoc = new Position; tokType = type; - if (!(inXJSTag && val === '>') && !(inXJSChild && tokType !== _braceL)) { + if (inTemplate || type !== _bquote && !(inXJSTag && type === _gt) && !(inXJSChild && tokType !== _braceL)) { skipSpace(); } tokVal = val; @@ -1235,11 +1309,11 @@ the next one’s tokStart will point at the right position.

  • -
  • +
  • - +

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

    @@ -1290,11 +1364,11 @@ whitespace and comments, and.

  • -
  • +
  • - +

    Token reading

    @@ -1303,11 +1377,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 @@ -1340,10 +1414,10 @@ into it.

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

  • -
  • +
  • - +

    A --> line comment

    @@ -1403,11 +1477,11 @@ into it.

  • -
  • +
  • - +

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

    @@ -1418,28 +1492,108 @@ into it.

    skipSpace(); return readToken(); } - if (next === 61) + if (next === 61) { size = input.charCodeAt(tokPos + 2) === 61 ? 3 : 2; - return finishOp(_relational, size); + return finishOp(_relational, size); + } + if (next === 47) {
    + +
  • + + +
  • +
    + +
    + +
    +

    ‘</‘, beginning of JSX closing element

    + +
    + +
          size = 2;
    +      return finishOp(_ltSlash, size);
    +    }
    +    return finishOp(code === 60 ? _lt : _gt, size);
       }
     
    -  function readToken_eq_excl(code) { // '=!'
    +  function readToken_eq_excl(code) { // '=!', '=>'
         var next = input.charCodeAt(tokPos + 1);
         if (next === 61) return finishOp(_equality, input.charCodeAt(tokPos + 2) === 61 ? 3 : 2);
    +    if (code === 61 && next === 62 && options.ecmaVersion >= 6) { // '=>'
    +      tokPos += 2;
    +      return finishToken(_arrow);
    +    }
         return finishOp(code === 61 ? _eq : _prefix, 1);
       }
     
    -  function getTokenFromCode(code) {
    +  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);
    +        }
    +      }
    + +
  • + + +
  • +
    + +
    + +
    +

    anything else is considered string literal

    + +
    + +
          return readString();
    +    }
    +
         switch(code) {
  • -
  • +
  • - +

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

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

  • -
  • +
  • - +

    Punctuation tokens.

    @@ -1471,33 +1625,30 @@ by a digit or another two dots.

    case 123: ++tokPos; return finishToken(_braceL); case 125: ++tokPos; return finishToken(_braceR); case 58: ++tokPos; return finishToken(_colon); - case 63: ++tokPos; return finishToken(_question);
    - -
  • - - -
  • -
    - -
    - -
    -

    ‘0x’ is a hexadecimal number.

    + case 63: ++tokPos; return finishToken(_question); -
    - -
        case 48: // '0'
    +    case 96: // '`'
    +      if (options.ecmaVersion >= 6) {
    +        ++tokPos;
    +        return finishToken(_bquote);
    +      }
    +
    +    case 48: // '0'
           var next = input.charCodeAt(tokPos + 1);
    -      if (next === 120 || next === 88) return readHexNumber();
    + if (next === 120 || next === 88) return readRadixNumber(16); // '0x', '0X' - hex number + if (options.ecmaVersion >= 6) { + if (next === 111 || next === 79) return readRadixNumber(8); // '0o', '0O' - octal number + if (next === 98 || next === 66) return readRadixNumber(2); // '0b', '0B' - binary number + }
  • -
  • +
  • - +

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

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

  • -
  • +
  • - +

    Quotes produce strings.

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

  • -
  • +
  • - +

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

    return readToken_slash(); case 37: case 42: // '%*' - return readToken_mult_modulo(); + return readToken_mult_modulo(code); case 124: case 38: // '|&' return readToken_pipe_amp(code); @@ -1580,11 +1731,11 @@ of the type given by its first argument.

  • -
  • +
  • - +

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

    @@ -1597,18 +1748,18 @@ of the type given by its first argument.

  • -
  • +
  • - +

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

    -
        if (isIdentifierStart(code) || code === 92 /* '\' */) return readWord();
    +            
        if (!inTemplate && (isIdentifierStart(code) || code === 92 /* '\' */)) return readWord();
     
         var tok = getTokenFromCode(code);
     
    @@ -1617,11 +1768,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.

    @@ -1644,11 +1795,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.

    @@ -1676,11 +1827,11 @@ since a ‘/‘ inside a ‘[]’ set does not end the expression.

  • -
  • +
  • - +

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

    @@ -1701,11 +1852,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 @@ -1731,10 +1882,10 @@ will return null unless the integer has exactly len di return total; } - function readHexNumber() { + function readRadixNumber(radix) { tokPos += 2; // 0x - var val = readInt(16); - if (val == null) raise(tokStart + 2, "Expected hexadecimal number"); + var val = readInt(radix); + if (val == null) raise(tokStart + 2, "Expected number in radix " + radix); if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number"); return finishToken(_num, val); }

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

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

    @@ -1781,24 +1932,61 @@ will return null unless the integer has exactly len di
  • -
  • +
  • - +

    Read a string value, interpreting backslash-escapes.

    +  function readCodePoint() {
    +    var ch = input.charCodeAt(tokPos), code;
    +    
    +    if (ch === 123) {
    +      if (options.ecmaVersion < 6) unexpected();
    +      ++tokPos;
    +      code = readHexChar(input.indexOf('}', tokPos) - tokPos);
    +      ++tokPos;
    +      if (code > 0x10FFFF) unexpected();
    +    } else {
    +      code = readHexChar(4);
    +    }
    + +
  • + + +
  • +
    + +
    + +
    +

    UTF-16 Encoding

    + +
    + +
        if (code <= 0xFFFF) {
    +      return String.fromCharCode(code);
    +    }
    +    var cu1 = ((code - 0x10000) >> 10) + 0xD800;
    +    var cu2 = ((code - 0x10000) & 1023) + 0xDC00;
    +    return String.fromCharCode(cu1, cu2);
    +  }
    +
       function readString(quote) {
    -    tokPos++;
    +    if (!inTemplate) tokPos++;
         var out = "";
         for (;;) {
           if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant");
           var ch = input.charCodeAt(tokPos);
    -      if (ch === quote) {
    +      if (inTemplate) {
    +        if (ch === 96 || ch === 36 && input.charCodeAt(tokPos + 1) === 123) // '`', '${'
    +          return finishToken(_string, out);
    +      } else if (ch === quote) {
             ++tokPos;
             return finishToken(_string, out);
           }
    @@ -1818,7 +2006,7 @@ will return null unless the integer has exactly len di
               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 += String.fromCharCode(readHexChar(4)); break; // 'u'
    +          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'
    @@ -1833,9 +2021,22 @@ will return null unless the integer has exactly len di
               }
             }
           } else {
    -        if (ch === 13 || ch === 10 || ch === 8232 || ch === 8233) raise(tokStart, "Unterminated string constant");
    -        out += String.fromCharCode(ch); // '\'
             ++tokPos;
    +        if (newline.test(String.fromCharCode(ch))) {
    +          if (inTemplate) {
    +            if (ch === 13 && input.charCodeAt(tokPos) === 10) {
    +              ++tokPos;
    +              ch = 10;
    +      }
    +            if (options.locations) {
    +              ++tokCurLine;
    +              tokLineStart = tokPos;
    +    }
    +          } else {
    +            raise(tokStart, "Unterminated string constant");
    +  }
    +        }
    +        out += String.fromCharCode(ch); // '\'
           }
         }
       }
    @@ -2170,11 +2371,11 @@ will return null unless the integer has exactly len di
             
  • -
  • +
  • - +

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

    @@ -2190,11 +2391,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 @@ -2208,11 +2409,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.

    @@ -2253,11 +2454,11 @@ containeds an escape, as a micro-optimization.

  • -
  • +
  • - +

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

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

  • -
  • +
  • - +

    Parser

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

  • -
  • +
  • - +

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

  • -
  • +
  • - +

    Parser utilities

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

  • -
  • +
  • - +

    Continue to the next token.

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

  • -
  • +
  • - +

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

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

  • -
  • +
  • - +

    Start an AST node, attaching a start offset.

    @@ -2416,11 +2617,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 @@ -2445,11 +2646,11 @@ only started after its left-hand side has already been parsed.

  • -
  • +
  • - +

    Finish an AST node, adding type and end properties.

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

  • -
  • +
  • - +

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

    @@ -2488,11 +2689,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.

    @@ -2504,17 +2705,19 @@ type, and if yes, consumes it as a side effect.

    if (tokType === type) { next(); return true; + } else { + return false; } }
  • -
  • +
  • - +

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

    @@ -2529,11 +2732,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.

    @@ -2548,11 +2751,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.

    @@ -2561,18 +2764,17 @@ raise an unexpected token error.

       function expect(type) {
    -    if (tokType === type) next();
    -    else unexpected();
    +    eat(type) || unexpected();
       }
  • -
  • +
  • - +

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

    @@ -2588,11 +2790,11 @@ raise an unexpected token error.

  • -
  • +
  • - +

    Get following char.

    @@ -2606,29 +2808,193 @@ raise an unexpected token error.

  • -
  • +
  • - +

    Raise an unexpected token error.

    -  function unexpected() {
    -    raise(tokStart, "Unexpected token");
    +  function unexpected(pos) {
    +    raise(pos != null ? pos : tokStart, "Unexpected token");
       }
  • -
  • +
  • - + +
    +

    Creates an empty hash object.

    + +
    + +
    +  function hash() {
    +    return Object.create(null);
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Convert existing expression atom to assignable pattern +if possible.

    + +
    + +
    +  function toAssignable(node, allowSpread, checkType) {
    +    if (options.ecmaVersion >= 6 && node) {
    +      switch (node.type) {
    +        case "Identifier":
    +        case "MemberExpression":
    +          break;          
    +
    +        case "ObjectExpression":
    +          node.type = "ObjectPattern";
    +          for (var i = 0; i < node.properties.length; i++) {
    +            var prop = node.properties[i];
    +            if (prop.kind !== "init") unexpected(prop.key.start);
    +            toAssignable(prop.value, false, checkType);
    +          }
    +          break;
    +
    +        case "ArrayExpression":
    +          node.type = "ArrayPattern";
    +          for (var i = 0, lastI = node.elements.length - 1; i <= lastI; i++) {
    +            toAssignable(node.elements[i], i === lastI, checkType);
    +          }
    +          break;
    +
    +        case "SpreadElement":
    +          if (allowSpread) {
    +            toAssignable(node.argument, false, checkType);
    +            checkSpreadAssign(node.argument);
    +          } else {
    +            unexpected(node.start);
    +          }
    +          break;
    +
    +        default:
    +          if (checkType) unexpected(node.start);
    +      }
    +    }
    +    return node;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Checks if node can be assignable spread argument.

    + +
    + +
    +  function checkSpreadAssign(node) {
    +    if (node.type !== "Identifier" && node.type !== "ArrayPattern")
    +      unexpected(node.start);
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
    +  function checkFunctionParam(param, nameHash) {
    +    switch (param.type) {
    +      case "Identifier":
    +        if (isStrictReservedWord(param.name) || isStrictBadIdWord(param.name))
    +          raise(param.start, "Defining '" + param.name + "' in strict mode");
    +        if (nameHash[param.name])
    +          raise(param.start, "Argument name clash in strict mode");
    +        nameHash[param.name] = true;
    +        break;
    +
    +      case "ObjectPattern":
    +        for (var i = 0; i < param.properties.length; i++)
    +          checkFunctionParam(param.properties[i].value, nameHash);
    +        break;
    +
    +      case "ArrayPattern":
    +        for (var i = 0; i < param.elements.length; i++)
    +          checkFunctionParam(param.elements[i], nameHash);
    +        break;
    +    }
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Check if property name clashes with already added. +Object/class getters and setters are not allowed to clash — +either with each other or with an init property — and in +strict mode, init properties are also not allowed to be repeated.

    + +
    + +
    +  function checkPropClash(prop, propHash) {
    +    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 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[kind] = true;
    +  }
    + +
  • + + +
  • +
    + +
    +

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

    @@ -2636,21 +3002,47 @@ to.

    -  function checkLVal(expr) {
    -    if (expr.type !== "Identifier" && expr.type !== "MemberExpression")
    +  function checkLVal(expr, isBinding) {
    +    switch (expr.type) {
    +      case "Identifier":
    +        if (strict && (isStrictBadIdWord(expr.name) || isStrictReservedWord(expr.name)))
    +          raise(expr.start, isBinding
    +            ? "Binding " + expr.name + " in strict mode"
    +            : "Assigning to " + expr.name + " in strict mode"
    +          );
    +        break;
    +      
    +      case "MemberExpression":
    +        if (!isBinding) break;
    +
    +      case "ObjectPattern":
    +        for (var i = 0; i < expr.properties.length; i++)
    +          checkLVal(expr.properties[i].value, isBinding);
    +        break;
    +
    +      case "ArrayPattern":
    +        for (var i = 0; i < expr.elements.length; i++) {
    +          var elem = expr.elements[i];
    +          if (elem) checkLVal(elem, isBinding);
    +        }
    +        break;
    +
    +      case "SpreadElement":
    +        break;
    +
    +      default:
           raise(expr.start, "Assigning to rvalue");
    -    if (strict && expr.type === "Identifier" && isStrictBadIdWord(expr.name))
    -      raise(expr.start, "Assigning to " + expr.name + " in strict mode");
    +  }
       }
  • -
  • +
  • - +

    Statement parsing

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

  • -
  • +
  • - +

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

    function parseTopLevel(program) { lastStart = lastEnd = tokPos; if (options.locations) lastEndLoc = new Position; - inFunction = strict = null; + inFunction = inGenerator = strict = null; labels = []; readToken(); @@ -2696,11 +3088,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 @@ -2720,11 +3112,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 @@ -2739,6 +3131,7 @@ complexity.

    case _do: return parseDoStatement(node); case _for: return parseForStatement(node); case _function: return parseFunctionStatement(node); + case _class: return parseClass(node, true); case _if: return parseIfStatement(node); case _return: return parseReturnStatement(node); case _switch: return parseSwitchStatement(node); @@ -2748,16 +3141,18 @@ complexity.

    case _while: return parseWhileStatement(node); case _with: return parseWithStatement(node); case _braceL: return parseBlock(); // no point creating a function for this - case _semi: return parseEmptyStatement(node);
    + case _semi: return parseEmptyStatement(node); + case _export: return parseExport(node); + case _import: return parseImport(node);
  • -
  • +
  • - +

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

  • -
  • +
  • - +

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

    @@ -2830,19 +3225,19 @@ continue to.

  • -
  • +
  • - +
    -

    Disambiguating between a for and a for/in loop is -non-trivial. Basically, we have to parse the init var +

    Disambiguating between a for and a for/in or for/of +loop is non-trivial. Basically, we have to parse the init var statement or expression, disallowing the in operator (see the second parameter to parseExpression), and then check -whether the next token is in. When there is no init part -(semicolon immediately after the opening parenthesis), it is -a regular for loop.

    +whether the next token is in or of. When there is no init +part (semicolon immediately after the opening parenthesis), it +is a regular for loop.

    @@ -2853,16 +3248,20 @@ a regular for loop.

    expect(_parenL); if (tokType === _semi) return parseFor(node, null); if (tokType === _var || tokType === _let) { - var init = startNode(), varKind = tokType.keyword; + var init = startNode(), varKind = tokType.keyword, isLet = tokType === _let; next(); parseVar(init, true, varKind); finishNode(init, "VariableDeclaration"); - if (init.declarations.length === 1 && eat(_in)) + if ((tokType === _in || (tokType === _name && tokVal === "of")) && init.declarations.length === 1 && + !(isLet && init.declarations[0].init)) return parseForIn(node, init); return parseFor(node, init); } var init = parseExpression(false, true); - if (eat(_in)) {checkLVal(init); return parseForIn(node, init);} + if (tokType === _in || (tokType === _name && tokVal === "of")) { + checkLVal(init); + return parseForIn(node, init); + } return parseFor(node, init); } @@ -2887,11 +3286,11 @@ a regular for loop.

  • -
  • +
  • - +

    In return (and break/continue), the keywords with optional arguments, we eagerly look for a semicolon or the @@ -2915,11 +3314,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 @@ -2958,11 +3357,6 @@ adding statements to.

    raise(lastEnd, "Illegal newline after throw"); node.argument = parseExpression(); semicolon(); - return finishNode(node, "ThrowStatement");next(); - if (newline.test(input.slice(lastEnd, tokStart))) - raise(lastEnd, "Illegal newline after throw"); - node.argument = parseExpression(); - semicolon(); return finishNode(node, "ThrowStatement"); } @@ -3038,11 +3432,11 @@ adding statements to.

  • -
  • +
  • - +

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

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

  • -
  • +
  • - +

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

  • -
  • +
  • - +

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

  • -
  • +
  • - +
    -

    Parse a for/in loop.

    +

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

       function parseForIn(node, init) {
    +    var type = tokType === _in ? "ForInStatement" : "ForOfStatement";
    +    next();
         node.left = init;
         node.right = parseExpression();
         expect(_parenR);
         node.body = parseStatement();
         labels.pop();
    -    return finishNode(node, "ForInStatement");
    +    return finishNode(node, type);
       }
  • -
  • +
  • - +

    Parse a list of variable declarations.

    @@ -3160,9 +3557,8 @@ expression.

    node.kind = kind; for (;;) { var decl = startNode(); - decl.id = parseIdent(); - if (strict && isStrictBadIdWord(decl.id.name)) - raise(decl.id.start, "Binding " + decl.id.name + " in strict mode"); + decl.id = options.ecmaVersion >= 6 ? toAssignable(parseExprAtom()) : parseIdent(); + checkLVal(decl.id, true); decl.init = eat(_eq) ? parseExpression(true, noIn) : (kind === _const.keyword ? unexpected() : null); node.declarations.push(finishNode(decl, "VariableDeclarator")); if (!eat(_comma)) break; @@ -3173,11 +3569,11 @@ expression.

  • -
  • +
  • - +

    Expression parsing

    @@ -3186,11 +3582,11 @@ expression.

  • -
  • +
  • - +

    These nest, from the most general expression type at the top to ‘atomic’, nondivisible expression types at the bottom. Most of @@ -3203,11 +3599,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) @@ -3230,11 +3626,11 @@ or the in operator (in for loops initalization expressions).

  • -
  • +
  • - +

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

    @@ -3247,10 +3643,10 @@ operators like +=.

    if (tokType.isAssign) { var node = startNodeFrom(left); node.operator = tokVal; - node.left = left; + node.left = tokType === _eq ? toAssignable(left) : left; + checkLVal(left); next(); node.right = parseMaybeAssign(noIn); - checkLVal(left); return finishNode(node, "AssignmentExpression"); } return left; @@ -3259,11 +3655,11 @@ operators like +=.

  • -
  • +
  • - +

    Parse a ternary conditional (?:) operator.

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

  • -
  • +
  • - +

    Start the precedence parser.

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

  • -
  • +
  • - +

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

  • -
  • +
  • - +

    Parse unary operators, both prefix and postfix.

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

  • -
  • +
  • - +

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

    @@ -3414,17 +3810,22 @@ operator that has a lower precedence than the set it is parsing.

    node.callee = base; node.arguments = parseExprList(_parenR, false); return parseSubscripts(finishNode(node, "CallExpression"), noCalls); - } else return base; + } else if (tokType === _bquote) { + var node = startNodeFrom(base); + node.tag = base; + node.quasi = parseTemplate(); + return parseSubscripts(finishNode(node, "TaggedTemplateExpression"), noCalls); + } return base; }
  • -
  • +
  • - +

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

    var node = startNode(); next(); return finishNode(node, "ThisExpression"); + + case _yield: + if (inGenerator) return parseYield(); + case _name: - return parseIdent(); + var id = parseIdent(tokType !== _name); + if (eat(_arrow)) { + return parseArrowExpression(startNodeFrom(id), [id]); + } + return id; + case _num: case _string: case _regexp: case _xjsText: var node = startNode(); node.value = tokVal; @@ -3457,23 +3867,131 @@ or {}.

    return finishNode(node, "Literal"); case _parenL: - var tokStartLoc1 = tokStartLoc, tokStart1 = tokStart; + var node = startNode(), tokStartLoc1 = tokStartLoc, tokStart1 = tokStart, val, exprList; next(); - var val = parseExpression(); + var oldParenL = ++metParenL; + if (tokType !== _parenR) { + val = parseExpression(); + exprList = val.type === "SequenceExpression" ? val.expressions : [val]; + } else { + exprList = []; + } + expect(_parenR);
    + +
  • + + +
  • +
    + +
    + +
    +

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

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

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

    + +
    + +
            if (!val) unexpected(lastStart);
    + +
  • + + +
  • +
    + +
    + +
    +

    forbid ‘…’ in sequence expressions

    + +
    + +
            if (options.ecmaVersion >= 6) {
    +          for (var i = 0; i < exprList.length; i++) {
    +            if (exprList[i].type === "SpreadElement") unexpected();
    +          }
    +        }
    +      }
           val.start = tokStart1;
    -      val.end = tokEnd;
    +      val.end = lastEnd;
           if (options.locations) {
             val.loc.start = tokStartLoc1;
    -        val.loc.end = tokEndLoc;
    +        val.loc.end = lastEndLoc;
    +      }
    +      if (options.ranges) {
    +        val.range = [tokStart1, lastEnd];
           }
    -      if (options.ranges)
    -        val.range = [tokStart1, tokEnd];
    -      expect(_parenR);
           return val;
     
         case _bracketL:
           var node = startNode();
    -      next();
    +      next();
    + +
  • + + +
  • +
    + +
    + +
    +

    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"));
    +        }
    +        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");
     
    @@ -3485,13 +4003,20 @@ or {}.

    next(); return parseFunction(node, false); + case _class: + return parseClass(startNode(), false); + case _new: return parseNew(); - case _relational: - if (tokVal === '<') { - return parseXJSElement(); - } + case _ellipsis: + return parseSpread(); + + case _bquote: + return parseTemplate(); + + case _lt: + return parseXJSElement(); default: unexpected(); @@ -3501,11 +4026,11 @@ or {}.

  • -
  • +
  • - +

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

  • -
  • +
  • - + +
    +

    Parse spread element ‘…expr’

    + +
    + +
    +  function parseSpread() {
    +    var node = startNode();
    +    next();
    +    node.argument = parseExpression(true);
    +    return finishNode(node, "SpreadElement");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse template expression.

    + +
    + +
    +  function parseTemplate() {
    +    var node = startNode();
    +    node.expressions = [];
    +    node.quasis = [];
    +    inTemplate = true;
    +    next();
    +    for (;;) {
    +      var elem = startNode();
    +      elem.value = {cooked: tokVal, raw: input.slice(tokStart, tokEnd)};
    +      elem.tail = false;
    +      next();
    +      node.quasis.push(finishNode(elem, "TemplateElement"));
    +      if (eat(_bquote)) { // '`', end of template
    +        elem.tail = true;
    +        break;
    +      }
    +      inTemplate = false;
    +      expect(_dollarBraceL);
    +      node.expressions.push(parseExpression());
    +      inTemplate = true;
    +      expect(_braceR);
    +    }
    +    inTemplate = false;
    +    return finishNode(node, "TemplateLiteral");
    +  }
    + +
  • + + +
  • +
    + +
    +

    Parse an object literal.

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

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

    if (options.allowTrailingCommas && eat(_braceR)) break; } else first = false; - var prop = {key: parsePropertyName()}, isGetSet = false, kind; + var prop = startNode(), kind, isGenerator; + if (options.ecmaVersion >= 6) { + prop.method = false; + prop.shorthand = false; + isGenerator = eat(_star); + } + parsePropertyName(prop); if (eat(_colon)) { prop.value = parseExpression(true); kind = prop.kind = "init"; - } else if (options.ecmaVersion >= 5 && prop.key.type === "Identifier" && + } else if (options.ecmaVersion >= 6 && tokType === _parenL) { + kind = 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")) { - isGetSet = sawGetSet = true; + if (isGenerator) unexpected(); kind = prop.kind = prop.key.name; - prop.key = parsePropertyName(); - if (tokType !== _parenL) unexpected(); - prop.value = parseFunction(startNode(), false); - } else unexpected();
    - -
  • - - -
  • -
    - -
    - -
    -

    getters and setters are not allowed to clash — either with -each other or with an init property — and in strict mode, -init properties are also not allowed to be repeated.

    + parsePropertyName(prop); + prop.value = parseMethod(false); + } else if (options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { + kind = prop.kind = "init"; + prop.value = prop.key; + prop.shorthand = true; + } else unexpected(); -
    - -
    -      if (prop.key.type === "Identifier" && (strict || sawGetSet)) {
    -        for (var i = 0; i < node.properties.length; ++i) {
    -          var other = node.properties[i];
    -          if (other.key.name === prop.key.name) {
    -            var conflict = kind == other.kind || isGetSet && other.kind === "init" ||
    -              kind === "init" && (other.kind === "get" || other.kind === "set");
    -            if (conflict && !strict && kind === "init" && other.kind === "init") conflict = false;
    -            if (conflict) raise(prop.key.start, "Redefinition of property");
    +      checkPropClash(prop, propHash);
    +      node.properties.push(finishNode(prop, "Property"));
               }
    -        }
    -      }
    -      node.properties.push(prop);
    -    }
         return finishNode(node, "ObjectExpression");
    -  }
    +        }
     
    -  function parsePropertyName() {
    -    if (tokType === _num || tokType === _string) return parseExprAtom();
    -    return parseIdent(true);
    +  function parsePropertyName(prop) {
    +    if (options.ecmaVersion >= 6) {
    +      if (eat(_bracketL)) {
    +        prop.computed = true;
    +        prop.key = parseExpression();
    +        expect(_bracketR);
    +        return;
    +      } else {
    +        prop.computed = false;
    +      }
    +    }
    +    prop.key = (tokType === _num || tokType === _string) ? parseExprAtom() : parseIdent(true);
       }
  • -
  • +
  • - + +
    +

    Initialize empty function node.

    + +
    + +
    +  function initFunction(node) {
    +    node.id = null;
    +    node.params = [];
    +    if (options.ecmaVersion >= 6) {
    +      node.defaults = [];
    +      node.rest = null;
    +      node.generator = false;
    +  }
    +  }
    + +
  • + + +
  • +
    + +
    +

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

    @@ -3612,56 +4218,186 @@ init properties are also not allowed to be repeated.

    -  function parseFunction(node, isStatement) {
    -    if (tokType === _name) node.id = parseIdent();
    -    else if (isStatement) unexpected();
    -    else node.id = null;
    -    node.params = [];
    -    node.rest = null;
    +  function parseFunction(node, isStatement, allowExpressionBody) {
    +    initFunction(node);
    +    if (options.ecmaVersion >= 6) {
    +      node.generator = eat(_star);
    +    }
    +    if (isStatement || tokType === _name) {
    +      node.id = parseIdent();
    +    }
    +    parseFunctionParams(node);
    +    parseFunctionBody(node, allowExpressionBody);
    +    return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse object or class method.

    + +
    + +
    +  function parseMethod(isGenerator) {
    +    var node = startNode();
    +    initFunction(node);
    +    parseFunctionParams(node);
    +    var allowExpressionBody;
    +    if (options.ecmaVersion >= 6) {
    +      node.generator = isGenerator;
    +      allowExpressionBody = true;
    +    } else {
    +      allowExpressionBody = false;
    +    }
    +    parseFunctionBody(node, allowExpressionBody);
    +    return finishNode(node, "FunctionExpression");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse arrow function expression with given parameters.

    + +
    + +
    +  function parseArrowExpression(node, params) {
    +    initFunction(node);
    +
    +    var defaults = node.defaults, hasDefaults = false;
    +    
    +    for (var i = 0, lastI = params.length - 1; i <= lastI; i++) {
    +      var param = params[i];
    +
    +      if (param.type === "AssignmentExpression" && param.operator === "=") {
    +        hasDefaults = true;
    +        params[i] = param.left;
    +        defaults.push(param.right);
    +      } else {
    +        toAssignable(param, i === lastI, true);
    +        defaults.push(null);
    +        if (param.type === "SpreadElement") {
    +          params.length--;
    +          node.rest = param.argument;
    +          break;
    +        }
    +      }
    +    }
    +
    +    node.params = params;
    +    if (!hasDefaults) node.defaults = [];
    +
    +    parseFunctionBody(node, true);
    +    return finishNode(node, "ArrowFunctionExpression");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parse function parameters.

    + +
    + +
    +  function parseFunctionParams(node) {
    +    var defaults = [], hasDefaults = false;
    +    
         expect(_parenL);
         for (;;) {
           if (eat(_parenR)) {
             break;
           } else if (options.ecmaVersion >= 6 && eat(_ellipsis)) {
    -        node.rest = parseIdent();
    +        node.rest = toAssignable(parseExprAtom(), false, true);
    +        checkSpreadAssign(node.rest);
             expect(_parenR);
             break;
           } else {
    -        node.params.push(parseIdent());
    +        node.params.push(options.ecmaVersion >= 6 ? toAssignable(parseExprAtom(), false, true) : parseIdent());
    +        if (options.ecmaVersion >= 6 && tokType === _eq) {
    +          next();
    +          hasDefaults = true;
    +          defaults.push(parseExpression(true));
    +        }
             if (!eat(_comma)) {
               expect(_parenR);
               break;
             }
           }
    -    }
    + } + + if (hasDefaults) node.defaults = defaults; + }
  • -
  • +
  • - + +
    +

    Parse function body and check parameters.

    + +
    + +
    +  function parseFunctionBody(node, allowExpression) {
    +    var isExpression = allowExpression && tokType !== _braceL;
    +    
    +    if (isExpression) {
    +      node.body = parseExpression(true);
    +      node.expression = true;
    +    } else {
    + +
  • + + +
  • +
    + +
    +

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

    -
        var oldInFunc = inFunction, oldLabels = labels;
    -    inFunction = true; labels = [];
    +            
          var oldInFunc = inFunction, oldInGen = inGenerator, oldLabels = labels;
    +      inFunction = true; inGenerator = node.generator; labels = [];
         node.body = parseBlock(true);
    -    inFunction = oldInFunc; labels = oldLabels;
    + node.expression = false; + inFunction = oldInFunc; inGenerator = oldInGen; labels = oldLabels; + }
  • -
  • +
  • - +

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

    -
        if (strict || node.body.body.length && isUseStrict(node.body.body[0])) {
    - -
  • - - -
  • -
    - -
    - -
    -

    Negative indices are used to reuse loop body for node.rest and node.id

    - -
    - -
          for (var i = -2, id; i < node.params.length; ++i) {
    -        if (i >= 0) {
    -          id = node.params[i];
    -        } else if (i == -2) {
    -          if (node.rest) id = node.rest;
    -          else continue;
    -        } else {
    -          if (node.id) id = node.id;
    -          else continue;
    -        }
    -        if (isStrictReservedWord(id.name) || isStrictBadIdWord(id.name))
    -          raise(id.start, "Defining '" + id.name + "' in strict mode");
    -        if (i >= 0) for (var j = 0; j < i; ++j) if (id.name === node.params[j].name)
    -          raise(id.start, "Argument name clash in strict mode");
    -      }
    +            
        if (strict || !isExpression && node.body.body.length && isUseStrict(node.body.body[0])) {
    +      var nameHash = hash();
    +      if (node.id)
    +        checkFunctionParam(node.id, nameHash);
    +      for (var i = 0; i < node.params.length; i++)
    +        checkFunctionParam(node.params[i], nameHash);
    +      if (node.rest)
    +        checkFunctionParam(node.rest, nameHash);
         }
    -
    -    return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
       }
  • -
  • +
  • - + +
    +

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

    + +
    + +
      
    +  function parseClass(node, isStatement) {
    +    next();
    +    node.id = tokType === _name ? parseIdent() : isStatement ? unexpected() : null;
    +    node.superClass = eat(_extends) ? parseExpression() : null;
    +    var classBody = startNode(), methodHash = hash(), staticMethodHash = hash();
    +    classBody.body = [];
    +    expect(_braceL);
    +    while (!eat(_braceR)) {
    +      var method = startNode();
    +      if (tokType === _name && tokVal === "static") {
    +        next();
    +        method.static = true;
    +        } else {
    +        method.static = false;
    +        }
    +      var isGenerator = eat(_star);
    +      method.key = parseIdent(true);
    +      if ((method.key.name === "get" || method.key.name === "set") && tokType === _name) {
    +        if (isGenerator) unexpected();
    +        method.kind = method.key.name;
    +        method.key = parseIdent(true);
    +      } else {
    +        method.kind = "";
    +      }
    +      method.value = parseMethod(isGenerator);
    +      checkPropClash(method, method.static ? staticMethodHash : methodHash);
    +      classBody.body.push(finishNode(method, "MethodDefinition"));
    +      eat(_semi);
    +    }
    +    node.body = finishNode(classBody, "ClassBody");
    +    return finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
    +  }
    + +
  • + + +
  • +
    + +
    +

    Parses a comma-separated list of expressions, and returns them as an array. close is the token type that ends the list, and @@ -3739,11 +4499,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 @@ -3776,11 +4536,320 @@ identifiers.

  • -
  • +
  • - + +
    +

    Parses module export declaration.

    + +
    + +
    +  function parseExport(node) {
    +    next();
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
        if (tokType === _var || tokType === _const || tokType === _let || tokType === _function || tokType === _class) {
    +      node.declaration = parseStatement();
    +      node.default = false;
    +      node.specifiers = null;
    +      node.source = null;
    +    } else
    + +
  • + + +
  • +
    + +
    + +
    +

    export default …;

    + +
    + +
        if (eat(_default)) {
    +      node.declaration = parseExpression(true);
    +      node.default = true;
    +      node.specifiers = null;
    +      node.source = null;
    +      semicolon();
    +    } else {
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
          var isBatch = tokType === _star;
    +      node.declaration = null;
    +      node.default = false;
    +      node.specifiers = parseExportSpecifiers();
    +      if (tokType === _name && tokVal === "from") {
    +        next();
    +        node.source = tokType === _string ? parseExprAtom() : unexpected();
    +      } else {
    +        if (isBatch) unexpected();
    +        node.source = null;
    +      }
    +    }
    +    return finishNode(node, "ExportDeclaration");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parses a comma-separated list of module exports.

    + +
    + +
    +  function parseExportSpecifiers() {
    +    var nodes = [], first = true;
    +    if (tokType === _star) {
    + +
  • + + +
  • +
    + +
    + +
    +

    export * from ‘…’

    + +
    + +
          var node = startNode();
    +      next();
    +      nodes.push(finishNode(node, "ExportBatchSpecifier"));
    +    } else {
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
          expect(_braceL);
    +      while (!eat(_braceR)) {
    +        if (!first) {
    +          expect(_comma);
    +          if (options.allowTrailingCommas && eat(_braceR)) break;
    +        } else first = false;
    +
    +        var node = startNode();
    +        node.id = parseIdent();
    +        if (tokType === _name && tokVal === "as") {
    +          next();
    +          node.name = parseIdent(true);
    +        } else {
    +          node.name = null;
    +        }
    +        nodes.push(finishNode(node, "ExportSpecifier"));
    +      }
    +    }
    +    return nodes;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parses import declaration.

    + +
    + +
    +  function parseImport(node) {
    +    next();
    + +
  • + + +
  • +
    + +
    + +
    +

    import ‘…’;

    + +
    + +
        if (tokType === _string) {
    +      node.specifiers = [];
    +      node.source = parseExprAtom();
    +      node.kind = "";
    +    } else {
    +      node.specifiers = parseImportSpecifiers();
    +      if (tokType !== _name || tokVal !== "from") unexpected();
    +      next();
    +      node.source = tokType === _string ? parseExprAtom() : unexpected();
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
          node.kind = node.specifiers[0].default ? "default" : "named";
    +    }
    +    return finishNode(node, "ImportDeclaration");
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parses a comma-separated list of module imports.

    + +
    + +
    +  function parseImportSpecifiers() {
    +    var nodes = [], first = true;
    +    if (tokType === _star) {
    +      var node = startNode();
    +      next();
    +      if (tokType !== _name || tokVal !== "as") unexpected();
    +      next();
    +      node.name = parseIdent();
    +      checkLVal(node.name, true);
    +      nodes.push(finishNode(node, "ImportBatchSpecifier"));
    +      return nodes;
    +    }
    +    if (tokType === _name) {
    + +
  • + + +
  • +
    + +
    + +
    +

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

    + +
    + +
          var node = startNode();
    +      node.id = parseIdent();
    +      checkLVal(node.id, true);
    +      node.name = null;
    +      node.default = true;
    +      nodes.push(finishNode(node, "ImportSpecifier"));
    +      if (!eat(_comma)) return nodes;
    +    }
    +    expect(_braceL);
    +    while (!eat(_braceR)) {
    +      if (!first) {
    +        expect(_comma);
    +        if (options.allowTrailingCommas && eat(_braceR)) break;
    +      } else first = false;
    +
    +      var node = startNode();
    +      node.id = parseIdent(true);
    +      if (tokType === _name && tokVal === "as") {
    +        next();
    +        node.name = parseIdent();
    +      } else {
    +        node.name = null;
    +      }
    +      checkLVal(node.name || node.id, true);
    +      node.default = false;
    +      nodes.push(finishNode(node, "ImportSpecifier"));
    +    }
    +    return nodes;
    +  }
    + +
  • + + +
  • +
    + +
    + +
    +

    Parses yield expression inside generator.

    + +
    + +
    +  function parseYield() {
    +    var node = startNode();
    +    next();
    +    node.delegate = eat(_star);
    +    node.argument = parseExpression(true);
    +    return finishNode(node, "YieldExpression");
    +  }
    + +
  • + + +
  • +
    + +
    +

    Transforms JSX element name to string.

    @@ -3805,11 +4874,11 @@ identifiers.

  • -
  • +
  • - +

    Parse next token as JSX identifier

    @@ -3833,11 +4902,11 @@ identifiers.

  • -
  • +
  • - +

    Parse namespaced identifier.

    @@ -3857,11 +4926,11 @@ identifiers.

  • -
  • +
  • - +

    Parse JSX object.

    @@ -3884,11 +4953,11 @@ identifiers.

  • -
  • +
  • - +

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

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

  • -
  • +
  • - +

    Parses attribute name as optionally namespaced identifier.

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

  • -
  • +
  • - +

    Parses any type of JSX attribute value.

    @@ -3946,34 +5015,37 @@ or single identifier.

       function parseXJSAttributeValue() {
    -    var node;
    -    if (tokType === _braceL) {
    -      node = parseXJSExpressionContainer();
    -      if (node.expression.type === "XJSEmptyExpression") {
    -        raise(
    -          node.start,
    -            'XJS attributes must only be assigned a non-empty ' +
    -            'expression'
    -        );
    -      }
    -    } else if (tokVal === '<') {
    -      node = parseXJSElement();
    -    } else if (tokType === _xjsText) {
    -      node = parseExprAtom();
    -    } else {
    -      raise(tokStart, "XJS value should be either an expression or a quoted XJS text");
    +    switch (tokType) {
    +      case _braceL:
    +        var node = parseXJSExpressionContainer();
    +        if (node.expression.type === "XJSEmptyExpression") {
    +          raise(
    +            node.start,
    +              'XJS attributes must only be assigned a non-empty ' +
    +              'expression'
    +          );
    +        }
    +        return node;
    +
    +      case _lt:
    +        return parseXJSElement();
    +
    +      case _xjsText:
    +        return parseExprAtom();
    +
    +      default:
    +        raise(tokStart, "XJS value should be either an expression or a quoted XJS text");
         }
    -    return node;
       }
  • -
  • +
  • - +

    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 @@ -4003,11 +5075,11 @@ at the beginning of the next one (right brace).

  • -
  • +
  • - +

    Parses JSX expression enclosed into curly brackets.

    @@ -4020,25 +5092,23 @@ at the beginning of the next one (right brace).

    var origInXJSTag = inXJSTag; inXJSTag = false; - expect(_braceL); - + next(); node.expression = tokType === _braceR ? parseXJSEmptyExpression() : parseExpression(); inXJSTag = origInXJSTag; - + expect(_braceR); - return finishNode(node, "XJSExpressionContainer"); }
  • -
  • +
  • - +

    Parses following JSX attribute name-value pair.

    @@ -4046,26 +5116,54 @@ at the beginning of the next one (right brace).

       function parseXJSAttribute() {
    -    var node = startNode();
    +    if (tokType === _braceL) {
    +      var tokStart1 = tokStart, tokStartLoc1 = tokStartLoc;
     
    +      var origInXJSTag = inXJSTag;
    +      inXJSTag = false;
    +
    +      next();
    +      var node = parseSpread();
    +
    +      inXJSTag = origInXJSTag;
    +
    +      expect(_braceR);
    +      node.type = "XJSSpreadAttribute";
    +      
    +      node.start = tokStart1;
    +      node.end = lastEnd;
    +      if (options.locations) {
    +        node.loc.start = tokStartLoc1;
    +        node.loc.end = lastEndLoc;
    +      }
    +      if (options.ranges) {
    +        node.range = [tokStart1, lastEnd];
    +      }
    +
    +      return node;
    +    }
    +
    +    var node = startNode();
         node.name = parseXJSAttributeName();
  • -
  • +
  • - +

    HTML empty attribute

    -
        if (tokVal === "=") {
    +            
        if (tokType === _eq) {
           next();
           node.value = parseXJSAttributeValue();
    +    } else {
    +      node.value = null;
         }
     
         return finishNode(node, "XJSAttribute");
    @@ -4074,11 +5172,11 @@ at the beginning of the next one (right brace).

  • -
  • +
  • - +

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

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

  • -
  • +
  • - +

    Parses JSX open tag.

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

    inXJSChild = false; inXJSTag = true; - expectChar('<'); + next(); node.name = parseXJSElementName(); - while (tokType !== _eof && tokType !== _slash && tokVal !== '>') { + while (tokType !== _eof && tokType !== _slash && tokType !== _gt) { attributes.push(parseXJSAttribute()); } @@ -4137,7 +5235,7 @@ at the beginning of the next one (right brace).

    inXJSChild = true; } - expectChar('>'); + expect(_gt); return finishNode(node, "XJSOpeningElement"); }
    @@ -4145,11 +5243,11 @@ at the beginning of the next one (right brace).

  • -
  • +
  • - +

    Parses JSX closing tag.

    @@ -4163,19 +5261,18 @@ at the beginning of the next one (right brace).

    inXJSChild = false; inXJSTag = true; tokRegexpAllowed = false; - expectChar('<'); - expect(_slash); + expect(_ltSlash); node.name = parseXJSElementName(); skipSpace();
  • -
  • +
  • - +

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

    @@ -4185,18 +5282,18 @@ whether to look for a standard JS token or an XJS text node

        inXJSChild = origInXJSChild;
         inXJSTag = origInXJSTag;
         tokRegexpAllowed = false;
    -    expectChar('>');
    +    expect(_gt);
         return finishNode(node, "XJSClosingElement");
       }
  • -
  • +
  • - +

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

    @@ -4210,14 +5307,15 @@ attributes, contents and closing tag.

    var origInXJSChild = inXJSChild; var openingElement = parseXJSOpeningElement(); + var closingElement = null; if (!openingElement.selfClosing) { - while (tokType !== _eof && !(tokVal === '<' && nextChar() === '/')) { + while (tokType !== _eof && tokType !== _ltSlash) { inXJSChild = true; children.push(parseXJSChild()); } inXJSChild = origInXJSChild; - var closingElement = parseXJSClosingElement(); + closingElement = parseXJSClosingElement(); if (getQualifiedXJSName(closingElement.name) !== getQualifiedXJSName(openingElement.name)) { raise( closingElement.start, @@ -4229,11 +5327,11 @@ attributes, contents and closing tag.

  • -
  • +
  • - +

    When (erroneously) writing two adjacent tags like

    var x = <div>one</div><div>two</div>;
    @@ -4245,7 +5343,7 @@ was intended, the left tag can be wrapped in parentheses.)

    -
        if (!origInXJSChild && tokVal === '<') {
    +            
        if (!origInXJSChild && tokType === _lt) {
           raise(tokStart, "Adjacent XJS elements must be wrapped in an enclosing tag");
         }
     
    diff --git a/package.json b/package.json
    index 4d238cf157..2261fd0c60 100644
    --- a/package.json
    +++ b/package.json
    @@ -2,7 +2,7 @@
         "name": "acorn-jsx",
         "description": "Alternative React JSX parser",
         "main": "acorn.js",
    -    "version": "0.7.1",
    +    "version": "0.7.1-1",
         "maintainers": [
           {
             "name": "Marijn Haverbeke",
    diff --git a/test/run.js b/test/run.js
    index 2d44344745..e1a2753f9e 100644
    --- a/test/run.js
    +++ b/test/run.js
    @@ -1,6 +1,7 @@
     var driver = require("./driver.js");
     require("./tests.js");
     require("./tests-harmony.js");
    +require("./tests-jsx.js");
     
     var testsRun = 0, failed = 0;
     function report(state, code, message) {
    diff --git a/test/tests-jsx.js b/test/tests-jsx.js
    index bd2b7d307f..940b855df8 100644
    --- a/test/tests-jsx.js
    +++ b/test/tests-jsx.js
    @@ -1,486 +1,505 @@
     // React JSX tests
     
    -if (typeof exports !== "undefined") {
    -  var test = require("./driver.js").test;
    -}
    -
    -// Simply taken from esprima-fb/fbtest.js
     var fbTestFixture = {
    -  '': {
    -    type: "ExpressionStatement",
    -    expression: {
    -      type: "XJSElement",
    -      openingElement: {
    -        type: "XJSOpeningElement",
    -        name: {
    -          type: "XJSIdentifier",
    -          name: "a",
    -          range: [1, 2],
    -          loc: {
    -            start: { line: 1, column: 1 },
    -            end: { line: 1, column: 2 }
    -          }
    -        },
    -        selfClosing: true,
    -        attributes: [],
    -        range: [0, 5],
    -        loc: {
    -          start: { line: 1, column: 0 },
    -          end: { line: 1, column: 5 }
    -        }
    -      },
    -      children: [],
    -      range: [0, 5],
    -      loc: {
    -        start: { line: 1, column: 0 },
    -        end: { line: 1, column: 5 }
    -      }
    -    },
    -    range: [0, 5],
    -    loc: {
    -      start: { line: 1, column: 0 },
    -      end: { line: 1, column: 5 }
    -    }
    -  },
    -  '': {
    -    type: 'ExpressionStatement',
    -    expression: {
    -      type: 'XJSElement',
    -      openingElement: {
    -        type: 'XJSOpeningElement',
    -        name: {
    -          type: 'XJSNamespacedName',
    -          namespace: {
    -            type: 'XJSIdentifier',
    -            name: 'n',
    +  // Taken and adapted from esprima-fb/fbtest.js.
    +  'XJS': {
    +    '': {
    +      type: "ExpressionStatement",
    +      expression: {
    +        type: "XJSElement",
    +        openingElement: {
    +          type: "XJSOpeningElement",
    +          name: {
    +            type: "XJSIdentifier",
    +            name: "a",
                 range: [1, 2],
                 loc: {
                   start: { line: 1, column: 1 },
                   end: { line: 1, column: 2 }
                 }
               },
    -          name: {
    -            type: 'XJSIdentifier',
    -            name: 'a',
    -            range: [3, 4],
    -            loc: {
    -              start: { line: 1, column: 3 },
    -              end: { line: 1, column: 4 }
    -            }
    -          },
    -          range: [1, 4],
    +          selfClosing: true,
    +          attributes: [],
    +          range: [0, 5],
               loc: {
    -            start: { line: 1, column: 1 },
    -            end: { line: 1, column: 4 }
    +            start: { line: 1, column: 0 },
    +            end: { line: 1, column: 5 }
               }
             },
    -        selfClosing: true,
    -        attributes: [{
    -          type: 'XJSAttribute',
    +        closingElement: null,
    +        children: [],
    +        range: [0, 5],
    +        loc: {
    +          start: { line: 1, column: 0 },
    +          end: { line: 1, column: 5 }
    +        }
    +      },
    +      range: [0, 5],
    +      loc: {
    +        start: { line: 1, column: 0 },
    +        end: { line: 1, column: 5 }
    +      }
    +    },
    +    '': {
    +      type: 'ExpressionStatement',
    +      expression: {
    +        type: 'XJSElement',
    +        openingElement: {
    +          type: 'XJSOpeningElement',
               name: {
                 type: 'XJSNamespacedName',
                 namespace: {
                   type: 'XJSIdentifier',
                   name: 'n',
    -              range: [5, 6],
    +              range: [1, 2],
                   loc: {
    -                start: { line: 1, column: 5 },
    -                end: { line: 1, column: 6 }
    +                start: { line: 1, column: 1 },
    +                end: { line: 1, column: 2 }
                   }
                 },
                 name: {
                   type: 'XJSIdentifier',
    -              name: 'v',
    -              range: [7, 8],
    -              loc: {
    -                start: { line: 1, column: 7 },
    -                end: { line: 1, column: 8 }
    -              }
    -            },
    -            range: [5, 8],
    -            loc: {
    -              start: { line: 1, column: 5 },
    -              end: { line: 1, column: 8 }
    -            }
    -          },
    -          range: [5, 8],
    -          loc: {
    -            start: { line: 1, column: 5 },
    -            end: { line: 1, column: 8 }
    -          }
    -        }],
    -        range: [0, 11],
    -        loc: {
    -          start: { line: 1, column: 0 },
    -          end: { line: 1, column: 11 }
    -        }
    -      },
    -      children: [],
    -      range: [0, 11],
    -      loc: {
    -        start: { line: 1, column: 0 },
    -        end: { line: 1, column: 11 }
    -      }
    -    },
    -    range: [0, 11],
    -    loc: {
    -      start: { line: 1, column: 0 },
    -      end: { line: 1, column: 11 }
    -    }
    -  },
    -  ' {value} ': {
    -    type: 'ExpressionStatement',
    -    expression: {
    -      type: 'XJSElement',
    -      openingElement: {
    -        type: 'XJSOpeningElement',
    -        name: {
    -          type: 'XJSIdentifier',
    -          name: 'a',
    -          range: [1, 2],
    -          loc: {
    -            start: { line: 1, column: 1 },
    -            end: { line: 1, column: 2 }
    -          }
    -        },
    -        selfClosing: false,
    -        attributes: [{
    -          type: 'XJSAttribute',
    -          name: {
    -            type: 'XJSNamespacedName',
    -            namespace: {
    -              type: 'XJSIdentifier',
    -              name: 'n',
    +              name: 'a',
                   range: [3, 4],
                   loc: {
                     start: { line: 1, column: 3 },
                     end: { line: 1, column: 4 }
                   }
                 },
    +            range: [1, 4],
    +            loc: {
    +              start: { line: 1, column: 1 },
    +              end: { line: 1, column: 4 }
    +            }
    +          },
    +          selfClosing: true,
    +          attributes: [{
    +            type: 'XJSAttribute',
                 name: {
    -              type: 'XJSIdentifier',
    -              name: 'foo',
    +              type: 'XJSNamespacedName',
    +              namespace: {
    +                type: 'XJSIdentifier',
    +                name: 'n',
    +                range: [5, 6],
    +                loc: {
    +                  start: { line: 1, column: 5 },
    +                  end: { line: 1, column: 6 }
    +                }
    +              },
    +              name: {
    +                type: 'XJSIdentifier',
    +                name: 'v',
    +                range: [7, 8],
    +                loc: {
    +                  start: { line: 1, column: 7 },
    +                  end: { line: 1, column: 8 }
    +                }
    +              },
                   range: [5, 8],
                   loc: {
                     start: { line: 1, column: 5 },
                     end: { line: 1, column: 8 }
                   }
                 },
    -            range: [3, 8],
    +            value: null,
    +            range: [5, 8],
                 loc: {
    -              start: { line: 1, column: 3 },
    +              start: { line: 1, column: 5 },
                   end: { line: 1, column: 8 }
                 }
    -          },
    -          value: {
    -            type: 'Literal',
    -            value: 'bar',
    -            raw: '"bar"',
    -            range: [9, 14],
    -            loc: {
    -              start: { line: 1, column: 9 },
    -              end: { line: 1, column: 14 }
    -            }
    -          },
    -          range: [3, 14],
    +          }],
    +          range: [0, 11],
               loc: {
    -            start: { line: 1, column: 3 },
    -            end: { line: 1, column: 14 }
    +            start: { line: 1, column: 0 },
    +            end: { line: 1, column: 11 }
               }
    -        }],
    -        range: [0, 15],
    +        },
    +        closingElement: null,
    +        children: [],
    +        range: [0, 11],
             loc: {
               start: { line: 1, column: 0 },
    -          end: { line: 1, column: 15 }
    +          end: { line: 1, column: 11 }
             }
           },
    -      closingElement: {
    -        type: 'XJSClosingElement',
    -        name: {
    -          type: 'XJSIdentifier',
    -          name: 'a',
    -          range: [38, 39],
    -          loc: {
    -            start: { line: 1, column: 38 },
    -            end: { line: 1, column: 39 }
    -          }
    -        },
    -        range: [36, 40],
    -        loc: {
    -          start: { line: 1, column: 36 },
    -          end: { line: 1, column: 40 }
    -        }
    -      },
    -      children: [{
    -        type: 'Literal',
    -        value: ' ',
    -        raw: ' ',
    -        range: [15, 16],
    -        loc: {
    -          start: { line: 1, column: 15 },
    -          end: { line: 1, column: 16 }
    -        }
    -      }, {
    -        type: 'XJSExpressionContainer',
    -        expression: {
    -          type: 'Identifier',
    -          name: 'value',
    -          range: [17, 22],
    -          loc: {
    -            start: { line: 1, column: 17 },
    -            end: { line: 1, column: 22 }
    -          }
    -        },
    -        range: [16, 23],
    -        loc: {
    -          start: { line: 1, column: 16 },
    -          end: { line: 1, column: 23 }
    -        }
    -      }, {
    -        type: 'Literal',
    -        value: ' ',
    -        raw: ' ',
    -        range: [23, 24],
    -        loc: {
    -          start: { line: 1, column: 23 },
    -          end: { line: 1, column: 24 }
    -        }
    -      }, {
    +      range: [0, 11],
    +      loc: {
    +        start: { line: 1, column: 0 },
    +        end: { line: 1, column: 11 }
    +      }
    +    },
    +    ' {value} ': {
    +      type: 'ExpressionStatement',
    +      expression: {
             type: 'XJSElement',
             openingElement: {
               type: 'XJSOpeningElement',
               name: {
                 type: 'XJSIdentifier',
    -            name: 'b',
    -            range: [25, 26],
    +            name: 'a',
    +            range: [1, 2],
                 loc: {
    -              start: { line: 1, column: 25 },
    -              end: { line: 1, column: 26 }
    +              start: { line: 1, column: 1 },
    +              end: { line: 1, column: 2 }
                 }
               },
               selfClosing: false,
    -          attributes: [],
    -          range: [24, 27],
    +          attributes: [{
    +            type: 'XJSAttribute',
    +            name: {
    +              type: 'XJSNamespacedName',
    +              namespace: {
    +                type: 'XJSIdentifier',
    +                name: 'n',
    +                range: [3, 4],
    +                loc: {
    +                  start: { line: 1, column: 3 },
    +                  end: { line: 1, column: 4 }
    +                }
    +              },
    +              name: {
    +                type: 'XJSIdentifier',
    +                name: 'foo',
    +                range: [5, 8],
    +                loc: {
    +                  start: { line: 1, column: 5 },
    +                  end: { line: 1, column: 8 }
    +                }
    +              },
    +              range: [3, 8],
    +              loc: {
    +                start: { line: 1, column: 3 },
    +                end: { line: 1, column: 8 }
    +              }
    +            },
    +            value: {
    +              type: 'Literal',
    +              value: 'bar',
    +              raw: '"bar"',
    +              range: [9, 14],
    +              loc: {
    +                start: { line: 1, column: 9 },
    +                end: { line: 1, column: 14 }
    +              }
    +            },
    +            range: [3, 14],
    +            loc: {
    +              start: { line: 1, column: 3 },
    +              end: { line: 1, column: 14 }
    +            }
    +          }],
    +          range: [0, 15],
               loc: {
    -            start: { line: 1, column: 24 },
    -            end: { line: 1, column: 27 }
    +            start: { line: 1, column: 0 },
    +            end: { line: 1, column: 15 }
               }
             },
             closingElement: {
               type: 'XJSClosingElement',
               name: {
                 type: 'XJSIdentifier',
    -            name: 'b',
    -            range: [34, 35],
    +            name: 'a',
    +            range: [38, 39],
                 loc: {
    -              start: { line: 1, column: 34 },
    -              end: { line: 1, column: 35 }
    +              start: { line: 1, column: 38 },
    +              end: { line: 1, column: 39 }
                 }
               },
    -          range: [32, 36],
    +          range: [36, 40],
               loc: {
    -            start: { line: 1, column: 32 },
    -            end: { line: 1, column: 36 }
    +            start: { line: 1, column: 36 },
    +            end: { line: 1, column: 40 }
               }
             },
             children: [{
    +          type: 'Literal',
    +          value: ' ',
    +          raw: ' ',
    +          range: [15, 16],
    +          loc: {
    +            start: { line: 1, column: 15 },
    +            end: { line: 1, column: 16 }
    +          }
    +        }, {
    +          type: 'XJSExpressionContainer',
    +          expression: {
    +            type: 'Identifier',
    +            name: 'value',
    +            range: [17, 22],
    +            loc: {
    +              start: { line: 1, column: 17 },
    +              end: { line: 1, column: 22 }
    +            }
    +          },
    +          range: [16, 23],
    +          loc: {
    +            start: { line: 1, column: 16 },
    +            end: { line: 1, column: 23 }
    +          }
    +        }, {
    +          type: 'Literal',
    +          value: ' ',
    +          raw: ' ',
    +          range: [23, 24],
    +          loc: {
    +            start: { line: 1, column: 23 },
    +            end: { line: 1, column: 24 }
    +          }
    +        }, {
               type: 'XJSElement',
               openingElement: {
                 type: 'XJSOpeningElement',
                 name: {
                   type: 'XJSIdentifier',
    -              name: 'c',
    -              range: [28, 29],
    +              name: 'b',
    +              range: [25, 26],
                   loc: {
    -                start: { line: 1, column: 28 },
    -                end: { line: 1, column: 29 }
    +                start: { line: 1, column: 25 },
    +                end: { line: 1, column: 26 }
                   }
                 },
    -            selfClosing: true,
    +            selfClosing: false,
                 attributes: [],
    +            range: [24, 27],
    +            loc: {
    +              start: { line: 1, column: 24 },
    +              end: { line: 1, column: 27 }
    +            }
    +          },
    +          closingElement: {
    +            type: 'XJSClosingElement',
    +            name: {
    +              type: 'XJSIdentifier',
    +              name: 'b',
    +              range: [34, 35],
    +              loc: {
    +                start: { line: 1, column: 34 },
    +                end: { line: 1, column: 35 }
    +              }
    +            },
    +            range: [32, 36],
    +            loc: {
    +              start: { line: 1, column: 32 },
    +              end: { line: 1, column: 36 }
    +            }
    +          },
    +          children: [{
    +            type: 'XJSElement',
    +            openingElement: {
    +              type: 'XJSOpeningElement',
    +              name: {
    +                type: 'XJSIdentifier',
    +                name: 'c',
    +                range: [28, 29],
    +                loc: {
    +                  start: { line: 1, column: 28 },
    +                  end: { line: 1, column: 29 }
    +                }
    +              },
    +              selfClosing: true,
    +              attributes: [],
    +              range: [27, 32],
    +              loc: {
    +                start: { line: 1, column: 27 },
    +                end: { line: 1, column: 32 }
    +              }
    +            },
    +            closingElement: null,
    +            children: [],
                 range: [27, 32],
                 loc: {
                   start: { line: 1, column: 27 },
                   end: { line: 1, column: 32 }
                 }
    -          },
    -          children: [],
    -          range: [27, 32],
    +          }],
    +          range: [24, 36],
               loc: {
    -            start: { line: 1, column: 27 },
    -            end: { line: 1, column: 32 }
    +            start: { line: 1, column: 24 },
    +            end: { line: 1, column: 36 }
               }
             }],
    -        range: [24, 36],
    +        range: [0, 40],
             loc: {
    -          start: { line: 1, column: 24 },
    -          end: { line: 1, column: 36 }
    +          start: { line: 1, column: 0 },
    +          end: { line: 1, column: 40 }
             }
    -      }],
    +      },
           range: [0, 40],
           loc: {
             start: { line: 1, column: 0 },
             end: { line: 1, column: 40 }
           }
         },
    -    range: [0, 40],
    -    loc: {
    -      start: { line: 1, column: 0 },
    -      end: { line: 1, column: 40 }
    -    }
    -  },
    -  '': {
    -    type: "ExpressionStatement",
    -    expression: {
    -      type: "XJSElement",
    -      openingElement: {
    -        type: "XJSOpeningElement",
    -        name: {
    -          type: "XJSIdentifier",
    -          name: "a",
    -          range: [1, 2],
    -          loc: {
    -            start: { line: 1, column: 1 },
    -            end: { line: 1, column: 2 }
    -          }
    -        },
    -        selfClosing: true,
    -        attributes: [
    -          {
    -            type: "XJSAttribute",
    -            name: {
    -              type: "XJSIdentifier",
    -              name: "b",
    -              range: [3, 4],
    -              loc: {
    -                start: { line: 1, column: 3 },
    -                end: { line: 1, column: 4 }
    -              }
    -            },
    -            value: {
    -              type: "XJSExpressionContainer",
    -              expression: {
    -                type: "Literal",
    -                value: " ",
    -                raw: "\" \"",
    -                range: [6, 9],
    +    '': {
    +      type: "ExpressionStatement",
    +      expression: {
    +        type: "XJSElement",
    +        openingElement: {
    +          type: "XJSOpeningElement",
    +          name: {
    +            type: "XJSIdentifier",
    +            name: "a",
    +            range: [1, 2],
    +            loc: {
    +              start: { line: 1, column: 1 },
    +              end: { line: 1, column: 2 }
    +            }
    +          },
    +          selfClosing: true,
    +          attributes: [
    +            {
    +              type: "XJSAttribute",
    +              name: {
    +                type: "XJSIdentifier",
    +                name: "b",
    +                range: [3, 4],
                     loc: {
    -                  start: { line: 1, column: 6 },
    -                  end: { line: 1, column: 9 }
    +                  start: { line: 1, column: 3 },
    +                  end: { line: 1, column: 4 }
                     }
                   },
    -              range: [5, 10],
    +              value: {
    +                type: "XJSExpressionContainer",
    +                expression: {
    +                  type: "Literal",
    +                  value: " ",
    +                  raw: "\" \"",
    +                  range: [6, 9],
    +                  loc: {
    +                    start: { line: 1, column: 6 },
    +                    end: { line: 1, column: 9 }
    +                  }
    +                },
    +                range: [5, 10],
    +                loc: {
    +                  start: { line: 1, column: 5 },
    +                  end: { line: 1, column: 10 }
    +                }
    +              },
    +              range: [3, 10],
                   loc: {
    -                start: { line: 1, column: 5 },
    +                start: { line: 1, column: 3 },
                     end: { line: 1, column: 10 }
                   }
                 },
    -            range: [3, 10],
    -            loc: {
    -              start: { line: 1, column: 3 },
    -              end: { line: 1, column: 10 }
    -            }
    -          },
    -          {
    -            type: "XJSAttribute",
    -            name: {
    -              type: "XJSIdentifier",
    -              name: "c",
    -              range: [11, 12],
    +            {
    +              type: "XJSAttribute",
    +              name: {
    +                type: "XJSIdentifier",
    +                name: "c",
    +                range: [11, 12],
    +                loc: {
    +                  start: { line: 1, column: 11 },
    +                  end: { line: 1, column: 12 }
    +                }
    +              },
    +              value: {
    +                type: "Literal",
    +                value: " ",
    +                raw: "\" \"",
    +                range: [13, 16],
    +                loc: {
    +                  start: { line: 1, column: 13 },
    +                  end: { line: 1, column: 16 }
    +                }
    +              },
    +              range: [11, 16],
                   loc: {
                     start: { line: 1, column: 11 },
    -                end: { line: 1, column: 12 }
    -              }
    -            },
    -            value: {
    -              type: "Literal",
    -              value: " ",
    -              raw: "\" \"",
    -              range: [13, 16],
    -              loc: {
    -                start: { line: 1, column: 13 },
                     end: { line: 1, column: 16 }
                   }
                 },
    -            range: [11, 16],
    -            loc: {
    -              start: { line: 1, column: 11 },
    -              end: { line: 1, column: 16 }
    -            }
    -          },
    -          {
    -            type: "XJSAttribute",
    -            name: {
    -              type: "XJSIdentifier",
    -              name: "d",
    -              range: [17, 18],
    +            {
    +              type: "XJSAttribute",
    +              name: {
    +                type: "XJSIdentifier",
    +                name: "d",
    +                range: [17, 18],
    +                loc: {
    +                  start: { line: 1, column: 17 },
    +                  end: { line: 1, column: 18 }
    +                }
    +              },
    +              value: {
    +                type: "Literal",
    +                value: "&",
    +                raw: "\"&\"",
    +                range: [19, 26],
    +                loc: {
    +                  start: { line: 1, column: 19 },
    +                  end: { line: 1, column: 26 }
    +                }
    +              },
    +              range: [17, 26],
                   loc: {
                     start: { line: 1, column: 17 },
    -                end: { line: 1, column: 18 }
    -              }
    -            },
    -            value: {
    -              type: "Literal",
    -              value: "&",
    -              raw: "\"&\"",
    -              range: [19, 26],
    -              loc: {
    -                start: { line: 1, column: 19 },
                     end: { line: 1, column: 26 }
                   }
    -            },
    -            range: [17, 26],
    -            loc: {
    -              start: { line: 1, column: 17 },
    -              end: { line: 1, column: 26 }
                 }
    +          ],
    +          range: [0, 29],
    +          loc: {
    +            start: { line: 1, column: 0 },
    +            end: { line: 1, column: 29 }
               }
    -        ],
    +        },
    +        closingElement: null,
    +        children: [],
             range: [0, 29],
             loc: {
               start: { line: 1, column: 0 },
               end: { line: 1, column: 29 }
             }
           },
    -      children: [],
           range: [0, 29],
           loc: {
             start: { line: 1, column: 0 },
             end: { line: 1, column: 29 }
           }
         },
    -    range: [0, 29],
    -    loc: {
    -      start: { line: 1, column: 0 },
    -      end: { line: 1, column: 29 }
    -    }
    -  },
    -  '': {
    -    type: "ExpressionStatement",
    -    expression: {
    -      type: "XJSElement",
    -      openingElement: {
    -        type: "XJSOpeningElement",
    -        name: {
    -          type: "XJSIdentifier",
    -          name: "a",
    +    '': {
    +      type: "ExpressionStatement",
    +      expression: {
    +        type: "XJSElement",
    +        openingElement: {
    +          type: "XJSOpeningElement",
    +          name: {
    +            type: "XJSIdentifier",
    +            name: "a",
    +            range: [
    +              1,
    +              2
    +            ],
    +            loc: {
    +              start: {
    +                line: 1,
    +                column: 1
    +              },
    +              end: {
    +                line: 1,
    +                column: 2
    +              }
    +            }
    +          },
    +          selfClosing: true,
    +          attributes: [],
               range: [
    -            1,
    -            2
    +            0,
    +            5
               ],
               loc: {
                 start: {
                   line: 1,
    -              column: 1
    +              column: 0
                 },
                 end: {
    -              line: 1,
    +              line: 2,
                   column: 2
                 }
               }
             },
    -        selfClosing: true,
    -        attributes: [],
    +        closingElement: null,
    +        children: [],
             range: [
               0,
               5
    @@ -496,7 +515,6 @@ var fbTestFixture = {
               }
             }
           },
    -      children: [],
           range: [
             0,
             5
    @@ -512,884 +530,67 @@ var fbTestFixture = {
             }
           }
         },
    -    range: [
    -      0,
    -      5
    -    ],
    -    loc: {
    -      start: {
    -        line: 1,
    -        column: 0
    -      },
    -      end: {
    -        line: 2,
    -        column: 2
    -      }
    -    }
    -  },
    -  '<日本語>': {
    -    type: "ExpressionStatement",
    -    expression: {
    -      type: "XJSElement",
    -      openingElement: {
    -        type: "XJSOpeningElement",
    -        name: {
    -          type: "XJSIdentifier",
    -          name: "日本語",
    -          range: [
    -            1,
    -            4
    -          ],
    -          loc: {
    -            start: {
    -              line: 1,
    -              column: 1
    -            },
    -            end: {
    -              line: 1,
    -              column: 4
    -            }
    -          }
    -        },
    -        selfClosing: false,
    -        attributes: [],
    -        range: [
    -          0,
    -          5
    -        ],
    -        loc: {
    -          start: {
    -            line: 1,
    -            column: 0
    -          },
    -          end: {
    -            line: 1,
    -            column: 5
    -          }
    -        }
    -      },
    -      closingElement: {
    -        type: "XJSClosingElement",
    -        name: {
    -          type: "XJSIdentifier",
    -          name: "日本語",
    -          range: [
    -            7,
    -            10
    -          ],
    -          loc: {
    -            start: {
    -              line: 1,
    -              column: 7
    -            },
    -            end: {
    -              line: 1,
    -              column: 10
    -            }
    -          }
    -        },
    -        range: [
    -          5,
    -          11
    -        ],
    -        loc: {
    -          start: {
    -            line: 1,
    -            column: 5
    -          },
    -          end: {
    -            line: 1,
    -            column: 11
    -          }
    -        }
    -      },
    -      children: [],
    -      range: [
    -        0,
    -        11
    -      ],
    -      loc: {
    -        start: {
    -          line: 1,
    -          column: 0
    -        },
    -        end: {
    -          line: 1,
    -          column: 11
    -        }
    -      }
    -    },
    -    range: [
    -      0,
    -      11
    -    ],
    -    loc: {
    -      start: {
    -        line: 1,
    -        column: 0
    -      },
    -      end: {
    -        line: 1,
    -        column: 11
    -      }
    -    }
    -  },
    -
    -  '\nbar\nbaz\r\n': {
    -    type: "ExpressionStatement",
    -    expression: {
    -      type: "XJSElement",
    -      openingElement: {
    -        type: "XJSOpeningElement",
    -        name: {
    -          type: "XJSIdentifier",
    -          name: "AbC-def",
    -          range: [
    -            1,
    -            8
    -          ],
    -          loc: {
    -            start: {
    -              line: 1,
    -              column: 1
    -            },
    -            end: {
    -              line: 1,
    -              column: 8
    -            }
    -          }
    -        },
    -        selfClosing: false,
    -        attributes: [
    -          {
    -            type: "XJSAttribute",
    -            name: {
    -              type: "XJSIdentifier",
    -              name: "test",
    -              range: [
    -                11,
    -                15
    -              ],
    -              loc: {
    -                start: {
    -                  line: 2,
    -                  column: 2
    -                },
    -                end: {
    -                  line: 2,
    -                  column: 6
    -                }
    -              }
    -            },
    -            value: {
    -              type: "Literal",
    -              value: "&&",
    -              raw: "\"&&\"",
    -              range: [
    -                16,
    -                31
    -              ],
    -              loc: {
    -                start: {
    -                  line: 2,
    -                  column: 7
    -                },
    -                end: {
    -                  line: 2,
    -                  column: 22
    -                }
    -              }
    -            },
    -            range: [
    -              11,
    -              31
    -            ],
    -            loc: {
    -              start: {
    -                line: 2,
    -                column: 2
    -              },
    -              end: {
    -                line: 2,
    -                column: 22
    -              }
    -            }
    -          }
    -        ],
    -        range: [
    -          0,
    -          32
    -        ],
    -        loc: {
    -          start: {
    -            line: 1,
    -            column: 0
    -          },
    -          end: {
    -            line: 2,
    -            column: 23
    -          }
    -        }
    -      },
    -      closingElement: {
    -        type: "XJSClosingElement",
    -        name: {
    -          type: "XJSIdentifier",
    -          name: "AbC-def",
    -          range: [
    -            44,
    -            51
    -          ],
    -          loc: {
    -            start: {
    -              line: 5,
    -              column: 2
    -            },
    -            end: {
    -              line: 5,
    -              column: 9
    -            }
    -          }
    -        },
    -        range: [
    -          42,
    -          52
    -        ],
    -        loc: {
    -          start: {
    -            line: 5,
    -            column: 0
    -          },
    -          end: {
    -            line: 5,
    -            column: 10
    -          }
    -        }
    -      },
    -      children: [
    -        {
    -          type: "Literal",
    -          value: "\nbar\nbaz\r\n",
    -          raw: "\nbar\nbaz\r\n",
    -          range: [
    -            32,
    -            42
    -          ],
    -          loc: {
    -            start: {
    -              line: 2,
    -              column: 23
    -            },
    -            end: {
    -              line: 5,
    -              column: 0
    -            }
    -          }
    -        }
    -      ],
    -      range: [
    -        0,
    -        52
    -      ],
    -      loc: {
    -        start: {
    -          line: 1,
    -          column: 0
    -        },
    -        end: {
    -          line: 5,
    -          column: 10
    -        }
    -      }
    -    },
    -    range: [
    -      0,
    -      52
    -    ],
    -    loc: {
    -      start: {
    -        line: 1,
    -        column: 0
    -      },
    -      end: {
    -        line: 5,
    -        column: 10
    -      }
    -    }
    -  },
    -
    -  ' : } />': {
    -    type: "ExpressionStatement",
    -    expression: {
    -      type: "XJSElement",
    -      openingElement: {
    -        type: "XJSOpeningElement",
    -        name: {
    -          type: "XJSIdentifier",
    -          name: "a",
    -          range: [
    -            1,
    -            2
    -          ],
    -          loc: {
    -            start: {
    -              line: 1,
    -              column: 1
    -            },
    -            end: {
    -              line: 1,
    -              column: 2
    -            }
    -          }
    -        },
    -        selfClosing: true,
    -        attributes: [
    -          {
    -            type: "XJSAttribute",
    -            name: {
    -              type: "XJSIdentifier",
    -              name: "b",
    -              range: [
    -                3,
    -                4
    -              ],
    -              loc: {
    -                start: {
    -                  line: 1,
    -                  column: 3
    -                },
    -                end: {
    -                  line: 1,
    -                  column: 4
    -                }
    -              }
    -            },
    -            value: {
    -              type: "XJSExpressionContainer",
    -              expression: {
    -                type: "ConditionalExpression",
    -                test: {
    -                  type: "Identifier",
    -                  name: "x",
    -                  range: [
    -                    6,
    -                    7
    -                  ],
    -                  loc: {
    -                    start: {
    -                      line: 1,
    -                      column: 6
    -                    },
    -                    end: {
    -                      line: 1,
    -                      column: 7
    -                    }
    -                  }
    -                },
    -                consequent: {
    -                  type: "XJSElement",
    -                  openingElement: {
    -                    type: "XJSOpeningElement",
    -                    name: {
    -                      type: "XJSIdentifier",
    -                      name: "c",
    -                      range: [
    -                        11,
    -                        12
    -                      ],
    -                      loc: {
    -                        start: {
    -                          line: 1,
    -                          column: 11
    -                        },
    -                        end: {
    -                          line: 1,
    -                          column: 12
    -                        }
    -                      }
    -                    },
    -                    selfClosing: true,
    -                    attributes: [],
    -                    range: [
    -                      10,
    -                      15
    -                    ],
    -                    loc: {
    -                      start: {
    -                        line: 1,
    -                        column: 10
    -                      },
    -                      end: {
    -                        line: 1,
    -                        column: 15
    -                      }
    -                    }
    -                  },
    -                  children: [],
    -                  range: [
    -                    10,
    -                    15
    -                  ],
    -                  loc: {
    -                    start: {
    -                      line: 1,
    -                      column: 10
    -                    },
    -                    end: {
    -                      line: 1,
    -                      column: 15
    -                    }
    -                  }
    -                },
    -                alternate: {
    -                  type: "XJSElement",
    -                  openingElement: {
    -                    type: "XJSOpeningElement",
    -                    name: {
    -                      type: "XJSIdentifier",
    -                      name: "d",
    -                      range: [
    -                        19,
    -                        20
    -                      ],
    -                      loc: {
    -                        start: {
    -                          line: 1,
    -                          column: 19
    -                        },
    -                        end: {
    -                          line: 1,
    -                          column: 20
    -                        }
    -                      }
    -                    },
    -                    selfClosing: true,
    -                    attributes: [],
    -                    range: [
    -                      18,
    -                      23
    -                    ],
    -                    loc: {
    -                      start: {
    -                        line: 1,
    -                        column: 18
    -                      },
    -                      end: {
    -                        line: 1,
    -                        column: 23
    -                      }
    -                    }
    -                  },
    -                  children: [],
    -                  range: [
    -                    18,
    -                    23
    -                  ],
    -                  loc: {
    -                    start: {
    -                      line: 1,
    -                      column: 18
    -                    },
    -                    end: {
    -                      line: 1,
    -                      column: 23
    -                    }
    -                  }
    -                },
    -                range: [
    -                  6,
    -                  23
    -                ],
    -                loc: {
    -                  start: {
    -                    line: 1,
    -                    column: 6
    -                  },
    -                  end: {
    -                    line: 1,
    -                    column: 23
    -                  }
    -                }
    -              },
    -              range: [
    -                5,
    -                24
    -              ],
    -              loc: {
    -                start: {
    -                  line: 1,
    -                  column: 5
    -                },
    -                end: {
    -                  line: 1,
    -                  column: 24
    -                }
    -              }
    -            },
    -            range: [
    -              3,
    -              24
    -            ],
    -            loc: {
    -              start: {
    -                line: 1,
    -                column: 3
    -              },
    -              end: {
    -                line: 1,
    -                column: 24
    -              }
    -            }
    -          }
    -        ],
    -        range: [
    -          0,
    -          27
    -        ],
    -        loc: {
    -          start: {
    -            line: 1,
    -            column: 0
    -          },
    -          end: {
    -            line: 1,
    -            column: 27
    -          }
    -        }
    -      },
    -      children: [],
    -      range: [
    -        0,
    -        27
    -      ],
    -      loc: {
    -        start: {
    -          line: 1,
    -          column: 0
    -        },
    -        end: {
    -          line: 1,
    -          column: 27
    -        }
    -      }
    -    },
    -    range: [
    -      0,
    -      27
    -    ],
    -    loc: {
    -      start: {
    -        line: 1,
    -        column: 0
    -      },
    -      end: {
    -        line: 1,
    -        column: 27
    -      }
    -    }
    -  },
    -
    -  '{}': {
    -    type: 'ExpressionStatement',
    -    expression: {
    -      type: 'XJSElement',
    -      openingElement: {
    -        type: 'XJSOpeningElement',
    -        name: {
    -          type: 'XJSIdentifier',
    -          name: 'a',
    -          range: [1, 2],
    -          loc: {
    -            start: { line: 1, column: 1 },
    -            end: { line: 1, column: 2 }
    -          }
    -        },
    -        selfClosing: false,
    -        attributes: [],
    -        range: [0, 3],
    -        loc: {
    -          start: { line: 1, column: 0 },
    -          end: { line: 1, column: 3 }
    -        }
    -      },
    -      closingElement: {
    -        type: 'XJSClosingElement',
    -        name: {
    -          type: 'XJSIdentifier',
    -          name: 'a',
    -          range: [7, 8],
    -          loc: {
    -            start: { line: 1, column: 7 },
    -            end: { line: 1, column: 8 }
    -          }
    -        },
    -        range: [5, 9],
    -        loc: {
    -          start: { line: 1, column: 5 },
    -          end: { line: 1, column: 9 }
    -        }
    -      },
    -      children: [{
    -        type: 'XJSExpressionContainer',
    -        expression: {
    -          type: 'XJSEmptyExpression',
    -          range: [4, 4],
    -          loc: {
    -            start: { line: 1, column: 4 },
    -            end: { line: 1, column: 4 }
    -          }
    -        },
    -        range: [3, 5],
    -        loc: {
    -          start: { line: 1, column: 3 },
    -          end: { line: 1, column: 5 }
    -        }
    -      }],
    -      range: [0, 9],
    -      loc: {
    -        start: { line: 1, column: 0 },
    -        end: { line: 1, column: 9 }
    -      }
    -    },
    -    range: [0, 9],
    -    loc: {
    -      start: { line: 1, column: 0 },
    -      end: { line: 1, column: 9 }
    -    }
    -  },
    -
    -  '{/* this is a comment */}': {
    -    type: 'ExpressionStatement',
    -    expression: {
    -      type: 'XJSElement',
    -      openingElement: {
    -        type: 'XJSOpeningElement',
    -        name: {
    -          type: 'XJSIdentifier',
    -          name: 'a',
    -          range: [1, 2],
    -          loc: {
    -            start: { line: 1, column: 1 },
    -            end: { line: 1, column: 2 }
    -          }
    -        },
    -        selfClosing: false,
    -        attributes: [],
    -        range: [0, 3],
    -        loc: {
    -          start: { line: 1, column: 0 },
    -          end: { line: 1, column: 3 }
    -        }
    -      },
    -      closingElement: {
    -        type: 'XJSClosingElement',
    -        name: {
    -          type: 'XJSIdentifier',
    -          name: 'a',
    -          range: [30, 31],
    -          loc: {
    -            start: { line: 1, column: 30 },
    -            end: { line: 1, column: 31 }
    -          }
    -        },
    -        range: [28, 32],
    -        loc: {
    -          start: { line: 1, column: 28 },
    -          end: { line: 1, column: 32 }
    -        }
    -      },
    -      children: [{
    -        type: 'XJSExpressionContainer',
    -        expression: {
    -          type: 'XJSEmptyExpression',
    -          range: [4, 27],
    -          loc: {
    -            start: { line: 1, column: 4 },
    -            end: { line: 1, column: 27 }
    -          }
    -        },
    -        range: [3, 28],
    -        loc: {
    -          start: { line: 1, column: 3 },
    -          end: { line: 1, column: 28 }
    -        }
    -      }],
    -      range: [0, 32],
    -      loc: {
    -        start: { line: 1, column: 0 },
    -        end: { line: 1, column: 32 }
    -      }
    -    },
    -    range: [0, 32],
    -    loc: {
    -      start: { line: 1, column: 0 },
    -      end: { line: 1, column: 32 }
    -    }
    -  },
    -
    -  '
    @test content
    ': { - type: 'ExpressionStatement', - expression: { - type: 'XJSElement', - openingElement: { - type: 'XJSOpeningElement', - name: { - type: 'XJSIdentifier', - name: 'div', - range: [1, 4], - loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 4 } - } - }, - selfClosing: false, - attributes: [], - range: [0, 5], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 5 } - } - }, - closingElement: { - type: 'XJSClosingElement', - name: { - type: 'XJSIdentifier', - name: 'div', - range: [20, 23], - loc: { - start: { line: 1, column: 20 }, - end: { line: 1, column: 23 } - } - }, - range: [18, 24], - loc: { - start: { line: 1, column: 18 }, - end: { line: 1, column: 24 } - } - }, - children: [{ - type: 'Literal', - value: '@test content', - raw: '@test content', - range: [5, 18], - loc: { - start: { line: 1, column: 5 }, - end: { line: 1, column: 18 } - } - }], - range: [0, 24], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 24 } - } - }, - range: [0, 24], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 24 } - } - }, - - '

    7x invalid-js-identifier
    ': { - type: 'ExpressionStatement', - expression: { - type: 'XJSElement', - openingElement: { - type: 'XJSOpeningElement', - name: { - type: 'XJSIdentifier', - name: 'div', - range: [ - 1, - 4 - ], - loc: { - start: { - line: 1, - column: 1 - }, - end: { - line: 1, - column: 4 - } - } - }, - selfClosing: false, - attributes: [], - range: [ - 0, - 5 - ], - loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 5 - } - } - }, - closingElement: { - type: 'XJSClosingElement', - name: { - type: 'XJSIdentifier', - name: 'div', - range: [ - 37, - 40 - ], - loc: { - start: { - line: 1, - column: 37 - }, - end: { - line: 1, - column: 40 - } - } - }, - range: [ - 35, - 41 - ], - loc: { - start: { - line: 1, - column: 35 - }, - end: { - line: 1, - column: 41 - } - } - }, - children: [{ - type: 'XJSElement', + '<日本語>': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", openingElement: { - type: 'XJSOpeningElement', + type: "XJSOpeningElement", name: { - type: 'XJSIdentifier', - name: 'br', + type: "XJSIdentifier", + name: "日本語", range: [ - 6, - 8 + 1, + 4 ], loc: { start: { line: 1, - column: 6 + column: 1 }, end: { line: 1, - column: 8 + column: 4 } } }, - selfClosing: true, + selfClosing: false, attributes: [], + range: [ + 0, + 5 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 5 + } + } + }, + closingElement: { + type: "XJSClosingElement", + name: { + type: "XJSIdentifier", + name: "日本語", + range: [ + 7, + 10 + ], + loc: { + start: { + line: 1, + column: 7 + }, + end: { + line: 1, + column: 10 + } + } + }, range: [ 5, 11 @@ -1407,38 +608,859 @@ var fbTestFixture = { }, children: [], range: [ - 5, + 0, 11 ], loc: { start: { line: 1, - column: 5 + column: 0 }, end: { line: 1, column: 11 } } - }, { - type: 'Literal', - value: '7x invalid-js-identifier', - raw: '7x invalid-js-identifier', + }, + range: [ + 0, + 11 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 11 + } + } + }, + + '\nbar\nbaz\n': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "AbC-def", + range: [ + 1, + 8 + ], + loc: { + start: { + line: 1, + column: 1 + }, + end: { + line: 1, + column: 8 + } + } + }, + selfClosing: false, + attributes: [ + { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "test", + range: [ + 11, + 15 + ], + loc: { + start: { + line: 2, + column: 2 + }, + end: { + line: 2, + column: 6 + } + } + }, + value: { + type: "Literal", + value: "&&", + raw: "\"&&\"", + range: [ + 16, + 31 + ], + loc: { + start: { + line: 2, + column: 7 + }, + end: { + line: 2, + column: 22 + } + } + }, + range: [ + 11, + 31 + ], + loc: { + start: { + line: 2, + column: 2 + }, + end: { + line: 2, + column: 22 + } + } + } + ], + range: [ + 0, + 32 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 2, + column: 23 + } + } + }, + closingElement: { + type: "XJSClosingElement", + name: { + type: "XJSIdentifier", + name: "AbC-def", + range: [ + 43, + 50 + ], + loc: { + start: { + line: 5, + column: 2 + }, + end: { + line: 5, + column: 9 + } + } + }, + range: [ + 41, + 51 + ], + loc: { + start: { + line: 5, + column: 0 + }, + end: { + line: 5, + column: 10 + } + } + }, + children: [ + { + type: "Literal", + value: "\nbar\nbaz\n", + raw: "\nbar\nbaz\n", + range: [ + 32, + 41 + ], + loc: { + start: { + line: 2, + column: 23 + }, + end: { + line: 5, + column: 0 + } + } + } + ], range: [ - 11, - 35 + 0, + 51 ], loc: { start: { line: 1, - column: 11 + column: 0 + }, + end: { + line: 5, + column: 10 + } + } + }, + range: [ + 0, + 51 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 5, + column: 10 + } + } + }, + + ' : } />': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "a", + range: [ + 1, + 2 + ], + loc: { + start: { + line: 1, + column: 1 + }, + end: { + line: 1, + column: 2 + } + } + }, + selfClosing: true, + attributes: [ + { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "b", + range: [ + 3, + 4 + ], + loc: { + start: { + line: 1, + column: 3 + }, + end: { + line: 1, + column: 4 + } + } + }, + value: { + type: "XJSExpressionContainer", + expression: { + type: "ConditionalExpression", + test: { + type: "Identifier", + name: "x", + range: [ + 6, + 7 + ], + loc: { + start: { + line: 1, + column: 6 + }, + end: { + line: 1, + column: 7 + } + } + }, + consequent: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "c", + range: [ + 11, + 12 + ], + loc: { + start: { + line: 1, + column: 11 + }, + end: { + line: 1, + column: 12 + } + } + }, + selfClosing: true, + attributes: [], + range: [ + 10, + 15 + ], + loc: { + start: { + line: 1, + column: 10 + }, + end: { + line: 1, + column: 15 + } + } + }, + closingElement: null, + children: [], + range: [ + 10, + 15 + ], + loc: { + start: { + line: 1, + column: 10 + }, + end: { + line: 1, + column: 15 + } + } + }, + alternate: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "d", + range: [ + 19, + 20 + ], + loc: { + start: { + line: 1, + column: 19 + }, + end: { + line: 1, + column: 20 + } + } + }, + selfClosing: true, + attributes: [], + range: [ + 18, + 23 + ], + loc: { + start: { + line: 1, + column: 18 + }, + end: { + line: 1, + column: 23 + } + } + }, + closingElement: null, + children: [], + range: [ + 18, + 23 + ], + loc: { + start: { + line: 1, + column: 18 + }, + end: { + line: 1, + column: 23 + } + } + }, + range: [ + 6, + 23 + ], + loc: { + start: { + line: 1, + column: 6 + }, + end: { + line: 1, + column: 23 + } + } + }, + range: [ + 5, + 24 + ], + loc: { + start: { + line: 1, + column: 5 + }, + end: { + line: 1, + column: 24 + } + } + }, + range: [ + 3, + 24 + ], + loc: { + start: { + line: 1, + column: 3 + }, + end: { + line: 1, + column: 24 + } + } + } + ], + range: [ + 0, + 27 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 27 + } + } + }, + closingElement: null, + children: [], + range: [ + 0, + 27 + ], + loc: { + start: { + line: 1, + column: 0 }, end: { line: 1, - column: 35 + column: 27 } } - }], + }, + range: [ + 0, + 27 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 27 + } + } + }, + + '{}': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + selfClosing: false, + attributes: [], + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + range: [5, 9], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 9 } + } + }, + children: [{ + type: 'XJSExpressionContainer', + expression: { + type: 'XJSEmptyExpression', + range: [4, 4], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 4 } + } + }, + range: [3, 5], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 5 } + } + }], + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + + '{/* this is a comment */}': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + selfClosing: false, + attributes: [], + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'a', + range: [30, 31], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 31 } + } + }, + range: [28, 32], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 32 } + } + }, + children: [{ + type: 'XJSExpressionContainer', + expression: { + type: 'XJSEmptyExpression', + range: [4, 27], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 27 } + } + }, + range: [3, 28], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 28 } + } + }], + range: [0, 32], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 32 } + } + }, + range: [0, 32], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 32 } + } + }, + + '
    @test content
    ': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [1, 4], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 4 } + } + }, + selfClosing: false, + attributes: [], + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [20, 23], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 23 } + } + }, + range: [18, 24], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 24 } + } + }, + children: [{ + type: 'Literal', + value: '@test content', + raw: '@test content', + range: [5, 18], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 18 } + } + }], + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + }, + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + }, + + '

    7x invalid-js-identifier
    ': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [ + 1, + 4 + ], + loc: { + start: { + line: 1, + column: 1 + }, + end: { + line: 1, + column: 4 + } + } + }, + selfClosing: false, + attributes: [], + range: [ + 0, + 5 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 5 + } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [ + 37, + 40 + ], + loc: { + start: { + line: 1, + column: 37 + }, + end: { + line: 1, + column: 40 + } + } + }, + range: [ + 35, + 41 + ], + loc: { + start: { + line: 1, + column: 35 + }, + end: { + line: 1, + column: 41 + } + } + }, + children: [{ + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'br', + range: [ + 6, + 8 + ], + loc: { + start: { + line: 1, + column: 6 + }, + end: { + line: 1, + column: 8 + } + } + }, + selfClosing: true, + attributes: [], + range: [ + 5, + 11 + ], + loc: { + start: { + line: 1, + column: 5 + }, + end: { + line: 1, + column: 11 + } + } + }, + closingElement: null, + children: [], + range: [ + 5, + 11 + ], + loc: { + start: { + line: 1, + column: 5 + }, + end: { + line: 1, + column: 11 + } + } + }, { + type: 'Literal', + value: '7x invalid-js-identifier', + raw: '7x invalid-js-identifier', + range: [ + 11, + 35 + ], + loc: { + start: { + line: 1, + column: 11 + }, + end: { + line: 1, + column: 35 + } + } + }], + range: [ + 0, + 41 + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 41 + } + } + }, range: [ 0, 41 @@ -1454,92 +1476,94 @@ var fbTestFixture = { } } }, - range: [ - 0, - 41 - ], - loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 41 - } - } - }, - ' right=monkeys /> gorillas />': { - "type": "ExpressionStatement", - "expression": { - "type": "XJSElement", - "openingElement": { - "type": "XJSOpeningElement", - "name": { - "type": "XJSIdentifier", - "name": "LeftRight", - "range": [ - 1, - 10 - ], - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 10 - } - } - }, - "selfClosing": true, - "attributes": [ - { - "type": "XJSAttribute", - "name": { - "type": "XJSIdentifier", - "name": "left", - "range": [ - 11, - 15 - ], - "loc": { - "start": { - "line": 1, - "column": 11 - }, - "end": { - "line": 1, - "column": 15 - } + ' right=monkeys /> gorillas />': { + "type": "ExpressionStatement", + "expression": { + "type": "XJSElement", + "openingElement": { + "type": "XJSOpeningElement", + "name": { + "type": "XJSIdentifier", + "name": "LeftRight", + "range": [ + 1, + 10 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 10 } - }, - "value": { - "type": "XJSElement", - "openingElement": { - "type": "XJSOpeningElement", - "name": { - "type": "XJSIdentifier", - "name": "a", + } + }, + "selfClosing": true, + "attributes": [ + { + "type": "XJSAttribute", + "name": { + "type": "XJSIdentifier", + "name": "left", + "range": [ + 11, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 15 + } + } + }, + "value": { + "type": "XJSElement", + "openingElement": { + "type": "XJSOpeningElement", + "name": { + "type": "XJSIdentifier", + "name": "a", + "range": [ + 17, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + "selfClosing": true, + "attributes": [], "range": [ - 17, - 18 + 16, + 21 ], "loc": { "start": { "line": 1, - "column": 17 + "column": 16 }, "end": { "line": 1, - "column": 18 + "column": 21 } } }, - "selfClosing": true, - "attributes": [], + closingElement: null, + "children": [], "range": [ 16, 21 @@ -1555,15 +1579,14 @@ var fbTestFixture = { } } }, - "children": [], "range": [ - 16, + 11, 21 ], "loc": { "start": { "line": 1, - "column": 16 + "column": 11 }, "end": { "line": 1, @@ -1571,167 +1594,169 @@ var fbTestFixture = { } } }, - "range": [ - 11, - 21 - ], - "loc": { - "start": { - "line": 1, - "column": 11 - }, - "end": { - "line": 1, - "column": 21 - } - } - }, - { - "type": "XJSAttribute", - "name": { - "type": "XJSIdentifier", - "name": "right", - "range": [ - 22, - 27 - ], - "loc": { - "start": { - "line": 1, - "column": 22 - }, - "end": { - "line": 1, - "column": 27 + { + "type": "XJSAttribute", + "name": { + "type": "XJSIdentifier", + "name": "right", + "range": [ + 22, + 27 + ], + "loc": { + "start": { + "line": 1, + "column": 22 + }, + "end": { + "line": 1, + "column": 27 + } } - } - }, - "value": { - "type": "XJSElement", - "openingElement": { - "type": "XJSOpeningElement", - "name": { - "type": "XJSIdentifier", - "name": "b", + }, + "value": { + "type": "XJSElement", + "openingElement": { + "type": "XJSOpeningElement", + "name": { + "type": "XJSIdentifier", + "name": "b", + "range": [ + 29, + 30 + ], + "loc": { + "start": { + "line": 1, + "column": 29 + }, + "end": { + "line": 1, + "column": 30 + } + } + }, + "selfClosing": false, + "attributes": [], "range": [ - 29, - 30 + 28, + 31 ], "loc": { "start": { "line": 1, - "column": 29 + "column": 28 }, "end": { "line": 1, - "column": 30 + "column": 31 } } }, - "selfClosing": false, - "attributes": [], + "closingElement": { + "type": "XJSClosingElement", + "name": { + "type": "XJSIdentifier", + "name": "b", + "range": [ + 52, + 53 + ], + "loc": { + "start": { + "line": 1, + "column": 52 + }, + "end": { + "line": 1, + "column": 53 + } + } + }, + "range": [ + 50, + 54 + ], + "loc": { + "start": { + "line": 1, + "column": 50 + }, + "end": { + "line": 1, + "column": 54 + } + } + }, + "children": [ + { + "type": "Literal", + "value": "monkeys /> gorillas", + "raw": "monkeys /> gorillas", + "range": [ + 31, + 50 + ], + "loc": { + "start": { + "line": 1, + "column": 31 + }, + "end": { + "line": 1, + "column": 50 + } + } + } + ], "range": [ 28, - 31 + 54 ], "loc": { "start": { "line": 1, "column": 28 }, - "end": { - "line": 1, - "column": 31 - } - } - }, - "closingElement": { - "type": "XJSClosingElement", - "name": { - "type": "XJSIdentifier", - "name": "b", - "range": [ - 52, - 53 - ], - "loc": { - "start": { - "line": 1, - "column": 52 - }, - "end": { - "line": 1, - "column": 53 - } - } - }, - "range": [ - 50, - 54 - ], - "loc": { - "start": { - "line": 1, - "column": 50 - }, "end": { "line": 1, "column": 54 } } }, - "children": [ - { - "type": "Literal", - "value": "monkeys /> gorillas", - "raw": "monkeys /> gorillas", - "range": [ - 31, - 50 - ], - "loc": { - "start": { - "line": 1, - "column": 31 - }, - "end": { - "line": 1, - "column": 50 - } - } - } - ], "range": [ - 28, + 22, 54 ], "loc": { "start": { "line": 1, - "column": 28 + "column": 22 }, "end": { "line": 1, "column": 54 } } + } + ], + "range": [ + 0, + 57 + ], + "loc": { + "start": { + "line": 1, + "column": 0 }, - "range": [ - 22, - 54 - ], - "loc": { - "start": { - "line": 1, - "column": 22 - }, - "end": { - "line": 1, - "column": 54 - } + "end": { + "line": 1, + "column": 57 } } - ], + }, + closingElement: null, + "children": [], "range": [ 0, 57 @@ -1747,7 +1772,6 @@ var fbTestFixture = { } } }, - "children": [], "range": [ 0, 57 @@ -1763,119 +1787,14 @@ var fbTestFixture = { } } }, - "range": [ - 0, - 57 - ], - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 57 - } - } - }, - '': { - type: 'ExpressionStatement', - expression: { - type: 'XJSElement', - openingElement: { - type: 'XJSOpeningElement', - name: { - type: 'XJSMemberExpression', - object: { - type: 'XJSIdentifier', - name: 'a', - range: [1, 2], - loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 2 } - } - }, - property: { - type: 'XJSIdentifier', - name: 'b', - range: [3, 4], - loc: { - start: { line: 1, column: 3 }, - end: { line: 1, column: 4 } - } - }, - range: [1, 4], - loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 4 } - } - }, - selfClosing: false, - attributes: [], - range: [0, 5], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 5 } - } - }, - closingElement: { - type: 'XJSClosingElement', - name: { - type: 'XJSMemberExpression', - object: { - type: 'XJSIdentifier', - name: 'a', - range: [7, 8], - loc: { - start: { line: 1, column: 7 }, - end: { line: 1, column: 8 } - } - }, - property: { - type: 'XJSIdentifier', - name: 'b', - range: [9, 10], - loc: { - start: { line: 1, column: 9 }, - end: { line: 1, column: 10 } - } - }, - range: [7, 10], - loc: { - start: { line: 1, column: 7 }, - end: { line: 1, column: 10 } - } - }, - range: [5, 11], - loc: { - start: { line: 1, column: 5 }, - end: { line: 1, column: 11 } - } - }, - children: [], - range: [0, 11], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 11 } - } - }, - range: [0, 11], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 11 } - } - }, - - '': { - type: 'ExpressionStatement', - expression: { - type: 'XJSElement', - openingElement: { - type: 'XJSOpeningElement', - name: { - type: 'XJSMemberExpression', - object: { + '': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { type: 'XJSMemberExpression', object: { type: 'XJSIdentifier', @@ -1901,156 +1820,782 @@ var fbTestFixture = { end: { line: 1, column: 4 } } }, - property: { - type: 'XJSIdentifier', - name: 'c', - range: [5, 6], - loc: { - start: { line: 1, column: 5 }, - end: { line: 1, column: 6 } - } - }, - range: [1, 6], + selfClosing: false, + attributes: [], + range: [0, 5], loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 6 } + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } } }, - selfClosing: false, - attributes: [], - range: [0, 7], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 7 } - } - }, - closingElement: { - type: 'XJSClosingElement', - name: { - type: 'XJSMemberExpression', - object: { + closingElement: { + type: 'XJSClosingElement', + name: { type: 'XJSMemberExpression', object: { type: 'XJSIdentifier', name: 'a', + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + property: { + type: 'XJSIdentifier', + name: 'b', range: [9, 10], loc: { start: { line: 1, column: 9 }, end: { line: 1, column: 10 } } }, + range: [7, 10], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 10 } + } + }, + range: [5, 11], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 11 } + } + }, + children: [], + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + + '': { + type: 'ExpressionStatement', + expression: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSMemberExpression', + object: { + type: 'XJSMemberExpression', + object: { + type: 'XJSIdentifier', + name: 'a', + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + property: { + type: 'XJSIdentifier', + name: 'b', + range: [3, 4], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + range: [1, 4], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 4 } + } + }, property: { type: 'XJSIdentifier', - name: 'b', - range: [11, 12], + name: 'c', + range: [5, 6], loc: { - start: { line: 1, column: 11 }, + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [1, 6], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 6 } + } + }, + selfClosing: false, + attributes: [], + range: [0, 7], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + closingElement: { + type: 'XJSClosingElement', + name: { + type: 'XJSMemberExpression', + object: { + type: 'XJSMemberExpression', + object: { + type: 'XJSIdentifier', + name: 'a', + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + property: { + type: 'XJSIdentifier', + name: 'b', + range: [11, 12], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, end: { line: 1, column: 12 } } }, - range: [9, 12], + property: { + type: 'XJSIdentifier', + name: 'c', + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }, + range: [9, 14], loc: { start: { line: 1, column: 9 }, - end: { line: 1, column: 12 } - } - }, - property: { - type: 'XJSIdentifier', - name: 'c', - range: [13, 14], - loc: { - start: { line: 1, column: 13 }, end: { line: 1, column: 14 } } }, - range: [9, 14], + range: [7, 15], loc: { - start: { line: 1, column: 9 }, - end: { line: 1, column: 14 } + start: { line: 1, column: 7 }, + end: { line: 1, column: 15 } } }, - range: [7, 15], + children: [], + range: [0, 15], loc: { - start: { line: 1, column: 7 }, + start: { line: 1, column: 0 }, end: { line: 1, column: 15 } } }, - children: [], range: [0, 15], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 15 } } }, - range: [0, 15], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 15 } - } - }, - // In order to more useful parse errors, we disallow following an - // XJSElement by a less-than symbol. In the rare case that the binary - // operator was intended, the tag can be wrapped in parentheses: - '(
    ) < x;': { - type: 'ExpressionStatement', - expression: { - type: 'BinaryExpression', - operator: '<', - left: { - type: 'XJSElement', - openingElement: { - type: 'XJSOpeningElement', - name: { - type: 'XJSIdentifier', - name: 'div', - range: [2, 5], + // In order to more useful parse errors, we disallow following an + // XJSElement by a less-than symbol. In the rare case that the binary + // operator was intended, the tag can be wrapped in parentheses: + '(
    ) < x;': { + type: 'ExpressionStatement', + expression: { + type: 'BinaryExpression', + operator: '<', + left: { + type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', + name: { + type: 'XJSIdentifier', + name: 'div', + range: [2, 5], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 5 } + } + }, + selfClosing: true, + attributes: [], + range: [1, 8], loc: { - start: { line: 1, column: 2 }, - end: { line: 1, column: 5 } + start: { line: 1, column: 1 }, + end: { line: 1, column: 8 } } }, - selfClosing: true, - attributes: [], - range: [1, 8], + closingElement: null, + children: [], + range: [0, 9], loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 8 } + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } } }, - children: [], - range: [0, 9], + right: { + type: 'Identifier', + name: 'x', + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + range: [0, 13], loc: { start: { line: 1, column: 0 }, - end: { line: 1, column: 9 } - } - }, - right: { - type: 'Identifier', - name: 'x', - range: [12, 13], - loc: { - start: { line: 1, column: 12 }, end: { line: 1, column: 13 } } }, - range: [0, 13], + range: [0, 14], loc: { start: { line: 1, column: 0 }, - end: { line: 1, column: 13 } + end: { line: 1, column: 14 } } }, - range: [0, 14], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 14 } + + '
    ': { + "type": "ExpressionStatement", + "expression": { + "type": "XJSElement", + "openingElement": { + "type": "XJSOpeningElement", + "name": { + "type": "XJSIdentifier", + "name": "div", + "range": [ + 1, + 4 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 4 + } + } + }, + "selfClosing": true, + "attributes": [ + { + "type": "XJSSpreadAttribute", + "argument": { + "type": "Identifier", + "name": "props", + "range": [ + 9, + 14 + ], + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 14 + } + } + }, + "range": [ + 5, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 15 + } + } + } + ], + "range": [ + 0, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + closingElement: null, + "children": [], + "range": [ + 0, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + "range": [ + 0, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + + '
    ': { + "type": "ExpressionStatement", + "expression": { + "type": "XJSElement", + "openingElement": { + "type": "XJSOpeningElement", + "name": { + "type": "XJSIdentifier", + "name": "div", + "range": [ + 1, + 4 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 4 + } + } + }, + "selfClosing": true, + "attributes": [ + { + "type": "XJSSpreadAttribute", + "argument": { + "type": "Identifier", + "name": "props", + "range": [ + 9, + 14 + ], + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 14 + } + } + }, + "range": [ + 5, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 15 + } + } + }, + { + "type": "XJSAttribute", + "name": { + "type": "XJSIdentifier", + "name": "post", + "range": [ + 16, + 20 + ], + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 20 + } + } + }, + "value": { + "type": "Literal", + "value": "attribute", + "raw": "\"attribute\"", + "range": [ + 21, + 32 + ], + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 32 + } + } + }, + "range": [ + 16, + 32 + ], + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 1, + "column": 32 + } + } + } + ], + "range": [ + 0, + 35 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 35 + } + } + }, + closingElement: null, + "children": [], + "range": [ + 0, + 35 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 35 + } + } + }, + "range": [ + 0, + 35 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 35 + } + } + }, + + '
    ': { + "type": "ExpressionStatement", + "expression": { + "type": "XJSElement", + "openingElement": { + "type": "XJSOpeningElement", + "name": { + "type": "XJSIdentifier", + "name": "div", + "range": [ + 1, + 4 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 4 + } + } + }, + "selfClosing": false, + "attributes": [ + { + "type": "XJSAttribute", + "name": { + "type": "XJSIdentifier", + "name": "pre", + "range": [ + 5, + 8 + ], + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 8 + } + } + }, + "value": { + "type": "Literal", + "value": "leading", + "raw": "\"leading\"", + "range": [ + 9, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + "range": [ + 5, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + { + "type": "XJSAttribute", + "name": { + "type": "XJSIdentifier", + "name": "pre2", + "range": [ + 19, + 23 + ], + "loc": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 23 + } + } + }, + "value": { + "type": "Literal", + "value": "attribute", + "raw": "\"attribute\"", + "range": [ + 24, + 35 + ], + "loc": { + "start": { + "line": 1, + "column": 24 + }, + "end": { + "line": 1, + "column": 35 + } + } + }, + "range": [ + 19, + 35 + ], + "loc": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 35 + } + } + }, + { + "type": "XJSSpreadAttribute", + "argument": { + "type": "Identifier", + "name": "props", + "range": [ + 40, + 45 + ], + "loc": { + "start": { + "line": 1, + "column": 40 + }, + "end": { + "line": 1, + "column": 45 + } + } + }, + "range": [ + 36, + 46 + ], + "loc": { + "start": { + "line": 1, + "column": 36 + }, + "end": { + "line": 1, + "column": 46 + } + } + } + ], + "range": [ + 0, + 47 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 47 + } + } + }, + "closingElement": { + "type": "XJSClosingElement", + "name": { + "type": "XJSIdentifier", + "name": "div", + "range": [ + 49, + 52 + ], + "loc": { + "start": { + "line": 1, + "column": 49 + }, + "end": { + "line": 1, + "column": 52 + } + } + }, + "range": [ + 47, + 53 + ], + "loc": { + "start": { + "line": 1, + "column": 47 + }, + "end": { + "line": 1, + "column": 53 + } + } + }, + "children": [], + "range": [ + 0, + 53 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 53 + } + } + }, + "range": [ + 0, + 53 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 53 + } + } } } }; -for (var code in fbTestFixture) { +if (typeof exports !== "undefined") { + var test = require("./driver.js").test; +} + +for (var code in fbTestFixture.XJS) { test(code, { type: 'Program', - body: [fbTestFixture[code]] - }, {locations: true, ranges: true}); + body: [fbTestFixture.XJS[code]] + }, { + ecmaVersion: 6, + locations: true, + ranges: true + }); } \ No newline at end of file diff --git a/test/tests.js b/test/tests.js index 5f058bd42e..2259f75e59 100644 --- a/test/tests.js +++ b/test/tests.js @@ -6,7 +6,6 @@ if (typeof exports != "undefined") { var testFail = require("./driver.js").testFail; var testAssert = require("./driver.js").testAssert; var acorn = require(".."); - require("./tests-jsx.js"); } test("this\n", { From 2fbf640e6089f717ed9816370e0194c507c426a6 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sun, 27 Jul 2014 02:56:41 +0300 Subject: [PATCH 018/198] Update README.md --- README.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 323e2d2d95..1240d37b82 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,28 @@ -# Acorn (JSX edition) +# Acorn-JSX [![Build Status](https://travis-ci.org/RReverser/acorn.svg?branch=master)](https://travis-ci.org/RReverser/acorn) This is modification of [Acorn][acorn] - a tiny, fast JavaScript parser, written completely in JavaScript. -It was forked to create experimental, alternative, faster [React.js JSX][jsx] parser by integrating pieces +It was forked to create experimental alternative, faster [React.js JSX][jsx] parser by integrating pieces of code from official parser, modified to match Acorn's parsing logic. -According to [benchmarks](http://marijnhaverbeke.nl/acorn/test/bench.html), Acorn is 5x faster than Esprima -when parsing code with location tracking (call it "source maps enabled mode"), and JSX extensions almost don't -affect those numbers. However, [esprima-fb](https://github.com/facebook/esprima) is forked&maintained from -harmony branch of esprima which is being heavily optimized and currently `acorn-jsx` is only 1.5-2x faster than -`esprima-fb`. +According to [benchmarks](test/bench.html), Acorn-JSX is 2x faster than official [Esprima-based parser][esprima-fb] +when location tracking is turned on in both (call it "source maps enabled mode"). +At the same time, it consumes all the ES6+JSX syntax that can be consumed by Esprima-FB +(this is proved by [official tests](test/tests-jsx.js)). -Currently, it consumes all the ES5+JSX syntax that can be consumed by official [Esprima-based parser][esprima-fb]. -However, official parser can consume ES6 syntax as well, and is maintained by authors of React.js itself, so it's -preferred to be used in real projects. +However, Esprima-FB is maintained by authors of React.js itself, +so it's recommended to be used in production code. [acorn]: http://marijnhaverbeke.nl/acorn/ [esprima-fb]: https://github.com/facebook/esprima [jsx]: http://facebook.github.io/react/docs/jsx-in-depth.html +## Transpiler + +Please note that this tool only parses source code to JSX AST. If you want to convert result to JS AST or directly to JS code and source map, check out [jsx-transpiler](https://github.com/RReverser/jsx-transpiler). + ## Installation The easiest way to install acorn is with [`npm`][npm]. From 5c89414c5ab4b8afe7ba5881187d329f0b62b3fc Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 5 Sep 2014 17:23:03 +0300 Subject: [PATCH 019/198] Final polishing after rebase. --- acorn.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/acorn.js b/acorn.js index 195748c920..485ce2681c 100644 --- a/acorn.js +++ b/acorn.js @@ -883,7 +883,7 @@ 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; @@ -1332,7 +1332,8 @@ 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; } @@ -1421,7 +1422,7 @@ 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); @@ -1597,14 +1598,6 @@ eat(type) || unexpected(); } - // 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. function nextChar() { From fe805f396ee3691836a50f8add9badac5e6ba084 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Mon, 8 Sep 2014 23:58:44 +0300 Subject: [PATCH 020/198] Update version. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2261fd0c60..7a4f689aa6 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-jsx", "description": "Alternative React JSX parser", "main": "acorn.js", - "version": "0.7.1-1", + "version": "0.7.1-2", "maintainers": [ { "name": "Marijn Haverbeke", From 533d1d62ecb0c8c7d983a6f588d86bf54f0ba5ac Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 9 Sep 2014 00:06:06 +0300 Subject: [PATCH 021/198] Updated docs. --- docs/acorn.html | 1262 ++++++++++++++++++++++++++--------------------- 1 file changed, 703 insertions(+), 559 deletions(-) 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>;
    
    From ae9fae6c761b6981d9e8021649fa7c6a70a2f72c Mon Sep 17 00:00:00 2001
    From: Arthur Stolyar 
    Date: Tue, 9 Sep 2014 01:06:52 +0300
    Subject: [PATCH 022/198] Fix in child XJS MemberExpression
    
    ---
     acorn.js | 6 +++++-
     1 file changed, 5 insertions(+), 1 deletion(-)
    
    diff --git a/acorn.js b/acorn.js
    index 0dc99c7a24..940367dd72 100644
    --- a/acorn.js
    +++ b/acorn.js
    @@ -3054,13 +3054,17 @@
       function parseXJSExpressionContainer() {
         var node = startNode();
     
    -    var origInXJSTag = inXJSTag;
    +    var origInXJSTag = inXJSTag,
    +      origInXJSChild = inXJSChild;
    +
         inXJSTag = false;
    +    inXJSChild = false;
     
         next();
         node.expression = tokType === _braceR ? parseXJSEmptyExpression() : parseExpression();
     
         inXJSTag = origInXJSTag;
    +    inXJSChild = origInXJSChild;
         
         expect(_braceR);
         return finishNode(node, "XJSExpressionContainer");
    
    From d3cece14fd9d13734c19943815d56e62534ede21 Mon Sep 17 00:00:00 2001
    From: Arthur Stolyar 
    Date: Tue, 9 Sep 2014 01:56:30 +0300
    Subject: [PATCH 023/198] Fix spaceSkip after inXJSChildExpression
    
    ---
     acorn.js | 10 +++++++---
     1 file changed, 7 insertions(+), 3 deletions(-)
    
    diff --git a/acorn.js b/acorn.js
    index 940367dd72..e308b040a6 100644
    --- a/acorn.js
    +++ b/acorn.js
    @@ -273,7 +273,8 @@
       // that `break` and `continue` have somewhere to jump to, and
       // `strict` indicates whether strict mode is on.
     
    -  var inFunction, inGenerator, labels, strict, inXJSChild, inXJSTag;
    +  var inFunction, inGenerator, labels, strict,
    +    inXJSChild, inXJSTag, inXJSChildExpression;
     
       // This counter is used for checking that arrow expressions did
       // not contain nested parentheses in argument list.
    @@ -580,7 +581,8 @@
         tokEnd = tokPos;
         if (options.locations) tokEndLoc = new Position;
         tokType = type;
    -    if (shouldSkipSpace !== false && !(inXJSTag && type === _gt) && !(inXJSChild && tokType !== _braceL)) {
    +    if (shouldSkipSpace !== false && !(inXJSTag && type === _gt) &&
    +      !((inXJSChild && tokType !== _braceL) || (inXJSChildExpression && tokType === _braceR))) {
           skipSpace();
         }
         tokVal = val;
    @@ -3059,12 +3061,14 @@
     
         inXJSTag = false;
         inXJSChild = false;
    +    inXJSChildExpression = origInXJSChild;
     
         next();
         node.expression = tokType === _braceR ? parseXJSEmptyExpression() : parseExpression();
     
         inXJSTag = origInXJSTag;
         inXJSChild = origInXJSChild;
    +    inXJSChildExpression = false;
         
         expect(_braceR);
         return finishNode(node, "XJSExpressionContainer");
    @@ -3227,4 +3231,4 @@
         return finishNode(node, "XJSElement");
       }
     
    -});
    +});
    \ No newline at end of file
    
    From 78a6caf67393077ca63e66fa1972d02c7a61c242 Mon Sep 17 00:00:00 2001
    From: Arthur Stolyar 
    Date: Tue, 9 Sep 2014 02:12:39 +0300
    Subject: [PATCH 024/198] Add test for inXJSChild MemberExpression
    
    ---
     test/tests-jsx.js | 617 ++++++++++++++++++++++++++++++++++++++++++++++
     1 file changed, 617 insertions(+)
    
    diff --git a/test/tests-jsx.js b/test/tests-jsx.js
    index 940b855df8..6563c1a455 100644
    --- a/test/tests-jsx.js
    +++ b/test/tests-jsx.js
    @@ -2581,6 +2581,623 @@ var fbTestFixture = {
               "column": 53
             }
           }
    +    },
    +    '
    {aa.b}
    ': { + "type": "ExpressionStatement", + "start": 0, + "end": 52, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 52 + } + }, + "range": [ + 0, + 52 + ], + "expression": { + "type": "XJSElement", + "start": 0, + "end": 52, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 52 + } + }, + "range": [ + 0, + 52 + ], + "openingElement": { + "type": "XJSOpeningElement", + "start": 0, + "end": 31, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 31 + } + }, + "range": [ + 0, + 31 + ], + "attributes": [ + { + "type": "XJSAttribute", + "start": 3, + "end": 16, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 16 + } + }, + "range": [ + 3, + 16 + ], + "name": { + "type": "XJSIdentifier", + "start": 3, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 5 + } + }, + "range": [ + 3, + 5 + ], + "name": "aa" + }, + "value": { + "type": "XJSExpressionContainer", + "start": 6, + "end": 16, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 16 + } + }, + "range": [ + 6, + 16 + ], + "expression": { + "type": "MemberExpression", + "start": 7, + "end": 15, + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 15 + } + }, + "range": [ + 7, + 15 + ], + "object": { + "type": "MemberExpression", + "start": 7, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "range": [ + 7, + 12 + ], + "object": { + "type": "Identifier", + "start": 7, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "range": [ + 7, + 9 + ], + "name": "aa" + }, + "property": { + "type": "Identifier", + "start": 10, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "range": [ + 10, + 12 + ], + "name": "bb" + }, + "computed": false + }, + "property": { + "type": "Identifier", + "start": 13, + "end": 15, + "loc": { + "start": { + "line": 1, + "column": 13 + }, + "end": { + "line": 1, + "column": 15 + } + }, + "range": [ + 13, + 15 + ], + "name": "cc" + }, + "computed": false + } + } + }, + { + "type": "XJSAttribute", + "start": 17, + "end": 30, + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 30 + } + }, + "range": [ + 17, + 30 + ], + "name": { + "type": "XJSIdentifier", + "start": 17, + "end": 19, + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 19 + } + }, + "range": [ + 17, + 19 + ], + "name": "bb" + }, + "value": { + "type": "XJSExpressionContainer", + "start": 20, + "end": 30, + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 30 + } + }, + "range": [ + 20, + 30 + ], + "expression": { + "type": "MemberExpression", + "start": 21, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 29 + } + }, + "range": [ + 21, + 29 + ], + "object": { + "type": "MemberExpression", + "start": 21, + "end": 26, + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 26 + } + }, + "range": [ + 21, + 26 + ], + "object": { + "type": "Identifier", + "start": 21, + "end": 23, + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 23 + } + }, + "range": [ + 21, + 23 + ], + "name": "bb" + }, + "property": { + "type": "Identifier", + "start": 24, + "end": 26, + "loc": { + "start": { + "line": 1, + "column": 24 + }, + "end": { + "line": 1, + "column": 26 + } + }, + "range": [ + 24, + 26 + ], + "name": "cc" + }, + "computed": false + }, + "property": { + "type": "Identifier", + "start": 27, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 27 + }, + "end": { + "line": 1, + "column": 29 + } + }, + "range": [ + 27, + 29 + ], + "name": "dd" + }, + "computed": false + } + } + } + ], + "name": { + "type": "XJSIdentifier", + "start": 1, + "end": 2, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 2 + } + }, + "range": [ + 1, + 2 + ], + "name": "A" + }, + "selfClosing": false + }, + "closingElement": { + "type": "XJSClosingElement", + "start": 48, + "end": 52, + "loc": { + "start": { + "line": 1, + "column": 48 + }, + "end": { + "line": 1, + "column": 52 + } + }, + "range": [ + 48, + 52 + ], + "name": { + "type": "XJSIdentifier", + "start": 50, + "end": 51, + "loc": { + "start": { + "line": 1, + "column": 50 + }, + "end": { + "line": 1, + "column": 51 + } + }, + "range": [ + 50, + 51 + ], + "name": "A" + } + }, + "children": [ + { + "type": "XJSElement", + "start": 31, + "end": 48, + "loc": { + "start": { + "line": 1, + "column": 31 + }, + "end": { + "line": 1, + "column": 48 + } + }, + "range": [ + 31, + 48 + ], + "openingElement": { + "type": "XJSOpeningElement", + "start": 31, + "end": 36, + "loc": { + "start": { + "line": 1, + "column": 31 + }, + "end": { + "line": 1, + "column": 36 + } + }, + "range": [ + 31, + 36 + ], + "attributes": [], + "name": { + "type": "XJSIdentifier", + "start": 32, + "end": 35, + "loc": { + "start": { + "line": 1, + "column": 32 + }, + "end": { + "line": 1, + "column": 35 + } + }, + "range": [ + 32, + 35 + ], + "name": "div" + }, + "selfClosing": false + }, + "closingElement": { + "type": "XJSClosingElement", + "start": 42, + "end": 48, + "loc": { + "start": { + "line": 1, + "column": 42 + }, + "end": { + "line": 1, + "column": 48 + } + }, + "range": [ + 42, + 48 + ], + "name": { + "type": "XJSIdentifier", + "start": 44, + "end": 47, + "loc": { + "start": { + "line": 1, + "column": 44 + }, + "end": { + "line": 1, + "column": 47 + } + }, + "range": [ + 44, + 47 + ], + "name": "div" + } + }, + "children": [ + { + "type": "XJSExpressionContainer", + "start": 36, + "end": 42, + "loc": { + "start": { + "line": 1, + "column": 36 + }, + "end": { + "line": 1, + "column": 42 + } + }, + "range": [ + 36, + 42 + ], + "expression": { + "type": "MemberExpression", + "start": 37, + "end": 41, + "loc": { + "start": { + "line": 1, + "column": 37 + }, + "end": { + "line": 1, + "column": 41 + } + }, + "range": [ + 37, + 41 + ], + "object": { + "type": "Identifier", + "start": 37, + "end": 39, + "loc": { + "start": { + "line": 1, + "column": 37 + }, + "end": { + "line": 1, + "column": 39 + } + }, + "range": [ + 37, + 39 + ], + "name": "aa" + }, + "property": { + "type": "Identifier", + "start": 40, + "end": 41, + "loc": { + "start": { + "line": 1, + "column": 40 + }, + "end": { + "line": 1, + "column": 41 + } + }, + "range": [ + 40, + 41 + ], + "name": "b" + }, + "computed": false + } + } + ] + } + ] + } } } }; From 9c17926e3f28dfa3369bb96683d30c81c3b57095 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 17 Sep 2014 20:54:41 +0300 Subject: [PATCH 025/198] Version update. Simplified shouldSkipSpace condition, fixed indentation. --- acorn.js | 13 ++++++------- package.json | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/acorn.js b/acorn.js index e308b040a6..3cbdab358a 100644 --- a/acorn.js +++ b/acorn.js @@ -581,15 +581,14 @@ tokEnd = tokPos; if (options.locations) tokEndLoc = new Position; tokType = type; - if (shouldSkipSpace !== false && !(inXJSTag && type === _gt) && - !((inXJSChild && tokType !== _braceL) || (inXJSChildExpression && tokType === _braceR))) { + if (shouldSkipSpace !== false && !(inXJSChild && tokType !== _braceL)) { skipSpace(); } tokVal = val; tokRegexpAllowed = type.beforeExpr; if (options.onToken) { options.onToken(new Token()); - } + } } function skipBlockComment() { @@ -757,7 +756,7 @@ size = 2; return finishOp(_ltSlash, size); } - return finishOp(code === 60 ? _lt : _gt, size); + return code === 60 ? finishOp(_lt, size) : finishOp(_gt, size, !inXJSTag); } function readToken_eq_excl(code) { // '=!', '=>' @@ -810,7 +809,7 @@ case 91: ++tokPos; return finishToken(_bracketL); case 93: ++tokPos; return finishToken(_bracketR); case 123: ++tokPos; return finishToken(_braceL); - case 125: ++tokPos; return finishToken(_braceR); + case 125: ++tokPos; return finishToken(_braceR, undefined, !inXJSChildExpression); case 58: ++tokPos; return finishToken(_colon); case 63: ++tokPos; return finishToken(_question); @@ -902,10 +901,10 @@ return tok; } - function finishOp(type, size) { + function finishOp(type, size, shouldSkipSpace) { var str = input.slice(tokPos, tokPos + size); tokPos += size; - finishToken(type, str); + finishToken(type, str, shouldSkipSpace); } // Parse a regular expression. Some context-awareness is necessary, diff --git a/package.json b/package.json index 7a4f689aa6..96f211a2f6 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-jsx", "description": "Alternative React JSX parser", "main": "acorn.js", - "version": "0.7.1-2", + "version": "0.7.1-3", "maintainers": [ { "name": "Marijn Haverbeke", From 96024e695042af4efeb08c5cf63a92bcae55edf0 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 17 Sep 2014 20:55:59 +0300 Subject: [PATCH 026/198] Updated docs. --- docs/acorn.html | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/docs/acorn.html b/docs/acorn.html index 16abf53e11..7ccb172c64 100644 --- a/docs/acorn.html +++ b/docs/acorn.html @@ -615,7 +615,8 @@ that break and continue have somewhere to jump to, and
    -  var inFunction, inGenerator, labels, strict, inXJSChild, inXJSTag;
    + var inFunction, inGenerator, labels, strict, + inXJSChild, inXJSTag, inXJSChildExpression;
  • @@ -1343,14 +1344,14 @@ the next one’s tokStart will point at the right position.

    tokEnd = tokPos; if (options.locations) tokEndLoc = new Position; tokType = type; - if (shouldSkipSpace !== false && !(inXJSTag && type === _gt) && !(inXJSChild && tokType !== _braceL)) { + if (shouldSkipSpace !== false && !(inXJSChild && tokType !== _braceL)) { skipSpace(); } tokVal = val; tokRegexpAllowed = type.beforeExpr; if (options.onToken) { options.onToken(new Token()); - } + } } function skipBlockComment() { @@ -1590,7 +1591,7 @@ into it.

          size = 2;
           return finishOp(_ltSlash, size);
         }
    -    return finishOp(code === 60 ? _lt : _gt, size);
    +    return code === 60 ? finishOp(_lt, size) : finishOp(_gt, size, !inXJSTag);
       }
     
       function readToken_eq_excl(code) { // '=!', '=>'
    @@ -1705,7 +1706,7 @@ by a digit or another two dots.

    case 91: ++tokPos; return finishToken(_bracketL); case 93: ++tokPos; return finishToken(_bracketR); case 123: ++tokPos; return finishToken(_braceL); - case 125: ++tokPos; return finishToken(_braceR); + case 125: ++tokPos; return finishToken(_braceR, undefined, !inXJSChildExpression); case 58: ++tokPos; return finishToken(_colon); case 63: ++tokPos; return finishToken(_question); @@ -1871,10 +1872,10 @@ character, or something that’s entirely disallowed.

    return tok; } - function finishOp(type, size) { + function finishOp(type, size, shouldSkipSpace) { var str = input.slice(tokPos, tokPos + size); tokPos += size; - finishToken(type, str); + finishToken(type, str, shouldSkipSpace); }
    @@ -5233,13 +5234,19 @@ at the beginning of the next one (right brace).

    function parseXJSExpressionContainer() { var node = startNode(); - var origInXJSTag = inXJSTag; + var origInXJSTag = inXJSTag, + origInXJSChild = inXJSChild; + inXJSTag = false; + inXJSChild = false; + inXJSChildExpression = origInXJSChild; next(); node.expression = tokType === _braceR ? parseXJSEmptyExpression() : parseExpression(); inXJSTag = origInXJSTag; + inXJSChild = origInXJSChild; + inXJSChildExpression = false; expect(_braceR); return finishNode(node, "XJSExpressionContainer"); From 0258dafa8af64a5cfb879f8ca64782c8c89d00fd Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 19 Oct 2014 18:01:34 +1100 Subject: [PATCH 027/198] add unicode flag support to regex --- acorn.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index 2d740e8c50..ffedd8bd61 100644 --- a/acorn.js +++ b/acorn.js @@ -934,7 +934,11 @@ // Need to use `readWord1` because '\uXXXX' sequences are allowed // here (don't ask). var mods = readWord1(); - if (mods && !/^[gmsiy]*$/.test(mods)) raise(start, "Invalid regular expression flag"); + if (mods) { + var validFlags = /^[gmsiy]*$/; + if (options.ecmaVersion >= 6) validFlags = /^[gmsiyu]*$/; + if (!validFlags.test(mods)) raise(start, "Invalid regular expression flag"); + } try { var value = new RegExp(content, mods); } catch (e) { From 156fee8b4d79c9daf786200be2e847eb45d0385c Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 22 Oct 2014 14:09:05 +0300 Subject: [PATCH 028/198] Update version. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 96f211a2f6..31341d59e4 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-jsx", "description": "Alternative React JSX parser", "main": "acorn.js", - "version": "0.7.1-3", + "version": "0.9.1-1", "maintainers": [ { "name": "Marijn Haverbeke", From 397d87fd1106d7d10fa49f2058cc832c2be5bdf1 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 25 Oct 2014 09:02:24 +1100 Subject: [PATCH 029/198] add additional regex property to regex literals containing pattern and flags --- acorn.js | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/acorn.js b/acorn.js index ffedd8bd61..f3c3d9f5dd 100644 --- a/acorn.js +++ b/acorn.js @@ -934,18 +934,36 @@ // Need to use `readWord1` because '\uXXXX' sequences are allowed // here (don't ask). var mods = readWord1(); + var tmp = content; if (mods) { var validFlags = /^[gmsiy]*$/; if (options.ecmaVersion >= 6) validFlags = /^[gmsiyu]*$/; if (!validFlags.test(mods)) raise(start, "Invalid regular expression flag"); + if (mods.indexOf('u') >= 0) { + // Replace each astral symbol and every Unicode code point + // escape sequence that represents such a symbol with a single + // ASCII symbol to avoid throwing on regular expressions that + // are only valid in combination with the `/u` flag. + tmp = tmp + .replace(/\\u\{([0-9a-fA-F]{5,6})\}/g, 'x') + .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x'); + } } + // Detect invalid regular expressions. try { - var value = new RegExp(content, mods); + new RegExp(tmp); } catch (e) { if (e instanceof SyntaxError) raise(start, "Error parsing regular expression: " + e.message); raise(e); } - return finishToken(_regexp, value); + // Get a regular expression object for this pattern-flag pair, or `null` in + // case the current environment doesn't support the flags it uses. + try { + var value = new RegExp(content, mods); + } catch (err) { + value = null; + } + return finishToken(_regexp, {pattern: content, flags: mods, value: value}); } // Read an integer in the given radix. Return null if zero digits @@ -2010,7 +2028,15 @@ } return id; - case _num: case _string: case _regexp: + case _regexp: + var node = startNode(); + node.regex = {pattern: tokVal.pattern, flags: tokVal.flags}; + node.value = tokVal.value; + node.raw = input.slice(tokStart, tokEnd); + next(); + return finishNode(node, "Literal"); + + case _num: case _string: var node = startNode(); node.value = tokVal; node.raw = input.slice(tokStart, tokEnd); From 6eeb101185394ba705070f788105843b2c27f737 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 25 Oct 2014 09:02:34 +1100 Subject: [PATCH 030/198] add regex tests --- test/tests-harmony.js | 29 +++++++++++++++++++++++ test/tests.js | 54 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/test/tests-harmony.js b/test/tests-harmony.js index 1a883ee051..b92c1e911e 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -14792,6 +14792,35 @@ test("func(...a, b)", { locations: true }); +test("/[a-z]/u", { + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "Literal", + regex: { + pattern: "[a-z]", + flags: "u" + }, + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 8 + } + } + } + } + ] +}, { + locations: true, + ecmaVersion: 6 +}); + // Harmony Invalid syntax testFail("0o", "Expected number in radix 8 (1:2)", {ecmaVersion: 6}); diff --git a/test/tests.js b/test/tests.js index 4fedc72ca1..287d98f84d 100644 --- a/test/tests.js +++ b/test/tests.js @@ -135,6 +135,60 @@ test("\n 42\n\n", { } }); +test("/foobar/", { + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "Literal", + value: /foobar/, + regex: { + pattern: "foobar", + flags: "" + }, + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 8 + } + } + } + } + ] +}); + +test("/[a-z]/g", { + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "Literal", + value: /[a-z]/, + regex: { + pattern: "[a-z]", + flags: "g" + }, + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 8 + } + } + } + } + ] +}); + test("(1 + 2 ) * 3", { type: "Program", body: [ From 1be5b3c82331ae73623af1fa6b09da2e1d7c7a9e Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 29 Oct 2014 20:35:37 +1100 Subject: [PATCH 031/198] make ImportDeclaration and ExportDeclaration semicolons more spec-compliant --- acorn.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/acorn.js b/acorn.js index 8013c92685..401b9421c8 100644 --- a/acorn.js +++ b/acorn.js @@ -2482,8 +2482,8 @@ node.source = null; semicolon(); } else { - // export * from '...' - // export { x, y as z } [from '...'] + // export * from '...'; + // export { x, y as z } [from '...']; var isBatch = tokType === _star; node.declaration = null; node['default'] = false; @@ -2495,6 +2495,7 @@ if (isBatch) unexpected(); node.source = null; } + semicolon(); } return finishNode(node, "ExportDeclaration"); } @@ -2549,6 +2550,7 @@ // (it doesn't support mixed default + named yet) node.kind = node.specifiers[0]['default'] ? "default" : "named"; } + semicolon(); return finishNode(node, "ImportDeclaration"); } From 62670e74cb5b41fee5093eefe36ee251171682f0 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 1 Nov 2014 23:17:25 +1100 Subject: [PATCH 032/198] remove readme --- README.md | 312 +----------------------------------------------------- 1 file changed, 2 insertions(+), 310 deletions(-) diff --git a/README.md b/README.md index 75cc2e3951..f2ce71b5d1 100644 --- a/README.md +++ b/README.md @@ -1,311 +1,3 @@ -# Acorn-JSX +# acorn-6to5 -[![Build Status](https://travis-ci.org/RReverser/acorn.svg?branch=master)](https://travis-ci.org/RReverser/acorn) - -This is modification of [Acorn][acorn] - a tiny, fast JavaScript parser, written completely in JavaScript. - -It was forked to create experimental alternative, faster [React.js JSX][jsx] parser by integrating pieces -of code from official parser, modified to match Acorn's parsing logic. - -According to [benchmarks](test/bench.html), Acorn-JSX is 2x faster than official [Esprima-based parser][esprima-fb] -when location tracking is turned on in both (call it "source maps enabled mode"). -At the same time, it consumes all the ES6+JSX syntax that can be consumed by Esprima-FB -(this is proved by [official tests](test/tests-jsx.js)). - -However, Esprima-FB is maintained by authors of React.js itself, -so it's recommended to be used in production code. - -[acorn]: http://marijnhaverbeke.nl/acorn/ -[esprima-fb]: https://github.com/facebook/esprima -[jsx]: http://facebook.github.io/react/docs/jsx-in-depth.html - -## Transpiler - -Please note that this tool only parses source code to JSX AST. If you want to convert result to JS AST or directly to JS code and source map, check out [jsx-transpiler](https://github.com/RReverser/jsx-transpiler). - -## Installation - -The easiest way to install acorn is with [`npm`][npm]. - -[npm]: http://npmjs.org - -```sh -npm install acorn-jsx -``` - -Alternately, download the source. - -```sh -git clone https://github.com/RReverser/acorn-jsx.git -``` - -## Components - -When run in a CommonJS (node.js) or AMD environment, exported values -appear in the interfaces exposed by the individual files, as usual. -When loaded in the browser (Acorn works in any JS-enabled browser more -recent than IE5) without any kind of module management, a single -global object `acorn` will be defined, and all the exported properties -will be added to that. - -### acorn.js - -This file contains the actual parser (and is what you get when you -`require("acorn")` in node.js). - -**parse**`(input, options)` is used to parse a JavaScript program. -The `input` parameter is a string, `options` can be undefined or an -object setting some of the options listed below. The return value will -be an abstract syntax tree object as specified by the -[Mozilla Parser API][mozapi]. - -When encountering a syntax error, the parser will raise a -`SyntaxError` object with a meaningful message. The error object will -have a `pos` property that indicates the character offset at which the -error occurred, and a `loc` object that contains a `{line, column}` -object referring to that same position. - -[mozapi]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API - -- **ecmaVersion**: Indicates the ECMAScript version to parse. Must be - either 3, 5, or 6. This influences support for strict mode, the set - of reserved words, and support for new syntax features. Default is 5. - -- **strictSemicolons**: If `true`, prevents the parser from doing - automatic semicolon insertion, and statements that do not end with - a semicolon will generate an error. Defaults to `false`. - -- **allowTrailingCommas**: If `false`, the parser will not allow - trailing commas in array and object literals. Default is `true`. - -- **forbidReserved**: If `true`, using a reserved word will generate - an error. Defaults to `false`. When given the value `"everywhere"`, - reserved words and keywords can also not be used as property names - (as in Internet Explorer's old parser). - -- **allowReturnOutsideFunction**: By default, a return statement at - the top level raises an error. Set this to `true` to accept such - code. - -- **locations**: When `true`, each node has a `loc` object attached - with `start` and `end` subobjects, each of which contains the - one-based line and zero-based column numbers in `{line, column}` - form. Default is `false`. - -- **onToken**: If a function is passed for this option, each found - token will be passed in same format as `tokenize()` returns. - - If array is passed, each found token is pushed to it. - - Note that you are not allowed to call the parser from the - callback—that will corrupt its internal state. - -- **onComment**: If a function is passed for this option, whenever a - comment is encountered the function will be called with the - following parameters: - - - `block`: `true` if the comment is a block comment, false if it - is a line comment. - - `text`: The content of the comment. - - `start`: Character offset of the start of the comment. - - `end`: Character offset of the end of the comment. - - When the `locations` options is on, the `{line, column}` locations - of the comment’s start and end are passed as two additional - parameters. - - If array is passed for this option, each found comment is pushed - to it as object in Esprima format: - - ```javascript - { - "type": "Line" | "Block", - "value": "comment text", - "range": ..., - "loc": ... - } - ``` - - Note that you are not allowed to call the parser from the - callback—that will corrupt its internal state. - -- **ranges**: Nodes have their start and end characters offsets - recorded in `start` and `end` properties (directly on the node, - rather than the `loc` object, which holds line/column data. To also - add a [semi-standardized][range] "range" property holding a - `[start, end]` array with the same numbers, set the `ranges` option - to `true`. - -- **program**: It is possible to parse multiple files into a single - AST by passing the tree produced by parsing the first file as the - `program` option in subsequent parses. This will add the toplevel - forms of the parsed file to the "Program" (top) node of an existing - parse tree. - -- **sourceFile**: When the `locations` option is `true`, you can pass - this option to add a `source` attribute in every node’s `loc` - object. Note that the contents of this option are not examined or - processed in any way; you are free to use whatever format you - choose. - -- **directSourceFile**: Like `sourceFile`, but a `sourceFile` property - will be added directly to the nodes, rather than the `loc` object. - -- **preserveParens**: If this option is `true`, parenthesized expressions - are represented by (non-standard) `ParenthesizedExpression` nodes - that have a single `expression` property containing the expression - inside parentheses. - -[range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 - -**parseExpressionAt**`(input, offset, options)` will parse a single -expression in a string, and return its AST. It will not complain if -there is more of the string left after the expression. - -**getLineInfo**`(input, offset)` can be used to get a `{line, -column}` object for a given program string and character offset. - -**tokenize**`(input, options)` exports a primitive interface to -Acorn's tokenizer. The function takes an input string and options -similar to `parse` (though only some options are meaningful here), and -returns a function that can be called repeatedly to read a single -token, and returns a `{start, end, type, value}` object (with added -`loc` property when the `locations` option is enabled and `range` -property when the `ranges` option is enabled). - -**tokTypes** holds an object mapping names to the token type objects -that end up in the `type` properties of tokens. - -#### Note on using with [Escodegen][escodegen] - -Escodegen supports generating comments from AST, attached in -Esprima-specific format. In order to simulate same format in -Acorn, consider following example: - -```javascript -var comments = [], tokens = []; - -var ast = acorn.parse('var x = 42; // answer', { - // collect ranges for each node - ranges: true, - // collect comments in Esprima's format - onComment: comments, - // collect token ranges - onToken: tokens -}); - -// attach comments using collected information -escodegen.attachComments(ast, comments, tokens); - -// generate code -console.log(escodegen.generate(ast, {comment: true})); -// > 'var x = 42; // answer' -``` - -[escodegen]: https://github.com/Constellation/escodegen - -#### Using Acorn in an environment with a Content Security Policy - -Some contexts, such as Chrome Web Apps, disallow run-time code evaluation. -Acorn uses `new Function` to generate fast functions that test whether -a word is in a given set, and will trigger a security error when used -in a context with such a -[Content Security Policy](http://www.html5rocks.com/en/tutorials/security/content-security-policy/#eval-too) -(see [#90](https://github.com/marijnh/acorn/issues/90) and -[#123](https://github.com/marijnh/acorn/issues/123)). - -The `bin/without_eval` script can be used to generate a version of -`acorn.js` that has the generated code inlined, and can thus run -without evaluating anything. In versions of this library downloaded -from NPM, this script will be available as `acorn_csp.js`. - -### acorn_loose.js ### - -This file implements an error-tolerant parser. It exposes a single -function. - -**parse_dammit**`(input, options)` takes the same arguments and -returns the same syntax tree as the `parse` function in `acorn.js`, -but never raises an error, and will do its best to parse syntactically -invalid code in as meaningful a way as it can. It'll insert identifier -nodes with name `"✖"` as placeholders in places where it can't make -sense of the input. Depends on `acorn.js`, because it uses the same -tokenizer. The loose parser does not support ECMAScript 6 syntax yet. - -### util/walk.js ### - -Implements an abstract syntax tree walker. Will store its interface in -`acorn.walk` when used without a module system. - -**simple**`(node, visitors, base, state)` does a 'simple' walk over -a tree. `node` should be the AST node to walk, and `visitors` an -object with properties whose names correspond to node types in the -[Mozilla Parser API][mozapi]. The properties should contain functions -that will be called with the node object and, if applicable the state -at that point. The last two arguments are optional. `base` is a walker -algorithm, and `state` is a start state. The default walker will -simply visit all statements and expressions and not produce a -meaningful state. (An example of a use of state it to track scope at -each point in the tree.) - -**ancestor**`(node, visitors, base, state)` does a 'simple' walk over -a tree, building up an array of ancestor nodes (including the current node) -and passing the array to callbacks in the `state` parameter. - -**recursive**`(node, state, functions, base)` does a 'recursive' -walk, where the walker functions are responsible for continuing the -walk on the child nodes of their target node. `state` is the start -state, and `functions` should contain an object that maps node types -to walker functions. Such functions are called with `(node, state, c)` -arguments, and can cause the walk to continue on a sub-node by calling -the `c` argument on it with `(node, state)` arguments. The optional -`base` argument provides the fallback walker functions for node types -that aren't handled in the `functions` object. If not given, the -default walkers will be used. - -**make**`(functions, base)` builds a new walker object by using the -walker functions in `functions` and filling in the missing ones by -taking defaults from `base`. - -**findNodeAt**`(node, start, end, test, base, state)` tries to -locate a node in a tree at the given start and/or end offsets, which -satisfies the predicate `test`. `start` end `end` can be either `null` -(as wildcard) or a number. `test` may be a string (indicating a node -type) or a function that takes `(nodeType, node)` arguments and -returns a boolean indicating whether this node is interesting. `base` -and `state` are optional, and can be used to specify a custom walker. -Nodes are tested from inner to outer, so if two nodes match the -boundaries, the inner one will be preferred. - -**findNodeAround**`(node, pos, test, base, state)` is a lot like -`findNodeAt`, but will match any node that exists 'around' (spanning) -the given position. - -**findNodeAfter**`(node, pos, test, base, state)` is similar to -`findNodeAround`, but will match all nodes *after* the given position -(testing outer nodes before inner nodes). - -## Command line interface - -The `bin/acorn` utility can be used to parse a file from the command -line. It accepts as arguments its input file and the following -options: - -- `--ecma3|--ecma5|--ecma6`: Sets the ECMAScript version to parse. Default is - version 5. - -- `--strictSemicolons`: Prevents the parser from doing automatic - semicolon insertion. Statements that do not end in semicolons will - generate an error. - -- `--locations`: Attaches a "loc" object to each node with "start" and - "end" subobjects, each of which contains the one-based line and - zero-based column numbers in `{line, column}` form. - -- `--compact`: No whitespace is used in the AST output. - -- `--silent`: Do not output the AST, just return the exit status. - -- `--help`: Print the usage information and quit. - -The utility spits out the syntax tree as JSON data. +[![Build Status](https://travis-ci.org/sebmck/acorn-6to5.svg?branch=master)](https://travis-ci.org/sebmck/acorn-6to5) From d6771b1cef23b379b2182d89095a5bf56a20ac81 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 1 Nov 2014 23:17:32 +1100 Subject: [PATCH 033/198] update package.json --- package.json | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 31341d59e4..3c7951983a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "acorn-jsx", - "description": "Alternative React JSX parser", + "name": "acorn-6to5", + "description": "Acorn fork used by 6to5", "main": "acorn.js", "version": "0.9.1-1", "maintainers": [ @@ -13,15 +13,18 @@ "name": "Ingvar Stepanyan", "email": "me@rreverser.com", "web": "https://github.com/RReverser" + }, + { + "name": "Sebastian McKenzie", + "email": "sebmck@gmail.com.com", + "web": "http://sebmck.com" } ], - "repository": "RReverser/acorn-jsx", + "repository": "https://github.com/sebmck/acorn-6to5", "licenses": [{ "type": "MIT", "url": "http://marijnhaverbeke.nl/acorn/LICENSE" }], "scripts": {"test": "node test/run.js"}, - "bin": {"acorn-jsx": "./bin/acorn"}, - "devDependencies": {"regenerate": "~0.6.2", - "unicode-7.0.0": "~0.1.5"} + "devDependencies": {"regenerate": "~0.6.2", "unicode-7.0.0": "~0.1.5"} } From 21900ae2b063b4d8af1f88869a5c3434da1f4330 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 1 Nov 2014 23:18:01 +1100 Subject: [PATCH 034/198] add acorn-jsx shoutout to readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index f2ce71b5d1..7610b61981 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ # acorn-6to5 [![Build Status](https://travis-ci.org/sebmck/acorn-6to5.svg?branch=master)](https://travis-ci.org/sebmck/acorn-6to5) + +Based on [acorn-jsx](https://github.com/RReverser/acorn-jsx). From 16063dd8b357dca5ded7ec772ca53a10dbeee9ad Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 2 Nov 2014 14:18:40 +1100 Subject: [PATCH 035/198] add strictMode option --- acorn.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/acorn.js b/acorn.js index d17a29c418..f5e9d835e3 100644 --- a/acorn.js +++ b/acorn.js @@ -164,6 +164,9 @@ comments.push(comment); }; } + if (opts.strictMode) { + strict = true; + } isKeyword = options.ecmaVersion >= 6 ? isEcma6Keyword : isEcma5AndLessKeyword; } From 7f57741824abc1015b59093866912ee091e710b6 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Mon, 3 Nov 2014 22:39:26 +1100 Subject: [PATCH 036/198] fix options.strictMode reference --- acorn.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index f5e9d835e3..d6e7acb738 100644 --- a/acorn.js +++ b/acorn.js @@ -164,7 +164,7 @@ comments.push(comment); }; } - if (opts.strictMode) { + if (options.strictMode) { strict = true; } isKeyword = options.ecmaVersion >= 6 ? isEcma6Keyword : isEcma5AndLessKeyword; From 4f0c37eb68ee6388dcb4474ec24d0297b5e2af04 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Tue, 4 Nov 2014 11:40:49 +1100 Subject: [PATCH 037/198] Add support for computed static mutator class methods --- acorn.js | 2 +- test/tests-harmony.js | 153 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index 401b9421c8..d94aee2fc3 100644 --- a/acorn.js +++ b/acorn.js @@ -2402,7 +2402,7 @@ } var isGenerator = eat(_star); parsePropertyName(method); - if (tokType === _name && !method.computed && method.key.type === "Identifier" && + if (tokType !== _parenL && !method.computed && method.key.type === "Identifier" && (method.key.name === "get" || method.key.name === "set")) { if (isGenerator) unexpected(); method.kind = method.key.name; diff --git a/test/tests-harmony.js b/test/tests-harmony.js index 539418f870..2302f58f60 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -8304,6 +8304,159 @@ test("class A { static get foo() {} static set foo(v) {} get foo() {} set foo(v) locations: true }); + +test("class A { static [foo]() {} }", { + type: "Program", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 29} + }, + body: [{ + type: "ClassDeclaration", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 29} + }, + id: { + type: "Identifier", + loc: { + start: {line: 1, column: 6}, + end: {line: 1, column: 7} + }, + name: "A" + }, + superClass: null, + body: { + type: "ClassBody", + loc: { + start: {line: 1, column: 8}, + end: {line: 1, column: 29} + }, + body: [{ + type: "MethodDefinition", + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 27} + }, + static: true, + computed: true, + key: { + type: "Identifier", + loc: { + start: {line: 1, column: 18}, + end: {line: 1, column: 21} + }, + name: "foo" + }, + kind: "", + value: { + type: "FunctionExpression", + loc: { + start: {line: 1, column: 22}, + end: {line: 1, column: 27} + }, + id: null, + params: [], + defaults: [], + rest: null, + generator: false, + body: { + type: "BlockStatement", + loc: { + start: {line: 1, column: 25}, + end: {line: 1, column: 27} + }, + body: [] + }, + expression: false + } + }] + } + }] +}, { + ecmaVersion: 6, + ranges: true, + locations: true +}); + +test("class A { static get [foo]() {} }", { + type: "Program", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 33} + }, + body: [{ + type: "ClassDeclaration", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 33} + }, + id: { + type: "Identifier", + loc: { + start: {line: 1, column: 6}, + end: {line: 1, column: 7} + }, + range: [ + 6, + 7 + ], + name: "A" + }, + superClass: null, + body: { + type: "ClassBody", + loc: { + start: {line: 1, column: 8}, + end: {line: 1, column: 33} + }, + body: [{ + type: "MethodDefinition", + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 31} + }, + static: true, + computed: true, + key: { + type: "Identifier", + loc: { + start: {line: 1, column: 22}, + end: {line: 1, column: 25} + }, + name: "foo" + }, + kind: "get", + value: { + type: "FunctionExpression", + loc: { + start: {line: 1, column: 26}, + end: {line: 1, column: 31} + }, + id: null, + params: [], + defaults: [], + rest: null, + generator: false, + body: { + type: "BlockStatement", + loc: { + start: {line: 1, column: 29}, + end: {line: 1, column: 31} + }, + body: [] + }, + expression: false + } + }] + } + }] +}, { + ecmaVersion: 6, + ranges: true, + locations: true +}); + test("class A { set foo(v) {} get foo() {} }", { type: "Program", body: [{ From 521ab6c11dba7bcb2f59867a5104d88802d60ee9 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 9 Nov 2014 13:07:00 +1100 Subject: [PATCH 038/198] Support ParanthesizedExpressions in checkLval --- acorn.js | 4 ++ test/tests-harmony.js | 106 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/acorn.js b/acorn.js index 401b9421c8..48983c0889 100644 --- a/acorn.js +++ b/acorn.js @@ -1386,6 +1386,10 @@ } break; + case "ParenthesizedExpression": + toAssignable(node.expression, allowSpread, checkType); + break; + default: if (checkType) unexpected(node.start); } diff --git a/test/tests-harmony.js b/test/tests-harmony.js index 539418f870..1c8330de6b 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -4448,6 +4448,112 @@ test("var {a:b} = {}", { locations: true }); + +test("({ x }) = { x: 5 }", { + type: "Program", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 18} + }, + body: [{ + type: "ExpressionStatement", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 18} + }, + expression: { + type: "AssignmentExpression", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 18} + }, + operator: "=", + left: { + type: "ParenthesizedExpression", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 7} + }, + expression: { + type: "ObjectPattern", + loc: { + start: {line: 1, column: 1}, + end: {line: 1, column: 6} + }, + properties: [ + { + type: "Property", + loc: { + start: {line: 1, column: 3}, + end: {line: 1, column: 4} + }, + method: false, + shorthand: true, + computed: false, + key: { + type: "Identifier", + loc: { + start: {line: 1, column: 3}, + end: {line: 1, column: 4} + }, + name: "x" + }, + kind: "init", + value: { + type: "Identifier", + loc: { + start: {line: 1, column: 3}, + end: {line: 1, column: 4} + }, + name: "x" + } + } + ] + } + }, + right: { + type: "ObjectExpression", + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 18} + }, + properties: [{ + type: "Property", + loc: { + start: {line: 1, column: 12}, + end: {line: 1, column: 16} + }, + method: false, + shorthand: false, + computed: false, + key: { + type: "Identifier", + loc: { + start: {line: 1, column: 12}, + end: {line: 1, column: 13} + }, + name: "x" + }, + value: { + type: "Literal", + loc: { + start: {line: 1, column: 15}, + end: {line: 1, column: 16} + }, + value: 5, + raw: "5" + }, + kind: "init" + }] + } + } + }] +}, { + ecmaVersion: 6, + locations: true, + preserveParens: true +}); + // Harmony: Modules test("export var document", { From c90022e97f06636efb3401e876895916b4e814cd Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 9 Nov 2014 16:09:16 +1100 Subject: [PATCH 039/198] fix sebmck@gmail.com email --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3c7951983a..c1aad8c601 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ }, { "name": "Sebastian McKenzie", - "email": "sebmck@gmail.com.com", + "email": "sebmck@gmail.com", "web": "http://sebmck.com" } ], From fc046bab5499d9afcac66d21d96c96379546ea6c Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 9 Nov 2014 16:09:22 +1100 Subject: [PATCH 040/198] remove build status from readme --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 7610b61981..7ea245540a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ # acorn-6to5 -[![Build Status](https://travis-ci.org/sebmck/acorn-6to5.svg?branch=master)](https://travis-ci.org/sebmck/acorn-6to5) - Based on [acorn-jsx](https://github.com/RReverser/acorn-jsx). From 41f7959d9ca5f6f448e99f7b8b3219253072f3e9 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 9 Nov 2014 16:11:16 +1100 Subject: [PATCH 041/198] fix package.json identation --- package.json | 56 ++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index c1aad8c601..50857a1bd3 100644 --- a/package.json +++ b/package.json @@ -1,30 +1,30 @@ { - "name": "acorn-6to5", - "description": "Acorn fork used by 6to5", - "main": "acorn.js", - "version": "0.9.1-1", - "maintainers": [ - { - "name": "Marijn Haverbeke", - "email": "marijnh@gmail.com", - "web": "http://marijnhaverbeke.nl" - }, - { - "name": "Ingvar Stepanyan", - "email": "me@rreverser.com", - "web": "https://github.com/RReverser" - }, - { - "name": "Sebastian McKenzie", - "email": "sebmck@gmail.com", - "web": "http://sebmck.com" - } - ], - "repository": "https://github.com/sebmck/acorn-6to5", - "licenses": [{ - "type": "MIT", - "url": "http://marijnhaverbeke.nl/acorn/LICENSE" - }], - "scripts": {"test": "node test/run.js"}, - "devDependencies": {"regenerate": "~0.6.2", "unicode-7.0.0": "~0.1.5"} + "name": "acorn-6to5", + "description": "Acorn fork used by 6to5", + "main": "acorn.js", + "version": "0.9.1-1", + "maintainers": [ + { + "name": "Marijn Haverbeke", + "email": "marijnh@gmail.com", + "web": "http://marijnhaverbeke.nl" + }, + { + "name": "Ingvar Stepanyan", + "email": "me@rreverser.com", + "web": "https://github.com/RReverser" + }, + { + "name": "Sebastian McKenzie", + "email": "sebmck@gmail.com", + "web": "http://sebmck.com" + } + ], + "repository": "https://github.com/sebmck/acorn-6to5", + "licenses": [{ + "type": "MIT", + "url": "http://marijnhaverbeke.nl/acorn/LICENSE" + }], + "scripts": {"test": "node test/run.js"}, + "devDependencies": {"regenerate": "~0.6.2", "unicode-7.0.0": "~0.1.5"} } From d231f10c36e5aa42893de9023c2d21a4d0c70d43 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sun, 9 Nov 2014 15:08:59 +0200 Subject: [PATCH 042/198] Disallow parenthesis in patterns Fixes #155 --- acorn.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/acorn.js b/acorn.js index d94aee2fc3..4b1f19a04a 100644 --- a/acorn.js +++ b/acorn.js @@ -1487,10 +1487,6 @@ case "SpreadElement": break; - case "ParenthesizedExpression": - checkLVal(expr.expression); - break; - default: raise(expr.start, "Assigning to rvalue"); } From 97c06f2699295e31ac97b4599200ab352b386249 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Mon, 10 Nov 2014 00:10:54 +1100 Subject: [PATCH 043/198] Revert "Merge branch 'check-lval-paren-expressions' of https://github.com/sebmck/acorn" This reverts commit c8d701914832367e3cc6f570f8da9e6096d26eef, reversing changes made to 0f40710d6a6c846d613764f314e9fb38c247e471. --- acorn.js | 4 -- test/tests-harmony.js | 106 ------------------------------------------ 2 files changed, 110 deletions(-) diff --git a/acorn.js b/acorn.js index 7ed2fc7db6..7ab963e2f0 100644 --- a/acorn.js +++ b/acorn.js @@ -1747,10 +1747,6 @@ } break; - case "ParenthesizedExpression": - toAssignable(node.expression, allowSpread, checkType); - break; - default: if (checkType) unexpected(node.start); } diff --git a/test/tests-harmony.js b/test/tests-harmony.js index 833d229e46..2302f58f60 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -4448,112 +4448,6 @@ test("var {a:b} = {}", { locations: true }); - -test("({ x }) = { x: 5 }", { - type: "Program", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 18} - }, - body: [{ - type: "ExpressionStatement", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 18} - }, - expression: { - type: "AssignmentExpression", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 18} - }, - operator: "=", - left: { - type: "ParenthesizedExpression", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 7} - }, - expression: { - type: "ObjectPattern", - loc: { - start: {line: 1, column: 1}, - end: {line: 1, column: 6} - }, - properties: [ - { - type: "Property", - loc: { - start: {line: 1, column: 3}, - end: {line: 1, column: 4} - }, - method: false, - shorthand: true, - computed: false, - key: { - type: "Identifier", - loc: { - start: {line: 1, column: 3}, - end: {line: 1, column: 4} - }, - name: "x" - }, - kind: "init", - value: { - type: "Identifier", - loc: { - start: {line: 1, column: 3}, - end: {line: 1, column: 4} - }, - name: "x" - } - } - ] - } - }, - right: { - type: "ObjectExpression", - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 18} - }, - properties: [{ - type: "Property", - loc: { - start: {line: 1, column: 12}, - end: {line: 1, column: 16} - }, - method: false, - shorthand: false, - computed: false, - key: { - type: "Identifier", - loc: { - start: {line: 1, column: 12}, - end: {line: 1, column: 13} - }, - name: "x" - }, - value: { - type: "Literal", - loc: { - start: {line: 1, column: 15}, - end: {line: 1, column: 16} - }, - value: 5, - raw: "5" - }, - kind: "init" - }] - } - } - }] -}, { - ecmaVersion: 6, - locations: true, - preserveParens: true -}); - // Harmony: Modules test("export var document", { From 1f1a47693036f542b3d614ae1304504a02380eed Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sun, 9 Nov 2014 16:02:12 +0200 Subject: [PATCH 044/198] Update tests for #158 --- test/tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/tests.js b/test/tests.js index 287d98f84d..1571cb5150 100644 --- a/test/tests.js +++ b/test/tests.js @@ -403,7 +403,7 @@ test("(1 + 2 ) * 3", { preserveParens: true }); -test("(x) = 23", {}, { preserveParens: true }); +testFail("(x) = 23", "Assigning to rvalue (1:0)", { preserveParens: true }); test("x = []", { type: "Program", From ac42c108f469e072482f7c949cf1389e6dccc934 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Tue, 11 Nov 2014 09:13:42 +1100 Subject: [PATCH 045/198] Implement ES7 Async/Await --- acorn.js | 127 +++++-- test/tests-harmony.js | 767 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 874 insertions(+), 20 deletions(-) diff --git a/acorn.js b/acorn.js index 401b9421c8..4b80e3d375 100644 --- a/acorn.js +++ b/acorn.js @@ -164,7 +164,13 @@ comments.push(comment); }; } - isKeyword = options.ecmaVersion >= 6 ? isEcma6Keyword : isEcma5AndLessKeyword; + if (options.ecmaVersion >= 7) { + isKeyword = isEcma7Keyword; + } else if (options.ecmaVersion === 6) { + isKeyword = isEcma6Keyword; + } else { + isKeyword = isEcma5AndLessKeyword; + } } // The `getLineInfo` function is mostly useful when the @@ -289,7 +295,7 @@ // that `break` and `continue` have somewhere to jump to, and // `strict` indicates whether strict mode is on. - var inFunction, inGenerator, labels, strict; + var inFunction, inGenerator, inAsync, labels, strict; // This counter is used for checking that arrow expressions did // not contain nested parentheses in argument list. @@ -305,7 +311,7 @@ function initParserState() { lastStart = lastEnd = tokPos; if (options.locations) lastEndLoc = new Position; - inFunction = inGenerator = strict = false; + inFunction = inGenerator = inAsync = strict = false; labels = []; readToken(); } @@ -368,6 +374,7 @@ var _class = {keyword: "class"}, _extends = {keyword: "extends", beforeExpr: true}; var _export = {keyword: "export"}, _import = {keyword: "import"}; var _yield = {keyword: "yield", beforeExpr: true}; + var _async = {keyword: "async"}, _await = {keyword: "await", beforeExpr: true}; // The keywords that denote values. @@ -394,7 +401,8 @@ "void": {keyword: "void", prefix: true, beforeExpr: true}, "delete": {keyword: "delete", prefix: true, beforeExpr: true}, "class": _class, "extends": _extends, - "export": _export, "import": _import, "yield": _yield}; + "export": _export, "import": _import, "yield": _yield, + "await": _await, "async": _async}; // Punctuation token types. Again, the `type` property is purely for debugging. @@ -517,7 +525,11 @@ var isEcma5AndLessKeyword = makePredicate(ecma5AndLessKeywords); - var isEcma6Keyword = makePredicate(ecma5AndLessKeywords + " let const class extends export import yield"); + var ecma6AndLessKeywords = ecma5AndLessKeywords + " let const class extends export import yield"; + + var isEcma6Keyword = makePredicate(ecma6AndLessKeywords); + + var isEcma7Keyword = makePredicate(ecma6AndLessKeywords + " async await"); var isKeyword = isEcma5AndLessKeyword; @@ -1539,6 +1551,7 @@ case _debugger: return parseDebuggerStatement(node); case _do: return parseDoStatement(node); case _for: return parseForStatement(node); + case _async: return parseAsync(node, true); case _function: return parseFunctionStatement(node); case _class: return parseClass(node, true); case _if: return parseIfStatement(node); @@ -1640,7 +1653,46 @@ function parseFunctionStatement(node) { next(); - return parseFunction(node, true); + return parseFunction(node, true, false); + } + + function parseAsync(node, isStatement) { + if (options.ecmaVersion < 7) { + unexpected(); + } + + next(); + + switch (tokType) { + case _function: + next(); + return parseFunction(node, isStatement, true); + + if (!isStatement) unexpected(); + + case _name: + var id = parseIdent(tokType !== _name); + if (eat(_arrow)) { + return parseArrowExpression(node, [id], true); + } + + case _parenL: + var oldParenL = ++metParenL; + var exprList = []; + next(); + if (tokType !== _parenR) { + var val = parseExpression(); + exprList = val.type === "SequenceExpression" ? val.expressions : [val]; + } + expect(_parenR); + // if '=>' follows '(...)', convert contents to arguments + if (metParenL === oldParenL && eat(_arrow)) { + return parseArrowExpression(node, exprList, true); + } + + default: + unexpected(); + } } function parseIfStatement(node) { @@ -2023,6 +2075,9 @@ case _yield: if (inGenerator) return parseYield(); + case _await: + if (inAsync) return parseAwait(); + case _name: var start = storeCurrentPos(); var id = parseIdent(tokType !== _name); @@ -2104,10 +2159,13 @@ case _braceL: return parseObj(); + case _async: + return parseAsync(startNode(), false); + case _function: var node = startNode(); next(); - return parseFunction(node, false); + return parseFunction(node, false, false); case _class: return parseClass(startNode(), false); @@ -2192,7 +2250,11 @@ if (options.allowTrailingCommas && eat(_braceR)) break; } else first = false; - var prop = startNode(), isGenerator; + var prop = startNode(), isGenerator, isAsync; + if (options.ecmaVersion >= 7) { + isAsync = eat(_async); + if (tokType === _star) unexpected(); + } if (options.ecmaVersion >= 6) { prop.method = false; prop.shorthand = false; @@ -2205,13 +2267,13 @@ } else if (options.ecmaVersion >= 6 && tokType === _parenL) { prop.kind = "init"; prop.method = true; - prop.value = parseMethod(isGenerator); + prop.value = parseMethod(isGenerator, isAsync); } else if (options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set")) { - if (isGenerator) unexpected(); + if (isGenerator || isAsync) unexpected(); prop.kind = prop.key.name; parsePropertyName(prop); - prop.value = parseMethod(false); + prop.value = parseMethod(false, false); } else if (options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { prop.kind = "init"; prop.value = prop.key; @@ -2240,7 +2302,7 @@ // Initialize empty function node. - function initFunction(node) { + function initFunction(node, isAsync) { node.id = null; node.params = []; if (options.ecmaVersion >= 6) { @@ -2248,14 +2310,18 @@ node.rest = null; node.generator = false; } + if (options.ecmaVersion >= 7) { + node.async = isAsync; + } } // Parse a function declaration or literal (depending on the // `isStatement` parameter). - function parseFunction(node, isStatement, allowExpressionBody) { - initFunction(node); + function parseFunction(node, isStatement, isAsync, allowExpressionBody) { + initFunction(node, isAsync); if (options.ecmaVersion >= 6) { + if (node.async && tokType === _star) unexpected(); node.generator = eat(_star); } if (isStatement || tokType === _name) { @@ -2268,9 +2334,9 @@ // Parse object or class method. - function parseMethod(isGenerator) { + function parseMethod(isGenerator, isAsync) { var node = startNode(); - initFunction(node); + initFunction(node, isAsync); parseFunctionParams(node); var allowExpressionBody; if (options.ecmaVersion >= 6) { @@ -2285,8 +2351,8 @@ // Parse arrow function expression with given parameters. - function parseArrowExpression(node, params) { - initFunction(node); + function parseArrowExpression(node, params, isAsync) { + initFunction(node, isAsync); var defaults = node.defaults, hasDefaults = false; @@ -2355,6 +2421,8 @@ function parseFunctionBody(node, allowExpression) { var isExpression = allowExpression && tokType !== _braceL; + var oldInAsync = inAsync; + inAsync = node.async; if (isExpression) { node.body = parseExpression(true); node.expression = true; @@ -2367,6 +2435,7 @@ node.expression = false; inFunction = oldInFunc; inGenerator = oldInGen; labels = oldLabels; } + inAsync = oldInAsync; // If this is a strict mode function, verify that argument names // are not repeated, and it does not try to bind the words `eval` @@ -2400,17 +2469,22 @@ } else { method['static'] = false; } + var isAsync = false; + if (options.ecmaVersion >= 7) { + isAsync = eat(_async); + if (tokType === _star) unexpected(); + } var isGenerator = eat(_star); parsePropertyName(method); if (tokType === _name && !method.computed && method.key.type === "Identifier" && (method.key.name === "get" || method.key.name === "set")) { - if (isGenerator) unexpected(); + if (isGenerator || isAsync) unexpected(); method.kind = method.key.name; parsePropertyName(method); } else { method.kind = ""; } - method.value = parseMethod(isGenerator); + method.value = parseMethod(isGenerator, isAsync); classBody.body.push(finishNode(method, "MethodDefinition")); eat(_semi); } @@ -2615,6 +2689,19 @@ return finishNode(node, "YieldExpression"); } + // Parses await expression inside async function. + + function parseAwait() { + var node = startNode(); + next(); + if (eat(_semi) || canInsertSemicolon()) { + unexpected(); + } + node.delegate = eat(_star); + node.argument = parseExpression(true); + return finishNode(node, "AwaitExpression"); + } + // Parses array and generator comprehensions. function parseComprehension(node, isGenerator) { diff --git a/test/tests-harmony.js b/test/tests-harmony.js index 539418f870..deca238eee 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -13405,6 +13405,771 @@ test("/[a-z]/u", { ecmaVersion: 6 }); +// ES7: Async Functions + +test('async function foo(promise) { await promise; }', { + type: "Program", + body: [{ + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + loc: { + start: {line: 1, column: 15}, + end: {line: 1, column: 18} + } + }, + params: [{ + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 19}, + end: {line: 1, column: 26} + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [{ + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 36}, + end: {line: 1, column: 43} + } + }, + loc: { + start: {line: 1, column: 30}, + end: {line: 1, column: 43} + } + }, + loc: { + start: {line: 1, column: 30}, + end: {line: 1, column: 44} + } + }], + loc: { + start: {line: 1, column: 28}, + end: {line: 1, column: 46} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 46} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('(function(x) { async function inner() { await x } })', { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "x", + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 11} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "inner", + loc: { + start: {line: 1, column: 30}, + end: {line: 1, column: 35} + } + }, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "x", + loc: { + start: {line: 1, column: 46}, + end: {line: 1, column: 47} + } + }, + loc: { + start: {line: 1, column: 40}, + end: {line: 1, column: 47} + } + }, + loc: { + start: {line: 1, column: 40}, + end: {line: 1, column: 47} + } + } + ], + loc: { + start: {line: 1, column: 38}, + end: {line: 1, column: 49} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 15}, + end: {line: 1, column: 49} + } + } + ], + loc: { + start: {line: 1, column: 13}, + end: {line: 1, column: 51} + } + }, + rest: null, + generator: false, + expression: false, + loc: { + start: {line: 1, column: 1}, + end: {line: 1, column: 51} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 52} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('var foo = async function(promise) { await promise; }', { + type: "Program", + body: [{ + type: "VariableDeclaration", + declarations: [ + { + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "foo", + loc: { + start: {line: 1, column: 4}, + end: {line: 1, column: 7} + } + }, + init: { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 25}, + end: {line: 1, column: 32} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 42}, + end: {line: 1, column: 49} + } + }, + loc: { + start: {line: 1, column: 36}, + end: {line: 1, column: 49} + } + }, + loc: { + start: {line: 1, column: 36}, + end: {line: 1, column: 50} + } + } + ], + loc: { + start: {line: 1, column: 34}, + end: {line: 1, column: 52} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 52} + } + }, + loc: { + start: {line: 1, column: 4}, + end: {line: 1, column: 52} + } + } + ], + kind: "var", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 52} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('var o = { a: 1, async foo(promise) { await promise } }', { + type: "Program", + body: [{ + type: "VariableDeclaration", + declarations: [ + { + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "o", + loc: { + start: {line: 1, column: 4}, + end: {line: 1, column: 5} + } + }, + init: { + type: "ObjectExpression", + properties: [ + { + type: "Property", + key: { + type: "Identifier", + name: "a", + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 11} + } + }, + value: { + type: "Literal", + value: 1, + loc: { + start: {line: 1, column: 13}, + end: {line: 1, column: 14} + } + }, + kind: "init", + method: false, + shorthand: false, + computed: false, + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 14} + } + }, + { + type: "Property", + key: { + type: "Identifier", + name: "foo", + loc: { + start: {line: 1, column: 22}, + end: {line: 1, column: 25} + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 26}, + end: {line: 1, column: 33} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 43}, + end: {line: 1, column: 50} + } + }, + loc: { + start: {line: 1, column: 37}, + end: {line: 1, column: 50} + } + }, + loc: { + start: {line: 1, column: 37}, + end: {line: 1, column: 50} + } + } + ], + loc: { + start: {line: 1, column: 35}, + end: {line: 1, column: 52} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 25}, + end: {line: 1, column: 52} + } + }, + kind: "init", + method: true, + shorthand: false, + computed: false, + loc: { + start: {line: 1, column: 16}, + end: {line: 1, column: 52} + } + } + ], + loc: { + start: {line: 1, column: 8}, + end: {line: 1, column: 54} + } + }, + loc: { + start: {line: 1, column: 4}, + end: {line: 1, column: 54} + } + } + ], + kind: "var", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 54} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('class Foo { async bar(promise) { await promise } }', { + type: "Program", + body: [{ + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + loc: { + start: {line: 1, column: 6}, + end: {line: 1, column: 9} + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [ + { + type: "MethodDefinition", + key: { + type: "Identifier", + name: "bar", + loc: { + start: {line: 1, column: 18}, + end: {line: 1, column: 21} + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 22}, + end: {line: 1, column: 29} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 39}, + end: {line: 1, column: 46} + } + }, + loc: { + start: {line: 1, column: 33}, + end: {line: 1, column: 46} + } + }, + loc: { + start: {line: 1, column: 33}, + end: {line: 1, column: 46} + } + } + ], + loc: { + start: {line: 1, column: 31}, + end: {line: 1, column: 48} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 21}, + end: {line: 1, column: 48} + } + }, + kind: "", + static: false, + loc: { + start: {line: 1, column: 12}, + end: {line: 1, column: 48} + } + } + ], + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 50} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 50} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('f(a, async promise => await promise)', { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "f", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 1} + } + }, + arguments: [ + { + type: "Identifier", + name: "a", + loc: { + start: {line: 1, column: 2}, + end: {line: 1, column: 3} + } + }, + { + type: "ArrowFunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 11}, + end: {line: 1, column: 18} + } + } + ], + defaults: [], + body: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 28}, + end: {line: 1, column: 35} + } + }, + loc: { + start: {line: 1, column: 22}, + end: {line: 1, column: 35} + } + }, + rest: null, + generator: false, + expression: true, + async: true, + loc: { + start: {line: 1, column: 5}, + end: {line: 1, column: 35} + } + } + ], + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 36} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 36} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('f(a, async(x, y) => await [x, y], b)', { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "f", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 1} + } + }, + arguments: [ + { + type: "Identifier", + name: "a", + loc: { + start: {line: 1, column: 2}, + end: {line: 1, column: 3} + } + }, + { + type: "ArrowFunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "x", + loc: { + start: {line: 1, column: 11}, + end: {line: 1, column: 12} + } + }, + { + type: "Identifier", + name: "y", + loc: { + start: {line: 1, column: 14}, + end: {line: 1, column: 15} + } + } + ], + defaults: [], + body: { + type: "AwaitExpression", + argument: { + type: "ArrayExpression", + elements: [ + { + type: "Identifier", + name: "x", + loc: { + start: {line: 1, column: 27}, + end: {line: 1, column: 28} + } + }, + { + type: "Identifier", + name: "y", + loc: { + start: {line: 1, column: 30}, + end: {line: 1, column: 31} + } + } + ], + loc: { + start: {line: 1, column: 26}, + end: {line: 1, column: 32} + } + }, + loc: { + start: {line: 1, column: 20}, + end: {line: 1, column: 32} + } + }, + rest: null, + generator: false, + expression: true, + async: true, + loc: { + start: {line: 1, column: 5}, + end: {line: 1, column: 32} + } + }, + { + type: "Identifier", + name: "b", + loc: { + start: {line: 1, column: 34}, + end: {line: 1, column: 35} + } + } + ], + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 36} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 36} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('f(async function(promise) { await promise })', { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "f", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 1} + } + }, + arguments: [ + { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 17}, + end: {line: 1, column: 24} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 34}, + end: {line: 1, column: 41} + } + }, + loc: { + start: {line: 1, column: 28}, + end: {line: 1, column: 41} + } + }, + loc: { + start: {line: 1, column: 28}, + end: {line: 1, column: 41} + } + } + ], + loc: { + start: {line: 1, column: 26}, + end: {line: 1, column: 43} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 2}, + end: {line: 1, column: 43} + } + } + ], + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 44} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 44} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + // Harmony Invalid syntax testFail("0o", "Expected number in radix 8 (1:2)", {ecmaVersion: 6}); @@ -13517,6 +14282,8 @@ testFail("(10) => 00", "Unexpected token (1:1)", {ecmaVersion: 6}); testFail("(10, 20) => 00", "Unexpected token (1:1)", {ecmaVersion: 6}); +testFail("function foo(promise) { await promise; }", "Unexpected token (1:30)", {ecmaVersion: 7}); + testFail("yield v", "Unexpected token (1:6)", {ecmaVersion: 6}); testFail("yield 10", "Unexpected token (1:6)", {ecmaVersion: 6}); From 211b3a6fdf8bcd57abb41e5561ef90461e59e3ca Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Tue, 11 Nov 2014 09:13:42 +1100 Subject: [PATCH 046/198] Implement ES7 Async/Await --- acorn.js | 127 +++++-- test/tests-harmony.js | 769 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 876 insertions(+), 20 deletions(-) diff --git a/acorn.js b/acorn.js index 401b9421c8..0e9b364416 100644 --- a/acorn.js +++ b/acorn.js @@ -164,7 +164,13 @@ comments.push(comment); }; } - isKeyword = options.ecmaVersion >= 6 ? isEcma6Keyword : isEcma5AndLessKeyword; + if (options.ecmaVersion >= 7) { + isKeyword = isEcma7Keyword; + } else if (options.ecmaVersion === 6) { + isKeyword = isEcma6Keyword; + } else { + isKeyword = isEcma5AndLessKeyword; + } } // The `getLineInfo` function is mostly useful when the @@ -289,7 +295,7 @@ // that `break` and `continue` have somewhere to jump to, and // `strict` indicates whether strict mode is on. - var inFunction, inGenerator, labels, strict; + var inFunction, inGenerator, inAsync, labels, strict; // This counter is used for checking that arrow expressions did // not contain nested parentheses in argument list. @@ -305,7 +311,7 @@ function initParserState() { lastStart = lastEnd = tokPos; if (options.locations) lastEndLoc = new Position; - inFunction = inGenerator = strict = false; + inFunction = inGenerator = inAsync = strict = false; labels = []; readToken(); } @@ -368,6 +374,7 @@ var _class = {keyword: "class"}, _extends = {keyword: "extends", beforeExpr: true}; var _export = {keyword: "export"}, _import = {keyword: "import"}; var _yield = {keyword: "yield", beforeExpr: true}; + var _async = {keyword: "async"}, _await = {keyword: "await", beforeExpr: true}; // The keywords that denote values. @@ -394,7 +401,8 @@ "void": {keyword: "void", prefix: true, beforeExpr: true}, "delete": {keyword: "delete", prefix: true, beforeExpr: true}, "class": _class, "extends": _extends, - "export": _export, "import": _import, "yield": _yield}; + "export": _export, "import": _import, "yield": _yield, + "await": _await, "async": _async}; // Punctuation token types. Again, the `type` property is purely for debugging. @@ -517,7 +525,11 @@ var isEcma5AndLessKeyword = makePredicate(ecma5AndLessKeywords); - var isEcma6Keyword = makePredicate(ecma5AndLessKeywords + " let const class extends export import yield"); + var ecma6AndLessKeywords = ecma5AndLessKeywords + " let const class extends export import yield"; + + var isEcma6Keyword = makePredicate(ecma6AndLessKeywords); + + var isEcma7Keyword = makePredicate(ecma6AndLessKeywords + " async await"); var isKeyword = isEcma5AndLessKeyword; @@ -1539,6 +1551,7 @@ case _debugger: return parseDebuggerStatement(node); case _do: return parseDoStatement(node); case _for: return parseForStatement(node); + case _async: return parseAsync(node, true); case _function: return parseFunctionStatement(node); case _class: return parseClass(node, true); case _if: return parseIfStatement(node); @@ -1640,7 +1653,46 @@ function parseFunctionStatement(node) { next(); - return parseFunction(node, true); + return parseFunction(node, true, false); + } + + function parseAsync(node, isStatement) { + if (options.ecmaVersion < 7) { + unexpected(); + } + + next(); + + switch (tokType) { + case _function: + next(); + return parseFunction(node, isStatement, true); + + if (!isStatement) unexpected(); + + case _name: + var id = parseIdent(tokType !== _name); + if (eat(_arrow)) { + return parseArrowExpression(node, [id], true); + } + + case _parenL: + var oldParenL = ++metParenL; + var exprList = []; + next(); + if (tokType !== _parenR) { + var val = parseExpression(); + exprList = val.type === "SequenceExpression" ? val.expressions : [val]; + } + expect(_parenR); + // if '=>' follows '(...)', convert contents to arguments + if (metParenL === oldParenL && eat(_arrow)) { + return parseArrowExpression(node, exprList, true); + } + + default: + unexpected(); + } } function parseIfStatement(node) { @@ -2023,6 +2075,9 @@ case _yield: if (inGenerator) return parseYield(); + case _await: + if (inAsync) return parseAwait(); + case _name: var start = storeCurrentPos(); var id = parseIdent(tokType !== _name); @@ -2104,10 +2159,13 @@ case _braceL: return parseObj(); + case _async: + return parseAsync(startNode(), false); + case _function: var node = startNode(); next(); - return parseFunction(node, false); + return parseFunction(node, false, false); case _class: return parseClass(startNode(), false); @@ -2192,7 +2250,11 @@ if (options.allowTrailingCommas && eat(_braceR)) break; } else first = false; - var prop = startNode(), isGenerator; + var prop = startNode(), isGenerator, isAsync; + if (options.ecmaVersion >= 7) { + isAsync = eat(_async); + if (isAsync && tokType === _star) unexpected(); + } if (options.ecmaVersion >= 6) { prop.method = false; prop.shorthand = false; @@ -2205,13 +2267,13 @@ } else if (options.ecmaVersion >= 6 && tokType === _parenL) { prop.kind = "init"; prop.method = true; - prop.value = parseMethod(isGenerator); + prop.value = parseMethod(isGenerator, isAsync); } else if (options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set")) { - if (isGenerator) unexpected(); + if (isGenerator || isAsync) unexpected(); prop.kind = prop.key.name; parsePropertyName(prop); - prop.value = parseMethod(false); + prop.value = parseMethod(false, false); } else if (options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { prop.kind = "init"; prop.value = prop.key; @@ -2240,7 +2302,7 @@ // Initialize empty function node. - function initFunction(node) { + function initFunction(node, isAsync) { node.id = null; node.params = []; if (options.ecmaVersion >= 6) { @@ -2248,14 +2310,18 @@ node.rest = null; node.generator = false; } + if (options.ecmaVersion >= 7) { + node.async = isAsync; + } } // Parse a function declaration or literal (depending on the // `isStatement` parameter). - function parseFunction(node, isStatement, allowExpressionBody) { - initFunction(node); + function parseFunction(node, isStatement, isAsync, allowExpressionBody) { + initFunction(node, isAsync); if (options.ecmaVersion >= 6) { + if (isAsync && tokType === _star) unexpected(); node.generator = eat(_star); } if (isStatement || tokType === _name) { @@ -2268,9 +2334,9 @@ // Parse object or class method. - function parseMethod(isGenerator) { + function parseMethod(isGenerator, isAsync) { var node = startNode(); - initFunction(node); + initFunction(node, isAsync); parseFunctionParams(node); var allowExpressionBody; if (options.ecmaVersion >= 6) { @@ -2285,8 +2351,8 @@ // Parse arrow function expression with given parameters. - function parseArrowExpression(node, params) { - initFunction(node); + function parseArrowExpression(node, params, isAsync) { + initFunction(node, isAsync); var defaults = node.defaults, hasDefaults = false; @@ -2355,6 +2421,8 @@ function parseFunctionBody(node, allowExpression) { var isExpression = allowExpression && tokType !== _braceL; + var oldInAsync = inAsync; + inAsync = node.async; if (isExpression) { node.body = parseExpression(true); node.expression = true; @@ -2367,6 +2435,7 @@ node.expression = false; inFunction = oldInFunc; inGenerator = oldInGen; labels = oldLabels; } + inAsync = oldInAsync; // If this is a strict mode function, verify that argument names // are not repeated, and it does not try to bind the words `eval` @@ -2400,17 +2469,22 @@ } else { method['static'] = false; } + var isAsync = false; + if (options.ecmaVersion >= 7) { + isAsync = eat(_async); + if (isAsync && tokType === _star) unexpected(); + } var isGenerator = eat(_star); parsePropertyName(method); if (tokType === _name && !method.computed && method.key.type === "Identifier" && (method.key.name === "get" || method.key.name === "set")) { - if (isGenerator) unexpected(); + if (isGenerator || isAsync) unexpected(); method.kind = method.key.name; parsePropertyName(method); } else { method.kind = ""; } - method.value = parseMethod(isGenerator); + method.value = parseMethod(isGenerator, isAsync); classBody.body.push(finishNode(method, "MethodDefinition")); eat(_semi); } @@ -2615,6 +2689,19 @@ return finishNode(node, "YieldExpression"); } + // Parses await expression inside async function. + + function parseAwait() { + var node = startNode(); + next(); + if (eat(_semi) || canInsertSemicolon()) { + unexpected(); + } + node.delegate = eat(_star); + node.argument = parseExpression(true); + return finishNode(node, "AwaitExpression"); + } + // Parses array and generator comprehensions. function parseComprehension(node, isGenerator) { diff --git a/test/tests-harmony.js b/test/tests-harmony.js index 539418f870..aa10ecec09 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -13405,6 +13405,771 @@ test("/[a-z]/u", { ecmaVersion: 6 }); +// ES7: Async Functions + +test('async function foo(promise) { await promise; }', { + type: "Program", + body: [{ + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + loc: { + start: {line: 1, column: 15}, + end: {line: 1, column: 18} + } + }, + params: [{ + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 19}, + end: {line: 1, column: 26} + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [{ + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 36}, + end: {line: 1, column: 43} + } + }, + loc: { + start: {line: 1, column: 30}, + end: {line: 1, column: 43} + } + }, + loc: { + start: {line: 1, column: 30}, + end: {line: 1, column: 44} + } + }], + loc: { + start: {line: 1, column: 28}, + end: {line: 1, column: 46} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 46} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('(function(x) { async function inner() { await x } })', { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "x", + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 11} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "inner", + loc: { + start: {line: 1, column: 30}, + end: {line: 1, column: 35} + } + }, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "x", + loc: { + start: {line: 1, column: 46}, + end: {line: 1, column: 47} + } + }, + loc: { + start: {line: 1, column: 40}, + end: {line: 1, column: 47} + } + }, + loc: { + start: {line: 1, column: 40}, + end: {line: 1, column: 47} + } + } + ], + loc: { + start: {line: 1, column: 38}, + end: {line: 1, column: 49} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 15}, + end: {line: 1, column: 49} + } + } + ], + loc: { + start: {line: 1, column: 13}, + end: {line: 1, column: 51} + } + }, + rest: null, + generator: false, + expression: false, + loc: { + start: {line: 1, column: 1}, + end: {line: 1, column: 51} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 52} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('var foo = async function(promise) { await promise; }', { + type: "Program", + body: [{ + type: "VariableDeclaration", + declarations: [ + { + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "foo", + loc: { + start: {line: 1, column: 4}, + end: {line: 1, column: 7} + } + }, + init: { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 25}, + end: {line: 1, column: 32} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 42}, + end: {line: 1, column: 49} + } + }, + loc: { + start: {line: 1, column: 36}, + end: {line: 1, column: 49} + } + }, + loc: { + start: {line: 1, column: 36}, + end: {line: 1, column: 50} + } + } + ], + loc: { + start: {line: 1, column: 34}, + end: {line: 1, column: 52} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 52} + } + }, + loc: { + start: {line: 1, column: 4}, + end: {line: 1, column: 52} + } + } + ], + kind: "var", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 52} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('var o = { a: 1, async foo(promise) { await promise } }', { + type: "Program", + body: [{ + type: "VariableDeclaration", + declarations: [ + { + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "o", + loc: { + start: {line: 1, column: 4}, + end: {line: 1, column: 5} + } + }, + init: { + type: "ObjectExpression", + properties: [ + { + type: "Property", + key: { + type: "Identifier", + name: "a", + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 11} + } + }, + value: { + type: "Literal", + value: 1, + loc: { + start: {line: 1, column: 13}, + end: {line: 1, column: 14} + } + }, + kind: "init", + method: false, + shorthand: false, + computed: false, + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 14} + } + }, + { + type: "Property", + key: { + type: "Identifier", + name: "foo", + loc: { + start: {line: 1, column: 22}, + end: {line: 1, column: 25} + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 26}, + end: {line: 1, column: 33} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 43}, + end: {line: 1, column: 50} + } + }, + loc: { + start: {line: 1, column: 37}, + end: {line: 1, column: 50} + } + }, + loc: { + start: {line: 1, column: 37}, + end: {line: 1, column: 50} + } + } + ], + loc: { + start: {line: 1, column: 35}, + end: {line: 1, column: 52} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 25}, + end: {line: 1, column: 52} + } + }, + kind: "init", + method: true, + shorthand: false, + computed: false, + loc: { + start: {line: 1, column: 16}, + end: {line: 1, column: 52} + } + } + ], + loc: { + start: {line: 1, column: 8}, + end: {line: 1, column: 54} + } + }, + loc: { + start: {line: 1, column: 4}, + end: {line: 1, column: 54} + } + } + ], + kind: "var", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 54} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('class Foo { async bar(promise) { await promise } }', { + type: "Program", + body: [{ + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + loc: { + start: {line: 1, column: 6}, + end: {line: 1, column: 9} + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [ + { + type: "MethodDefinition", + key: { + type: "Identifier", + name: "bar", + loc: { + start: {line: 1, column: 18}, + end: {line: 1, column: 21} + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 22}, + end: {line: 1, column: 29} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 39}, + end: {line: 1, column: 46} + } + }, + loc: { + start: {line: 1, column: 33}, + end: {line: 1, column: 46} + } + }, + loc: { + start: {line: 1, column: 33}, + end: {line: 1, column: 46} + } + } + ], + loc: { + start: {line: 1, column: 31}, + end: {line: 1, column: 48} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 21}, + end: {line: 1, column: 48} + } + }, + kind: "", + static: false, + loc: { + start: {line: 1, column: 12}, + end: {line: 1, column: 48} + } + } + ], + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 50} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 50} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('f(a, async promise => await promise)', { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "f", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 1} + } + }, + arguments: [ + { + type: "Identifier", + name: "a", + loc: { + start: {line: 1, column: 2}, + end: {line: 1, column: 3} + } + }, + { + type: "ArrowFunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 11}, + end: {line: 1, column: 18} + } + } + ], + defaults: [], + body: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 28}, + end: {line: 1, column: 35} + } + }, + loc: { + start: {line: 1, column: 22}, + end: {line: 1, column: 35} + } + }, + rest: null, + generator: false, + expression: true, + async: true, + loc: { + start: {line: 1, column: 5}, + end: {line: 1, column: 35} + } + } + ], + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 36} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 36} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('f(a, async(x, y) => await [x, y], b)', { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "f", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 1} + } + }, + arguments: [ + { + type: "Identifier", + name: "a", + loc: { + start: {line: 1, column: 2}, + end: {line: 1, column: 3} + } + }, + { + type: "ArrowFunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "x", + loc: { + start: {line: 1, column: 11}, + end: {line: 1, column: 12} + } + }, + { + type: "Identifier", + name: "y", + loc: { + start: {line: 1, column: 14}, + end: {line: 1, column: 15} + } + } + ], + defaults: [], + body: { + type: "AwaitExpression", + argument: { + type: "ArrayExpression", + elements: [ + { + type: "Identifier", + name: "x", + loc: { + start: {line: 1, column: 27}, + end: {line: 1, column: 28} + } + }, + { + type: "Identifier", + name: "y", + loc: { + start: {line: 1, column: 30}, + end: {line: 1, column: 31} + } + } + ], + loc: { + start: {line: 1, column: 26}, + end: {line: 1, column: 32} + } + }, + loc: { + start: {line: 1, column: 20}, + end: {line: 1, column: 32} + } + }, + rest: null, + generator: false, + expression: true, + async: true, + loc: { + start: {line: 1, column: 5}, + end: {line: 1, column: 32} + } + }, + { + type: "Identifier", + name: "b", + loc: { + start: {line: 1, column: 34}, + end: {line: 1, column: 35} + } + } + ], + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 36} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 36} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('f(async function(promise) { await promise })', { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "f", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 1} + } + }, + arguments: [ + { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 17}, + end: {line: 1, column: 24} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 34}, + end: {line: 1, column: 41} + } + }, + loc: { + start: {line: 1, column: 28}, + end: {line: 1, column: 41} + } + }, + loc: { + start: {line: 1, column: 28}, + end: {line: 1, column: 41} + } + } + ], + loc: { + start: {line: 1, column: 26}, + end: {line: 1, column: 43} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 2}, + end: {line: 1, column: 43} + } + } + ], + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 44} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 44} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + // Harmony Invalid syntax testFail("0o", "Expected number in radix 8 (1:2)", {ecmaVersion: 6}); @@ -13517,6 +14282,10 @@ testFail("(10) => 00", "Unexpected token (1:1)", {ecmaVersion: 6}); testFail("(10, 20) => 00", "Unexpected token (1:1)", {ecmaVersion: 6}); +testFail("function foo(promise) { await promise; }", "Unexpected token (1:30)", {ecmaVersion: 7}); + +testFail("async function* foo(promise) { await promise; }", "Unexpected token (1:14)", {ecmaVersion: 7}); + testFail("yield v", "Unexpected token (1:6)", {ecmaVersion: 6}); testFail("yield 10", "Unexpected token (1:6)", {ecmaVersion: 6}); From 273dda04f1c0e2c7a05d47a1c194f2dabcceebec Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Tue, 11 Nov 2014 09:43:15 +1100 Subject: [PATCH 047/198] Revert "Merge branch 'async-await' of https://github.com/sebmck/acorn" This reverts commit 904d46ae736214d50da3a5c2b616204f0e0ae7d1, reversing changes made to 49e421660af161af0e75c2fa066ea356d6650e69. --- acorn.js | 131 ++------ test/tests-harmony.js | 767 ------------------------------------------ 2 files changed, 22 insertions(+), 876 deletions(-) diff --git a/acorn.js b/acorn.js index 0205d2e25f..f9321ecfe7 100644 --- a/acorn.js +++ b/acorn.js @@ -167,13 +167,7 @@ if (options.strictMode) { strict = true; } - if (options.ecmaVersion >= 7) { - isKeyword = isEcma7Keyword; - } else if (options.ecmaVersion === 6) { - isKeyword = isEcma6Keyword; - } else { - isKeyword = isEcma5AndLessKeyword; - } + isKeyword = options.ecmaVersion >= 6 ? isEcma6Keyword : isEcma5AndLessKeyword; } // The `getLineInfo` function is mostly useful when the @@ -298,7 +292,7 @@ // that `break` and `continue` have somewhere to jump to, and // `strict` indicates whether strict mode is on. - var inFunction, inGenerator, inAsync, labels, strict, + var inFunction, inGenerator, labels, strict, inXJSChild, inXJSTag, inXJSChildExpression; // This counter is used for checking that arrow expressions did @@ -315,7 +309,7 @@ function initParserState() { lastStart = lastEnd = tokPos; if (options.locations) lastEndLoc = new Position; - inFunction = inGenerator = inAsync = strict = false; + inFunction = inGenerator = strict = false; labels = []; readToken(); } @@ -382,7 +376,6 @@ var _class = {keyword: "class"}, _extends = {keyword: "extends", beforeExpr: true}; var _export = {keyword: "export"}, _import = {keyword: "import"}; var _yield = {keyword: "yield", beforeExpr: true}; - var _async = {keyword: "async"}, _await = {keyword: "await", beforeExpr: true}; // The keywords that denote values. @@ -409,8 +402,7 @@ "void": {keyword: "void", prefix: true, beforeExpr: true}, "delete": {keyword: "delete", prefix: true, beforeExpr: true}, "class": _class, "extends": _extends, - "export": _export, "import": _import, "yield": _yield, - "await": _await, "async": _async}; + "export": _export, "import": _import, "yield": _yield}; // Punctuation token types. Again, the `type` property is purely for debugging. @@ -538,11 +530,7 @@ var isEcma5AndLessKeyword = makePredicate(ecma5AndLessKeywords); - var ecma6AndLessKeywords = ecma5AndLessKeywords + " let const class extends export import yield"; - - var isEcma6Keyword = makePredicate(ecma6AndLessKeywords); - - var isEcma7Keyword = makePredicate(ecma6AndLessKeywords + " async await"); + var isEcma6Keyword = makePredicate(ecma5AndLessKeywords + " let const class extends export import yield"); var isKeyword = isEcma5AndLessKeyword; @@ -1908,7 +1896,6 @@ case _debugger: return parseDebuggerStatement(node); case _do: return parseDoStatement(node); case _for: return parseForStatement(node); - case _async: return parseAsync(node, true); case _function: return parseFunctionStatement(node); case _class: return parseClass(node, true); case _if: return parseIfStatement(node); @@ -2010,46 +1997,7 @@ function parseFunctionStatement(node) { next(); - return parseFunction(node, true, false); - } - - function parseAsync(node, isStatement) { - if (options.ecmaVersion < 7) { - unexpected(); - } - - next(); - - switch (tokType) { - case _function: - next(); - return parseFunction(node, isStatement, true); - - if (!isStatement) unexpected(); - - case _name: - var id = parseIdent(tokType !== _name); - if (eat(_arrow)) { - return parseArrowExpression(node, [id], true); - } - - case _parenL: - var oldParenL = ++metParenL; - var exprList = []; - next(); - if (tokType !== _parenR) { - var val = parseExpression(); - exprList = val.type === "SequenceExpression" ? val.expressions : [val]; - } - expect(_parenR); - // if '=>' follows '(...)', convert contents to arguments - if (metParenL === oldParenL && eat(_arrow)) { - return parseArrowExpression(node, exprList, true); - } - - default: - unexpected(); - } + return parseFunction(node, true); } function parseIfStatement(node) { @@ -2432,9 +2380,6 @@ case _yield: if (inGenerator) return parseYield(); - case _await: - if (inAsync) return parseAwait(); - case _name: var start = storeCurrentPos(); var id = parseIdent(tokType !== _name); @@ -2516,13 +2461,10 @@ case _braceL: return parseObj(); - case _async: - return parseAsync(startNode(), false); - case _function: var node = startNode(); next(); - return parseFunction(node, false, false); + return parseFunction(node, false); case _class: return parseClass(startNode(), false); @@ -2610,11 +2552,7 @@ if (options.allowTrailingCommas && eat(_braceR)) break; } else first = false; - var prop = startNode(), isGenerator, isAsync; - if (options.ecmaVersion >= 7) { - isAsync = eat(_async); - if (tokType === _star) unexpected(); - } + var prop = startNode(), isGenerator; if (options.ecmaVersion >= 6) { prop.method = false; prop.shorthand = false; @@ -2627,13 +2565,13 @@ } else if (options.ecmaVersion >= 6 && tokType === _parenL) { prop.kind = "init"; prop.method = true; - prop.value = parseMethod(isGenerator, isAsync); + 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 || isAsync) unexpected(); + if (isGenerator) unexpected(); prop.kind = prop.key.name; parsePropertyName(prop); - prop.value = parseMethod(false, false); + prop.value = parseMethod(false); } else if (options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { prop.kind = "init"; prop.value = prop.key; @@ -2662,26 +2600,22 @@ // Initialize empty function node. - function initFunction(node, isAsync) { + function initFunction(node) { node.id = null; node.params = []; if (options.ecmaVersion >= 6) { node.defaults = []; node.rest = null; node.generator = false; - } - if (options.ecmaVersion >= 7) { - node.async = isAsync; - } + } } // Parse a function declaration or literal (depending on the // `isStatement` parameter). - function parseFunction(node, isStatement, isAsync, allowExpressionBody) { - initFunction(node, isAsync); + function parseFunction(node, isStatement, allowExpressionBody) { + initFunction(node); if (options.ecmaVersion >= 6) { - if (node.async && tokType === _star) unexpected(); node.generator = eat(_star); } if (isStatement || tokType === _name) { @@ -2694,9 +2628,9 @@ // Parse object or class method. - function parseMethod(isGenerator, isAsync) { + function parseMethod(isGenerator) { var node = startNode(); - initFunction(node, isAsync); + initFunction(node); parseFunctionParams(node); var allowExpressionBody; if (options.ecmaVersion >= 6) { @@ -2711,8 +2645,8 @@ // Parse arrow function expression with given parameters. - function parseArrowExpression(node, params, isAsync) { - initFunction(node, isAsync); + function parseArrowExpression(node, params) { + initFunction(node); var defaults = node.defaults, hasDefaults = false; @@ -2780,9 +2714,7 @@ function parseFunctionBody(node, allowExpression) { var isExpression = allowExpression && tokType !== _braceL; - - var oldInAsync = inAsync; - inAsync = node.async; + if (isExpression) { node.body = parseExpression(true); node.expression = true; @@ -2795,7 +2727,6 @@ node.expression = false; inFunction = oldInFunc; inGenerator = oldInGen; labels = oldLabels; } - inAsync = oldInAsync; // If this is a strict mode function, verify that argument names // are not repeated, and it does not try to bind the words `eval` @@ -2829,22 +2760,17 @@ } else { method['static'] = false; } - var isAsync = false; - if (options.ecmaVersion >= 7) { - isAsync = eat(_async); - if (tokType === _star) unexpected(); - } var isGenerator = eat(_star); parsePropertyName(method); if (tokType !== _parenL && !method.computed && method.key.type === "Identifier" && (method.key.name === "get" || method.key.name === "set")) { - if (isGenerator || isAsync) unexpected(); + if (isGenerator) unexpected(); method.kind = method.key.name; parsePropertyName(method); } else { method.kind = ""; } - method.value = parseMethod(isGenerator, isAsync); + method.value = parseMethod(isGenerator); classBody.body.push(finishNode(method, "MethodDefinition")); eat(_semi); } @@ -3049,19 +2975,6 @@ return finishNode(node, "YieldExpression"); } - // Parses await expression inside async function. - - function parseAwait() { - var node = startNode(); - next(); - if (eat(_semi) || canInsertSemicolon()) { - unexpected(); - } - node.delegate = eat(_star); - node.argument = parseExpression(true); - return finishNode(node, "AwaitExpression"); - } - // Parses array and generator comprehensions. function parseComprehension(node, isGenerator) { diff --git a/test/tests-harmony.js b/test/tests-harmony.js index abe47b1d0f..2302f58f60 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -13558,771 +13558,6 @@ test("/[a-z]/u", { ecmaVersion: 6 }); -// ES7: Async Functions - -test('async function foo(promise) { await promise; }', { - type: "Program", - body: [{ - type: "FunctionDeclaration", - id: { - type: "Identifier", - name: "foo", - loc: { - start: {line: 1, column: 15}, - end: {line: 1, column: 18} - } - }, - params: [{ - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 19}, - end: {line: 1, column: 26} - } - }], - defaults: [], - body: { - type: "BlockStatement", - body: [{ - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 36}, - end: {line: 1, column: 43} - } - }, - loc: { - start: {line: 1, column: 30}, - end: {line: 1, column: 43} - } - }, - loc: { - start: {line: 1, column: 30}, - end: {line: 1, column: 44} - } - }], - loc: { - start: {line: 1, column: 28}, - end: {line: 1, column: 46} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 46} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('(function(x) { async function inner() { await x } })', { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "x", - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 11} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "FunctionDeclaration", - id: { - type: "Identifier", - name: "inner", - loc: { - start: {line: 1, column: 30}, - end: {line: 1, column: 35} - } - }, - params: [], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "x", - loc: { - start: {line: 1, column: 46}, - end: {line: 1, column: 47} - } - }, - loc: { - start: {line: 1, column: 40}, - end: {line: 1, column: 47} - } - }, - loc: { - start: {line: 1, column: 40}, - end: {line: 1, column: 47} - } - } - ], - loc: { - start: {line: 1, column: 38}, - end: {line: 1, column: 49} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 15}, - end: {line: 1, column: 49} - } - } - ], - loc: { - start: {line: 1, column: 13}, - end: {line: 1, column: 51} - } - }, - rest: null, - generator: false, - expression: false, - loc: { - start: {line: 1, column: 1}, - end: {line: 1, column: 51} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 52} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('var foo = async function(promise) { await promise; }', { - type: "Program", - body: [{ - type: "VariableDeclaration", - declarations: [ - { - type: "VariableDeclarator", - id: { - type: "Identifier", - name: "foo", - loc: { - start: {line: 1, column: 4}, - end: {line: 1, column: 7} - } - }, - init: { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 25}, - end: {line: 1, column: 32} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 42}, - end: {line: 1, column: 49} - } - }, - loc: { - start: {line: 1, column: 36}, - end: {line: 1, column: 49} - } - }, - loc: { - start: {line: 1, column: 36}, - end: {line: 1, column: 50} - } - } - ], - loc: { - start: {line: 1, column: 34}, - end: {line: 1, column: 52} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 52} - } - }, - loc: { - start: {line: 1, column: 4}, - end: {line: 1, column: 52} - } - } - ], - kind: "var", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 52} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('var o = { a: 1, async foo(promise) { await promise } }', { - type: "Program", - body: [{ - type: "VariableDeclaration", - declarations: [ - { - type: "VariableDeclarator", - id: { - type: "Identifier", - name: "o", - loc: { - start: {line: 1, column: 4}, - end: {line: 1, column: 5} - } - }, - init: { - type: "ObjectExpression", - properties: [ - { - type: "Property", - key: { - type: "Identifier", - name: "a", - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 11} - } - }, - value: { - type: "Literal", - value: 1, - loc: { - start: {line: 1, column: 13}, - end: {line: 1, column: 14} - } - }, - kind: "init", - method: false, - shorthand: false, - computed: false, - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 14} - } - }, - { - type: "Property", - key: { - type: "Identifier", - name: "foo", - loc: { - start: {line: 1, column: 22}, - end: {line: 1, column: 25} - } - }, - value: { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 26}, - end: {line: 1, column: 33} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 43}, - end: {line: 1, column: 50} - } - }, - loc: { - start: {line: 1, column: 37}, - end: {line: 1, column: 50} - } - }, - loc: { - start: {line: 1, column: 37}, - end: {line: 1, column: 50} - } - } - ], - loc: { - start: {line: 1, column: 35}, - end: {line: 1, column: 52} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 25}, - end: {line: 1, column: 52} - } - }, - kind: "init", - method: true, - shorthand: false, - computed: false, - loc: { - start: {line: 1, column: 16}, - end: {line: 1, column: 52} - } - } - ], - loc: { - start: {line: 1, column: 8}, - end: {line: 1, column: 54} - } - }, - loc: { - start: {line: 1, column: 4}, - end: {line: 1, column: 54} - } - } - ], - kind: "var", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 54} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('class Foo { async bar(promise) { await promise } }', { - type: "Program", - body: [{ - type: "ClassDeclaration", - id: { - type: "Identifier", - name: "Foo", - loc: { - start: {line: 1, column: 6}, - end: {line: 1, column: 9} - } - }, - superClass: null, - body: { - type: "ClassBody", - body: [ - { - type: "MethodDefinition", - key: { - type: "Identifier", - name: "bar", - loc: { - start: {line: 1, column: 18}, - end: {line: 1, column: 21} - } - }, - value: { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 22}, - end: {line: 1, column: 29} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 39}, - end: {line: 1, column: 46} - } - }, - loc: { - start: {line: 1, column: 33}, - end: {line: 1, column: 46} - } - }, - loc: { - start: {line: 1, column: 33}, - end: {line: 1, column: 46} - } - } - ], - loc: { - start: {line: 1, column: 31}, - end: {line: 1, column: 48} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 21}, - end: {line: 1, column: 48} - } - }, - kind: "", - static: false, - loc: { - start: {line: 1, column: 12}, - end: {line: 1, column: 48} - } - } - ], - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 50} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 50} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('f(a, async promise => await promise)', { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "CallExpression", - callee: { - type: "Identifier", - name: "f", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 1} - } - }, - arguments: [ - { - type: "Identifier", - name: "a", - loc: { - start: {line: 1, column: 2}, - end: {line: 1, column: 3} - } - }, - { - type: "ArrowFunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 11}, - end: {line: 1, column: 18} - } - } - ], - defaults: [], - body: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 28}, - end: {line: 1, column: 35} - } - }, - loc: { - start: {line: 1, column: 22}, - end: {line: 1, column: 35} - } - }, - rest: null, - generator: false, - expression: true, - async: true, - loc: { - start: {line: 1, column: 5}, - end: {line: 1, column: 35} - } - } - ], - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 36} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 36} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('f(a, async(x, y) => await [x, y], b)', { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "CallExpression", - callee: { - type: "Identifier", - name: "f", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 1} - } - }, - arguments: [ - { - type: "Identifier", - name: "a", - loc: { - start: {line: 1, column: 2}, - end: {line: 1, column: 3} - } - }, - { - type: "ArrowFunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "x", - loc: { - start: {line: 1, column: 11}, - end: {line: 1, column: 12} - } - }, - { - type: "Identifier", - name: "y", - loc: { - start: {line: 1, column: 14}, - end: {line: 1, column: 15} - } - } - ], - defaults: [], - body: { - type: "AwaitExpression", - argument: { - type: "ArrayExpression", - elements: [ - { - type: "Identifier", - name: "x", - loc: { - start: {line: 1, column: 27}, - end: {line: 1, column: 28} - } - }, - { - type: "Identifier", - name: "y", - loc: { - start: {line: 1, column: 30}, - end: {line: 1, column: 31} - } - } - ], - loc: { - start: {line: 1, column: 26}, - end: {line: 1, column: 32} - } - }, - loc: { - start: {line: 1, column: 20}, - end: {line: 1, column: 32} - } - }, - rest: null, - generator: false, - expression: true, - async: true, - loc: { - start: {line: 1, column: 5}, - end: {line: 1, column: 32} - } - }, - { - type: "Identifier", - name: "b", - loc: { - start: {line: 1, column: 34}, - end: {line: 1, column: 35} - } - } - ], - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 36} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 36} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('f(async function(promise) { await promise })', { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "CallExpression", - callee: { - type: "Identifier", - name: "f", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 1} - } - }, - arguments: [ - { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 17}, - end: {line: 1, column: 24} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 34}, - end: {line: 1, column: 41} - } - }, - loc: { - start: {line: 1, column: 28}, - end: {line: 1, column: 41} - } - }, - loc: { - start: {line: 1, column: 28}, - end: {line: 1, column: 41} - } - } - ], - loc: { - start: {line: 1, column: 26}, - end: {line: 1, column: 43} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 2}, - end: {line: 1, column: 43} - } - } - ], - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 44} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 44} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - // Harmony Invalid syntax testFail("0o", "Expected number in radix 8 (1:2)", {ecmaVersion: 6}); @@ -14435,8 +13670,6 @@ testFail("(10) => 00", "Unexpected token (1:1)", {ecmaVersion: 6}); testFail("(10, 20) => 00", "Unexpected token (1:1)", {ecmaVersion: 6}); -testFail("function foo(promise) { await promise; }", "Unexpected token (1:30)", {ecmaVersion: 7}); - testFail("yield v", "Unexpected token (1:6)", {ecmaVersion: 6}); testFail("yield 10", "Unexpected token (1:6)", {ecmaVersion: 6}); From c5ca7ee32c91c419940a71c5028e71020d720bde Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 12 Nov 2014 20:41:55 +1100 Subject: [PATCH 048/198] Add remaining esprima-fb async/await tests --- test/tests-harmony.js | 230 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) diff --git a/test/tests-harmony.js b/test/tests-harmony.js index aa10ecec09..e8dc034f88 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -14170,6 +14170,236 @@ test('f(async function(promise) { await promise })', { locations: true }); +test("f(a, async(1, 2), b);", { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "f", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 1} + } + }, + arguments: [ + { + type: "Identifier", + name: "a", + loc: { + start: {line: 1, column: 2}, + end: {line: 1, column: 3} + } + }, + { + type: "CallExpression", + callee: { + type: "Identifier", + name: "async", + loc: { + start: {line: 1, column: 5}, + end: {line: 1, column: 10} + } + }, + arguments: [ + { + type: "Literal", + value: 1, + loc: { + start: {line: 1,column: 11}, + end: {line: 1,column: 12} + } + }, + { + type: "Literal", + value: 2, + loc: { + start: {line: 1,column: 14}, + end: {line: 1,column: 15} + } + } + ], + loc: { + start: {line: 1,column: 5}, + end: {line: 1,column: 16} + } + }, + { + type: "Identifier", + name: "b", + loc: { + start: {line: 1,column: 18}, + end: {line: 1,column: 19} + } + } + ], + loc: { + start: {line: 1,column: 0}, + end: {line: 1,column: 20} + } + }, + loc: { + start: {line: 1,column: 0}, + end: {line: 1,column: 20} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test("var ok = async(x);", { + type: "Program", + body: [{ + type: "VariableDeclaration", + declarations: [ + { + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "ok", + loc: { + start: {line: 1,column: 4}, + end: {line: 1,column: 6} + } + }, + init: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "async", + loc: { + start: {line: 1,column: 9}, + end: {line: 1,column: 14} + } + }, + arguments: [ + { + type: "Identifier", + name: "x", + loc: { + start: {line: 1,column: 15}, + end: {line: 1,column: 16} + } + } + ], + loc: { + start: {line: 1,column: 9}, + end: {line: 1,column: 17} + } + }, + loc: { + start: {line: 1,column: 4}, + end: {line: 1,column: 17} + } + } + ], + kind: "var", + loc: { + start: {line: 1,column: 0}, + end: {line: 1,column: 17} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test("var async; async = 10;", { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "FunctionExpression", + id: null, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "VariableDeclaration", + declarations: [ + { + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "async", + loc: { + start: {line: 1,column: 18}, + end: {line: 1,column: 23} + } + }, + init: null, + loc: { + start: {line: 1,column: 18}, + end: {line: 1,column: 23} + } + } + ], + kind: "var", + loc: { + start: {line: 1,column: 14}, + end: {line: 1,column: 24} + } + }, + { + type: "ExpressionStatement", + expression: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "Identifier", + name: "async", + loc: { + start: {line: 1,column: 25}, + end: {line: 1,column: 30} + } + }, + right: { + type: "Literal", + value: 10, + loc: { + start: {line: 1,column: 33}, + end: {line: 1,column: 35} + } + }, + loc: { + start: {line: 1,column: 25}, + end: {line: 1,column: 35} + } + }, + loc: { + start: {line: 1,column: 25}, + end: {line: 1,column: 36} + } + } + ], + loc: { + start: {line: 1,column: 12}, + end: {line: 1,column: 37} + } + }, + rest: null, + generator: false, + expression: false, + loc: { + start: {line: 1,column: 1}, + end: {line: 1,column: 37} + } + }, + loc: { + start: {line: 1,column: 0}, + end: {line: 1,column: 38} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + // Harmony Invalid syntax testFail("0o", "Expected number in radix 8 (1:2)", {ecmaVersion: 6}); From 2506be7b1ac70ddbfb36b537cab6dcb86bdd2cee Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Thu, 13 Nov 2014 13:16:49 +1100 Subject: [PATCH 049/198] Add support for exporting async functions --- acorn.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index 0e9b364416..188df622d6 100644 --- a/acorn.js +++ b/acorn.js @@ -2542,7 +2542,7 @@ function parseExport(node) { next(); // export var|const|let|function|class ...; - if (tokType === _var || tokType === _const || tokType === _let || tokType === _function || tokType === _class) { + if (tokType === _var || tokType === _const || tokType === _let || tokType === _function || tokType === _class || tokType === _async) { node.declaration = parseStatement(); node['default'] = false; node.specifiers = null; From 8ef9ecc34dd358cf5abe97711908e2f6724031f5 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 13 Nov 2014 19:25:25 +0200 Subject: [PATCH 050/198] Update version. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 31341d59e4..13bdd52350 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-jsx", "description": "Alternative React JSX parser", "main": "acorn.js", - "version": "0.9.1-1", + "version": "0.9.1-2", "maintainers": [ { "name": "Marijn Haverbeke", From 82f88c459d1f522383bb73430e2d4dc09607d31d Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 15 Nov 2014 02:30:12 +0200 Subject: [PATCH 051/198] Fix ignored whitespaces before children elements. Similar to 790afe (template literals). Fixes #4. --- acorn.js | 3 ++ package.json | 2 +- test/tests-jsx.js | 126 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 121 insertions(+), 10 deletions(-) diff --git a/acorn.js b/acorn.js index 13052a1218..419afd10ae 100644 --- a/acorn.js +++ b/acorn.js @@ -3272,6 +3272,9 @@ inXJSChild = origInXJSChild; inXJSTag = origInXJSTag; tokRegexpAllowed = false; + if (inXJSChild) { + tokPos = tokEnd; + } expect(_gt); return finishNode(node, "XJSClosingElement"); } diff --git a/package.json b/package.json index 13bdd52350..e8cc1b2784 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-jsx", "description": "Alternative React JSX parser", "main": "acorn.js", - "version": "0.9.1-2", + "version": "0.9.1-3", "maintainers": [ { "name": "Marijn Haverbeke", diff --git a/test/tests-jsx.js b/test/tests-jsx.js index 5f61b9edf5..d7b58acb94 100644 --- a/test/tests-jsx.js +++ b/test/tests-jsx.js @@ -3199,6 +3199,111 @@ var fbTestFixture = { ] } } + }, + 'Regression': { + '

    foo bar baz

    ;': { + type: "ExpressionStatement", + start: 0, + end: 40, + expression: { + type: "XJSElement", + start: 0, + end: 38, + openingElement: { + type: "XJSOpeningElement", + start: 0, + end: 3, + attributes: [], + name: { + type: "XJSIdentifier", + start: 1, + end: 2, + name: "p" + }, + selfClosing: false + }, + closingElement: { + type: "XJSClosingElement", + start: 34, + end: 38, + name: { + type: "XJSIdentifier", + start: 36, + end: 37, + name: "p" + } + }, + children: [ + { + type: "Literal", + start: 3, + end: 7, + value: "foo ", + raw: "foo " + }, + { + type: "XJSElement", + start: 7, + end: 30, + openingElement: { + type: "XJSOpeningElement", + start: 7, + end: 22, + attributes: [{ + type: "XJSAttribute", + start: 10, + end: 21, + name: { + type: "XJSIdentifier", + start: 10, + end: 14, + name: "href" + }, + value: { + type: "Literal", + start: 15, + end: 21, + value: "test", + raw: "\"test\"" + } + }], + name: { + type: "XJSIdentifier", + start: 8, + end: 9, + name: "a" + }, + selfClosing: false + }, + closingElement: { + type: "XJSClosingElement", + start: 26, + end: 30, + name: { + type: "XJSIdentifier", + start: 28, + end: 29, + name: "a" + } + }, + children: [{ + type: "Literal", + start: 22, + end: 26, + value: " bar", + raw: " bar" + }] + }, + { + type: "Literal", + start: 30, + end: 34, + value: " baz", + raw: " baz" + } + ] + } + } } }; @@ -3206,13 +3311,16 @@ if (typeof exports !== "undefined") { var test = require("./driver.js").test; } -for (var code in fbTestFixture.XJS) { - test(code, { - type: 'Program', - body: [fbTestFixture.XJS[code]] - }, { - ecmaVersion: 6, - locations: true, - ranges: true - }); +for (var ns in fbTestFixture) { + ns = fbTestFixture[ns]; + for (var code in ns) { + test(code, { + type: 'Program', + body: [ns[code]] + }, { + ecmaVersion: 6, + locations: true, + ranges: true + }); + } } From 68acfb7cc56de919dba17e09356225d9a2eedbf4 Mon Sep 17 00:00:00 2001 From: Richard Eames Date: Tue, 18 Nov 2014 13:08:24 -0700 Subject: [PATCH 052/198] Better async/await support --- acorn.js | 95 +++++- bin/acorn | 1 + test/tests-harmony.js | 736 +++++++++++++++++++++++++++++++++--------- 3 files changed, 674 insertions(+), 158 deletions(-) diff --git a/acorn.js b/acorn.js index b89158e41e..9fd3bdf6ca 100644 --- a/acorn.js +++ b/acorn.js @@ -2028,9 +2028,10 @@ if (options.ecmaVersion < 7) { unexpected(); } - - next(); - + var start = storeCurrentPos(); + var retNode = startNodeAt(start); + var finishedAsync = parseIdent(true); + switch (tokType) { case _function: next(); @@ -2057,10 +2058,36 @@ if (metParenL === oldParenL && eat(_arrow)) { return parseArrowExpression(node, exprList, true); } - + retNode.callee = finishedAsync; + retNode.arguments = exprList; + retNode = parseSubscripts(finishNode(retNode, "CallExpression"), start); + break; default: - unexpected(); + if (isStatement) { + if (tokType.beforeExpr) { + // Probably using async as an ident + if (tokType.isAssign) { + retNode.operator = tokVal; + retNode.left = tokType === _eq ? toAssignable(finishedAsync) : finishedAsync; + checkLVal(finishedAsync); + next(); + retNode.right = parseMaybeAssign(); + retNode = finishNode(retNode, "AssignmentExpression"); + } + else { + unexpected + } + semicolon(); + } + else { + unexpected(); + } + } + else { + retNode = finishedAsync; + } } + return retNode; } function parseIfStatement(node) { @@ -2615,19 +2642,65 @@ } else first = false; var prop = startNode(), isGenerator, isAsync; - if (options.ecmaVersion >= 7) { - isAsync = eat(_async); - if (isAsync && tokType === _star) unexpected(); + if (tokType == _async) { // "async" is a valid key + prop.computed = false; + prop.key = parseIdent(true); + isAsync = true; } if (options.ecmaVersion >= 6) { - prop.method = false; - prop.shorthand = false; isGenerator = eat(_star); } - parsePropertyName(prop); + + if (tokType === _name || tokType.keyword) { + // possibly an async function + if (isAsync && options.ecmaVersion < 7) { + unexpected(); + } + if (isAsync && isGenerator) { + unexpected(); + } + if (options.ecmaVersion >= 6) { + prop.method = false; + prop.shorthand = false; + } + parsePropertyName(prop); + } + else if (tokType === _colon) { + // key could be "async" + if (options.ecmaVersion >= 6) { + prop.method = false; + prop.shorthand = false; + } + isAsync = false; + } + else if (tokType === _bracketL) { + // could be async computed + if (isAsync && isGenerator) { + unexpected(); + } + parsePropertyName(prop); + } + else if (tokType === _braceR) { + // object unpack, and key could be == "async" + if (isAsync) { + isAsync = false; + prop.computed = false; + } + else { + parsePropertyName(prop); + } + } + else { + //unexpected(); + isAsync = false; + parsePropertyName(prop); + } if (eat(_colon)) { prop.value = parseExpression(true); prop.kind = "init"; + if (isAsync) { + unexpected(); + } } else if (options.ecmaVersion >= 6 && tokType === _parenL) { prop.kind = "init"; prop.method = true; diff --git a/bin/acorn b/bin/acorn index 2a226da063..dd5baea012 100755 --- a/bin/acorn +++ b/bin/acorn @@ -20,6 +20,7 @@ for (var i = 2; i < process.argv.length; ++i) { else if (arg == "--ecma3") options.ecmaVersion = 3; else if (arg == "--ecma5") options.ecmaVersion = 5; else if (arg == "--ecma6") options.ecmaVersion = 6; + else if (arg == "--ecma7") options.ecmaVersion = 7; else if (arg == "--strictSemicolons") options.strictSemicolons = true; else if (arg == "--locations") options.locations = true; else if (arg == "--silent") silent = true; diff --git a/test/tests-harmony.js b/test/tests-harmony.js index ebb51f6d4c..22d120abe7 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -14371,81 +14371,170 @@ test('f(async function(promise) { await promise })', { }); test("f(a, async(1, 2), b);", { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "CallExpression", - callee: { - type: "Identifier", - name: "f", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 1} + "type": "Program", + "start": 0, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 21 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 21 } }, - arguments: [ - { - type: "Identifier", - name: "a", - loc: { - start: {line: 1, column: 2}, - end: {line: 1, column: 3} + "expression": { + "type": "CallExpression", + "start": 0, + "end": 20, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 20 } }, - { - type: "CallExpression", - callee: { - type: "Identifier", - name: "async", - loc: { - start: {line: 1, column: 5}, - end: {line: 1, column: 10} + "callee": { + "type": "Identifier", + "start": 0, + "end": 1, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 } }, - arguments: [ - { - type: "Literal", - value: 1, - loc: { - start: {line: 1,column: 11}, - end: {line: 1,column: 12} + "name": "f" + }, + "arguments": [ + { + "type": "Identifier", + "start": 2, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 2 + }, + "end": { + "line": 1, + "column": 3 } }, - { - type: "Literal", - value: 2, - loc: { - start: {line: 1,column: 14}, - end: {line: 1,column: 15} + "name": "a" + }, + { + "type": "CallExpression", + "start": 5, + "end": 16, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 16 } - } - ], - loc: { - start: {line: 1,column: 5}, - end: {line: 1,column: 16} + }, + "callee": { + "type": "Identifier", + "start": 5, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "name": "async" + }, + "arguments": [ + { + "type": "Literal", + "start": 11, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "value": 1, + "raw": "1" + }, + { + "type": "Literal", + "start": 14, + "end": 15, + "loc": { + "start": { + "line": 1, + "column": 14 + }, + "end": { + "line": 1, + "column": 15 + } + }, + "value": 2, + "raw": "2" + } + ] + }, + { + "type": "Identifier", + "start": 18, + "end": 19, + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 19 + } + }, + "name": "b" } - }, - { - type: "Identifier", - name: "b", - loc: { - start: {line: 1,column: 18}, - end: {line: 1,column: 19} - } - } - ], - loc: { - start: {line: 1,column: 0}, - end: {line: 1,column: 20} + ] } - }, - loc: { - start: {line: 1,column: 0}, - end: {line: 1,column: 20} } - }] -}, { + ] +} +, { ecmaVersion: 7, locations: true }); @@ -14499,7 +14588,7 @@ test("var ok = async(x);", { kind: "var", loc: { start: {line: 1,column: 0}, - end: {line: 1,column: 17} + end: {line: 1,column: 18} } }] }, { @@ -14508,98 +14597,448 @@ test("var ok = async(x);", { }); test("var async; async = 10;", { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "FunctionExpression", - id: null, - params: [], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "VariableDeclaration", - declarations: [ - { - type: "VariableDeclarator", - id: { - type: "Identifier", - name: "async", - loc: { - start: {line: 1,column: 18}, - end: {line: 1,column: 23} - } - }, - init: null, - loc: { - start: {line: 1,column: 18}, - end: {line: 1,column: 23} - } - } - ], - kind: "var", - loc: { - start: {line: 1,column: 14}, - end: {line: 1,column: 24} - } - }, - { - type: "ExpressionStatement", - expression: { - type: "AssignmentExpression", - operator: "=", - left: { - type: "Identifier", - name: "async", - loc: { - start: {line: 1,column: 25}, - end: {line: 1,column: 30} - } - }, - right: { - type: "Literal", - value: 10, - loc: { - start: {line: 1,column: 33}, - end: {line: 1,column: 35} - } - }, - loc: { - start: {line: 1,column: 25}, - end: {line: 1,column: 35} - } - }, - loc: { - start: {line: 1,column: 25}, - end: {line: 1,column: 36} - } - } - ], - loc: { - start: {line: 1,column: 12}, - end: {line: 1,column: 37} + "type": "Program", + "start": 0, + "end": 22, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 22 + } + }, + "body": [ + { + "type": "VariableDeclaration", + "start": 0, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 10 } }, - rest: null, - generator: false, - expression: false, - loc: { - start: {line: 1,column: 1}, - end: {line: 1,column: 37} - } + "declarations": [ + { + "type": "VariableDeclarator", + "start": 4, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "id": { + "type": "Identifier", + "start": 4, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "name": "async" + }, + "init": null + } + ], + "kind": "var" }, - loc: { - start: {line: 1,column: 0}, - end: {line: 1,column: 38} + { + "type": "AssignmentExpression", + "start": 11, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 21 + } + }, + "operator": "=", + "left": { + "type": "Identifier", + "start": 11, + "end": 16, + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 16 + } + }, + "name": "async" + }, + "right": { + "type": "Literal", + "start": 19, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 1, + "column": 21 + } + }, + "value": 10, + "raw": "10" + } } - }] + ] }, { ecmaVersion: 7, locations: true }); +test("var {a, async} = b;" { + "type": "Program", + "start": 0, + "end": 19, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 19 + } + }, + "body": [ + { + "type": "VariableDeclaration", + "start": 0, + "end": 19, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 19 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 4, + "end": 18, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 18 + } + }, + "id": { + "type": "ObjectPattern", + "start": 4, + "end": 14, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 14 + } + }, + "properties": [ + { + "type": "Property", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "method": false, + "shorthand": true, + "computed": false, + "key": { + "type": "Identifier", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "name": "a" + }, + "kind": "init", + "value": { + "type": "Identifier", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "name": "a" + } + }, + { + "type": "Property", + "start": 8, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "computed": false, + "key": { + "type": "Identifier", + "start": 8, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "name": "async" + }, + "kind": "init", + "value": { + "type": "Identifier", + "start": 8, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "name": "async" + }, + "shorthand": true + } + ] + }, + "init": { + "type": "Identifier", + "start": 17, + "end": 18, + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 18 + } + }, + "name": "b" + } + } + ], + "kind": "var" + } + ] +}, { + ecmaVersion: 7, + locations: true +}); + +test("var x = { async: true };", { + "type": "Program", + "start": 0, + "end": 24, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "body": [ + { + "type": "VariableDeclaration", + "start": 0, + "end": 24, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 24 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 4, + "end": 23, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 23 + } + }, + "id": { + "type": "Identifier", + "start": 4, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 5 + } + }, + "name": "x" + }, + "init": { + "type": "ObjectExpression", + "start": 8, + "end": 23, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 23 + } + }, + "properties": [ + { + "type": "Property", + "start": 10, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 21 + } + }, + "computed": false, + "key": { + "type": "Identifier", + "start": 10, + "end": 15, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 15 + } + }, + "name": "async" + }, + "method": false, + "shorthand": false, + "value": { + "type": "Literal", + "start": 17, + "end": 21, + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 21 + } + }, + "value": true, + "raw": "true" + }, + "kind": "init" + } + ] + } + } + ], + "kind": "var" + } + ] +}, {ecmaVersion: 7, locations: true}); // Harmony Invalid syntax testFail("0o", "Expected number in radix 8 (1:2)", {ecmaVersion: 6}); @@ -14716,6 +15155,9 @@ testFail("function foo(promise) { await promise; }", "Unexpected token (1:30)", testFail("async function* foo(promise) { await promise; }", "Unexpected token (1:14)", {ecmaVersion: 7}); +testFail("var a = { async ['a']: true }", "Unexpected token (1:28)", {ecmaVersion: 7}); +testFail("var a = { async *['a'](){} }", "Unexpected token (1:17)", {ecmaVersion: 7}); + testFail("yield v", "Unexpected token (1:6)", {ecmaVersion: 6}); testFail("yield 10", "Unexpected token (1:6)", {ecmaVersion: 6}); From d09acb7d3b0ea9f1ccb6ad113ea4094621fad7df Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 19 Nov 2014 12:49:33 +1100 Subject: [PATCH 053/198] disable loose test runner --- test/run.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/test/run.js b/test/run.js index 4075bc55fb..f7dbbe7c94 100644 --- a/test/run.js +++ b/test/run.js @@ -50,18 +50,6 @@ config: { parse: (typeof require === "undefined" ? window.acorn : require("../acorn.js")).parse } - }, - Loose: { - config: { - parse: (typeof require === "undefined" ? window.acorn : require("../acorn_loose")).parse_dammit, - loose: true, - filter: function (test) { - if (/`/.test(test.code)) return false; // FIXME remove this when the loose parse supports template strings - var opts = test.options || {}; - if (opts.loose === false) return false; - return (opts.ecmaVersion || 5) <= 6; - } - } } }; From b0bf126c22aa0d29e8b467b1d6b32692068f1800 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 19 Nov 2014 12:49:41 +1100 Subject: [PATCH 054/198] fix up async/await --- acorn.js | 13 +++---------- test/tests-harmony.js | 2 +- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/acorn.js b/acorn.js index 9fd3bdf6ca..16a80e27d7 100644 --- a/acorn.js +++ b/acorn.js @@ -2075,7 +2075,7 @@ retNode = finishNode(retNode, "AssignmentExpression"); } else { - unexpected + unexpected(); } semicolon(); } @@ -2649,6 +2649,8 @@ } if (options.ecmaVersion >= 6) { isGenerator = eat(_star); + prop.method = false; + prop.shorthand = false; } if (tokType === _name || tokType.keyword) { @@ -2659,18 +2661,9 @@ if (isAsync && isGenerator) { unexpected(); } - if (options.ecmaVersion >= 6) { - prop.method = false; - prop.shorthand = false; - } parsePropertyName(prop); } else if (tokType === _colon) { - // key could be "async" - if (options.ecmaVersion >= 6) { - prop.method = false; - prop.shorthand = false; - } isAsync = false; } else if (tokType === _bracketL) { diff --git a/test/tests-harmony.js b/test/tests-harmony.js index 22d120abe7..c2683c3da8 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -14716,7 +14716,7 @@ test("var async; async = 10;", { locations: true }); -test("var {a, async} = b;" { +test("var {a, async} = b;", { "type": "Program", "start": 0, "end": 19, From f35dad09805cafceb899f77688d8329310327eb0 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 19 Nov 2014 13:20:47 +1100 Subject: [PATCH 055/198] Revert "fix up async/await" This reverts commit f18f264a330258da521027cc4edd5852e26f8add. --- acorn.js | 13 ++++++++++--- test/tests-harmony.js | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/acorn.js b/acorn.js index 16a80e27d7..9fd3bdf6ca 100644 --- a/acorn.js +++ b/acorn.js @@ -2075,7 +2075,7 @@ retNode = finishNode(retNode, "AssignmentExpression"); } else { - unexpected(); + unexpected } semicolon(); } @@ -2649,8 +2649,6 @@ } if (options.ecmaVersion >= 6) { isGenerator = eat(_star); - prop.method = false; - prop.shorthand = false; } if (tokType === _name || tokType.keyword) { @@ -2661,9 +2659,18 @@ if (isAsync && isGenerator) { unexpected(); } + if (options.ecmaVersion >= 6) { + prop.method = false; + prop.shorthand = false; + } parsePropertyName(prop); } else if (tokType === _colon) { + // key could be "async" + if (options.ecmaVersion >= 6) { + prop.method = false; + prop.shorthand = false; + } isAsync = false; } else if (tokType === _bracketL) { diff --git a/test/tests-harmony.js b/test/tests-harmony.js index c2683c3da8..22d120abe7 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -14716,7 +14716,7 @@ test("var async; async = 10;", { locations: true }); -test("var {a, async} = b;", { +test("var {a, async} = b;" { "type": "Program", "start": 0, "end": 19, From 5e119c22d65980b2499cbfdefde9084bfb7a39ae Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 19 Nov 2014 13:20:59 +1100 Subject: [PATCH 056/198] Revert "Better async/await support" This reverts commit 89437cfd7f8bb380490fb574fd91a128a120f5b4. --- acorn.js | 95 +----- bin/acorn | 1 - test/tests-harmony.js | 722 ++++++++---------------------------------- 3 files changed, 151 insertions(+), 667 deletions(-) diff --git a/acorn.js b/acorn.js index 9fd3bdf6ca..b89158e41e 100644 --- a/acorn.js +++ b/acorn.js @@ -2028,10 +2028,9 @@ if (options.ecmaVersion < 7) { unexpected(); } - var start = storeCurrentPos(); - var retNode = startNodeAt(start); - var finishedAsync = parseIdent(true); - + + next(); + switch (tokType) { case _function: next(); @@ -2058,36 +2057,10 @@ if (metParenL === oldParenL && eat(_arrow)) { return parseArrowExpression(node, exprList, true); } - retNode.callee = finishedAsync; - retNode.arguments = exprList; - retNode = parseSubscripts(finishNode(retNode, "CallExpression"), start); - break; + default: - if (isStatement) { - if (tokType.beforeExpr) { - // Probably using async as an ident - if (tokType.isAssign) { - retNode.operator = tokVal; - retNode.left = tokType === _eq ? toAssignable(finishedAsync) : finishedAsync; - checkLVal(finishedAsync); - next(); - retNode.right = parseMaybeAssign(); - retNode = finishNode(retNode, "AssignmentExpression"); - } - else { - unexpected - } - semicolon(); - } - else { - unexpected(); - } - } - else { - retNode = finishedAsync; - } + unexpected(); } - return retNode; } function parseIfStatement(node) { @@ -2642,65 +2615,19 @@ } else first = false; var prop = startNode(), isGenerator, isAsync; - if (tokType == _async) { // "async" is a valid key - prop.computed = false; - prop.key = parseIdent(true); - isAsync = true; + if (options.ecmaVersion >= 7) { + isAsync = eat(_async); + if (isAsync && tokType === _star) unexpected(); } if (options.ecmaVersion >= 6) { + prop.method = false; + prop.shorthand = false; isGenerator = eat(_star); } - - if (tokType === _name || tokType.keyword) { - // possibly an async function - if (isAsync && options.ecmaVersion < 7) { - unexpected(); - } - if (isAsync && isGenerator) { - unexpected(); - } - if (options.ecmaVersion >= 6) { - prop.method = false; - prop.shorthand = false; - } - parsePropertyName(prop); - } - else if (tokType === _colon) { - // key could be "async" - if (options.ecmaVersion >= 6) { - prop.method = false; - prop.shorthand = false; - } - isAsync = false; - } - else if (tokType === _bracketL) { - // could be async computed - if (isAsync && isGenerator) { - unexpected(); - } - parsePropertyName(prop); - } - else if (tokType === _braceR) { - // object unpack, and key could be == "async" - if (isAsync) { - isAsync = false; - prop.computed = false; - } - else { - parsePropertyName(prop); - } - } - else { - //unexpected(); - isAsync = false; - parsePropertyName(prop); - } + parsePropertyName(prop); if (eat(_colon)) { prop.value = parseExpression(true); prop.kind = "init"; - if (isAsync) { - unexpected(); - } } else if (options.ecmaVersion >= 6 && tokType === _parenL) { prop.kind = "init"; prop.method = true; diff --git a/bin/acorn b/bin/acorn index dd5baea012..2a226da063 100755 --- a/bin/acorn +++ b/bin/acorn @@ -20,7 +20,6 @@ for (var i = 2; i < process.argv.length; ++i) { else if (arg == "--ecma3") options.ecmaVersion = 3; else if (arg == "--ecma5") options.ecmaVersion = 5; else if (arg == "--ecma6") options.ecmaVersion = 6; - else if (arg == "--ecma7") options.ecmaVersion = 7; else if (arg == "--strictSemicolons") options.strictSemicolons = true; else if (arg == "--locations") options.locations = true; else if (arg == "--silent") silent = true; diff --git a/test/tests-harmony.js b/test/tests-harmony.js index 22d120abe7..ebb51f6d4c 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -14371,170 +14371,81 @@ test('f(async function(promise) { await promise })', { }); test("f(a, async(1, 2), b);", { - "type": "Program", - "start": 0, - "end": 21, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 21 - } - }, - "body": [ - { - "type": "ExpressionStatement", - "start": 0, - "end": 21, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 21 + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "f", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 1} } }, - "expression": { - "type": "CallExpression", - "start": 0, - "end": 20, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 20 + arguments: [ + { + type: "Identifier", + name: "a", + loc: { + start: {line: 1, column: 2}, + end: {line: 1, column: 3} } }, - "callee": { - "type": "Identifier", - "start": 0, - "end": 1, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 1 + { + type: "CallExpression", + callee: { + type: "Identifier", + name: "async", + loc: { + start: {line: 1, column: 5}, + end: {line: 1, column: 10} } }, - "name": "f" - }, - "arguments": [ - { - "type": "Identifier", - "start": 2, - "end": 3, - "loc": { - "start": { - "line": 1, - "column": 2 - }, - "end": { - "line": 1, - "column": 3 + arguments: [ + { + type: "Literal", + value: 1, + loc: { + start: {line: 1,column: 11}, + end: {line: 1,column: 12} } }, - "name": "a" - }, - { - "type": "CallExpression", - "start": 5, - "end": 16, - "loc": { - "start": { - "line": 1, - "column": 5 - }, - "end": { - "line": 1, - "column": 16 + { + type: "Literal", + value: 2, + loc: { + start: {line: 1,column: 14}, + end: {line: 1,column: 15} } - }, - "callee": { - "type": "Identifier", - "start": 5, - "end": 10, - "loc": { - "start": { - "line": 1, - "column": 5 - }, - "end": { - "line": 1, - "column": 10 - } - }, - "name": "async" - }, - "arguments": [ - { - "type": "Literal", - "start": 11, - "end": 12, - "loc": { - "start": { - "line": 1, - "column": 11 - }, - "end": { - "line": 1, - "column": 12 - } - }, - "value": 1, - "raw": "1" - }, - { - "type": "Literal", - "start": 14, - "end": 15, - "loc": { - "start": { - "line": 1, - "column": 14 - }, - "end": { - "line": 1, - "column": 15 - } - }, - "value": 2, - "raw": "2" - } - ] - }, - { - "type": "Identifier", - "start": 18, - "end": 19, - "loc": { - "start": { - "line": 1, - "column": 18 - }, - "end": { - "line": 1, - "column": 19 - } - }, - "name": "b" + } + ], + loc: { + start: {line: 1,column: 5}, + end: {line: 1,column: 16} } - ] + }, + { + type: "Identifier", + name: "b", + loc: { + start: {line: 1,column: 18}, + end: {line: 1,column: 19} + } + } + ], + loc: { + start: {line: 1,column: 0}, + end: {line: 1,column: 20} } + }, + loc: { + start: {line: 1,column: 0}, + end: {line: 1,column: 20} } - ] -} -, { + }] +}, { ecmaVersion: 7, locations: true }); @@ -14588,7 +14499,7 @@ test("var ok = async(x);", { kind: "var", loc: { start: {line: 1,column: 0}, - end: {line: 1,column: 18} + end: {line: 1,column: 17} } }] }, { @@ -14597,448 +14508,98 @@ test("var ok = async(x);", { }); test("var async; async = 10;", { - "type": "Program", - "start": 0, - "end": 22, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 22 - } - }, - "body": [ - { - "type": "VariableDeclaration", - "start": 0, - "end": 10, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 10 - } - }, - "declarations": [ - { - "type": "VariableDeclarator", - "start": 4, - "end": 9, - "loc": { - "start": { - "line": 1, - "column": 4 - }, - "end": { - "line": 1, - "column": 9 - } - }, - "id": { - "type": "Identifier", - "start": 4, - "end": 9, - "loc": { - "start": { - "line": 1, - "column": 4 - }, - "end": { - "line": 1, - "column": 9 - } - }, - "name": "async" - }, - "init": null - } - ], - "kind": "var" - }, - { - "type": "AssignmentExpression", - "start": 11, - "end": 21, - "loc": { - "start": { - "line": 1, - "column": 11 - }, - "end": { - "line": 1, - "column": 21 - } - }, - "operator": "=", - "left": { - "type": "Identifier", - "start": 11, - "end": 16, - "loc": { - "start": { - "line": 1, - "column": 11 - }, - "end": { - "line": 1, - "column": 16 - } - }, - "name": "async" - }, - "right": { - "type": "Literal", - "start": 19, - "end": 21, - "loc": { - "start": { - "line": 1, - "column": 19 - }, - "end": { - "line": 1, - "column": 21 - } - }, - "value": 10, - "raw": "10" - } - } - ] -}, { - ecmaVersion: 7, - locations: true -}); - -test("var {a, async} = b;" { - "type": "Program", - "start": 0, - "end": 19, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 19 - } - }, - "body": [ - { - "type": "VariableDeclaration", - "start": 0, - "end": 19, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 19 - } - }, - "declarations": [ - { - "type": "VariableDeclarator", - "start": 4, - "end": 18, - "loc": { - "start": { - "line": 1, - "column": 4 - }, - "end": { - "line": 1, - "column": 18 - } - }, - "id": { - "type": "ObjectPattern", - "start": 4, - "end": 14, - "loc": { - "start": { - "line": 1, - "column": 4 - }, - "end": { - "line": 1, - "column": 14 - } - }, - "properties": [ + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "FunctionExpression", + id: null, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "VariableDeclaration", + declarations: [ { - "type": "Property", - "start": 5, - "end": 6, - "loc": { - "start": { - "line": 1, - "column": 5 - }, - "end": { - "line": 1, - "column": 6 + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "async", + loc: { + start: {line: 1,column: 18}, + end: {line: 1,column: 23} } }, - "method": false, - "shorthand": true, - "computed": false, - "key": { - "type": "Identifier", - "start": 5, - "end": 6, - "loc": { - "start": { - "line": 1, - "column": 5 - }, - "end": { - "line": 1, - "column": 6 - } - }, - "name": "a" - }, - "kind": "init", - "value": { - "type": "Identifier", - "start": 5, - "end": 6, - "loc": { - "start": { - "line": 1, - "column": 5 - }, - "end": { - "line": 1, - "column": 6 - } - }, - "name": "a" + init: null, + loc: { + start: {line: 1,column: 18}, + end: {line: 1,column: 23} + } + } + ], + kind: "var", + loc: { + start: {line: 1,column: 14}, + end: {line: 1,column: 24} + } + }, + { + type: "ExpressionStatement", + expression: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "Identifier", + name: "async", + loc: { + start: {line: 1,column: 25}, + end: {line: 1,column: 30} } }, - { - "type": "Property", - "start": 8, - "end": 13, - "loc": { - "start": { - "line": 1, - "column": 8 - }, - "end": { - "line": 1, - "column": 13 - } - }, - "computed": false, - "key": { - "type": "Identifier", - "start": 8, - "end": 13, - "loc": { - "start": { - "line": 1, - "column": 8 - }, - "end": { - "line": 1, - "column": 13 - } - }, - "name": "async" - }, - "kind": "init", - "value": { - "type": "Identifier", - "start": 8, - "end": 13, - "loc": { - "start": { - "line": 1, - "column": 8 - }, - "end": { - "line": 1, - "column": 13 - } - }, - "name": "async" - }, - "shorthand": true - } - ] - }, - "init": { - "type": "Identifier", - "start": 17, - "end": 18, - "loc": { - "start": { - "line": 1, - "column": 17 + right: { + type: "Literal", + value: 10, + loc: { + start: {line: 1,column: 33}, + end: {line: 1,column: 35} + } }, - "end": { - "line": 1, - "column": 18 + loc: { + start: {line: 1,column: 25}, + end: {line: 1,column: 35} } }, - "name": "b" + loc: { + start: {line: 1,column: 25}, + end: {line: 1,column: 36} + } } + ], + loc: { + start: {line: 1,column: 12}, + end: {line: 1,column: 37} } - ], - "kind": "var" + }, + rest: null, + generator: false, + expression: false, + loc: { + start: {line: 1,column: 1}, + end: {line: 1,column: 37} + } + }, + loc: { + start: {line: 1,column: 0}, + end: {line: 1,column: 38} } - ] + }] }, { ecmaVersion: 7, locations: true }); -test("var x = { async: true };", { - "type": "Program", - "start": 0, - "end": 24, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 24 - } - }, - "body": [ - { - "type": "VariableDeclaration", - "start": 0, - "end": 24, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 24 - } - }, - "declarations": [ - { - "type": "VariableDeclarator", - "start": 4, - "end": 23, - "loc": { - "start": { - "line": 1, - "column": 4 - }, - "end": { - "line": 1, - "column": 23 - } - }, - "id": { - "type": "Identifier", - "start": 4, - "end": 5, - "loc": { - "start": { - "line": 1, - "column": 4 - }, - "end": { - "line": 1, - "column": 5 - } - }, - "name": "x" - }, - "init": { - "type": "ObjectExpression", - "start": 8, - "end": 23, - "loc": { - "start": { - "line": 1, - "column": 8 - }, - "end": { - "line": 1, - "column": 23 - } - }, - "properties": [ - { - "type": "Property", - "start": 10, - "end": 21, - "loc": { - "start": { - "line": 1, - "column": 10 - }, - "end": { - "line": 1, - "column": 21 - } - }, - "computed": false, - "key": { - "type": "Identifier", - "start": 10, - "end": 15, - "loc": { - "start": { - "line": 1, - "column": 10 - }, - "end": { - "line": 1, - "column": 15 - } - }, - "name": "async" - }, - "method": false, - "shorthand": false, - "value": { - "type": "Literal", - "start": 17, - "end": 21, - "loc": { - "start": { - "line": 1, - "column": 17 - }, - "end": { - "line": 1, - "column": 21 - } - }, - "value": true, - "raw": "true" - }, - "kind": "init" - } - ] - } - } - ], - "kind": "var" - } - ] -}, {ecmaVersion: 7, locations: true}); // Harmony Invalid syntax testFail("0o", "Expected number in radix 8 (1:2)", {ecmaVersion: 6}); @@ -15155,9 +14716,6 @@ testFail("function foo(promise) { await promise; }", "Unexpected token (1:30)", testFail("async function* foo(promise) { await promise; }", "Unexpected token (1:14)", {ecmaVersion: 7}); -testFail("var a = { async ['a']: true }", "Unexpected token (1:28)", {ecmaVersion: 7}); -testFail("var a = { async *['a'](){} }", "Unexpected token (1:17)", {ecmaVersion: 7}); - testFail("yield v", "Unexpected token (1:6)", {ecmaVersion: 6}); testFail("yield 10", "Unexpected token (1:6)", {ecmaVersion: 6}); From d3e987896c5682fccdeb94d634361a6cbfb78be2 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Thu, 20 Nov 2014 19:46:47 +1100 Subject: [PATCH 057/198] Fix spread attributes within elements inside expression containers --- acorn.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/acorn.js b/acorn.js index 419afd10ae..1d357e5133 100644 --- a/acorn.js +++ b/acorn.js @@ -3169,13 +3169,14 @@ if (tokType === _braceL) { var tokStart1 = tokStart, tokStartLoc1 = tokStartLoc; - var origInXJSTag = inXJSTag; - inXJSTag = false; + var origInXJSTag = inXJSTag, origInXJSChildExpression = inXJSChildExpression; + inXJSTag = inXJSChildExpression = false; next(); if (tokType !== _ellipsis) unexpected(); var node = parseMaybeUnary(); + inXJSChildExpression = origInXJSChildExpression; inXJSTag = origInXJSTag; expect(_braceR); From 20a5d62ac643d165144c240a2f5744da86c646f8 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Thu, 20 Nov 2014 21:07:03 +1100 Subject: [PATCH 058/198] Add regression test for #5 --- test/tests-jsx.js | 77 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/test/tests-jsx.js b/test/tests-jsx.js index d7b58acb94..d0348a253e 100644 --- a/test/tests-jsx.js +++ b/test/tests-jsx.js @@ -3303,6 +3303,83 @@ var fbTestFixture = { } ] } + }, + + '
    {
    }
    ': { + type: 'Program', + start: 0, + end: 30, + body: [{ + type: 'ExpressionStatement', + start: 0, + end: 30, + expression: { + type: 'XJSElement', + start: 0, + end: 30, + openingElement: { + type: 'XJSOpeningElement', + start: 0, + end: 5, + attributes: [], + name: { + type: 'XJSIdentifier', + start: 1, + end: 4, + name: 'div' + }, + selfClosing: false + }, + closingElement: { + type: 'XJSClosingElement', + start: 24, + end: 30, + name: { + type: 'XJSIdentifier', + start: 26, + end: 29, + name: 'div' + } + }, + children: [{ + type: 'XJSExpressionContainer', + start: 5, + end: 24, + expression: { + type: 'XJSElement', + start: 6, + end: 23, + openingElement: { + type: 'XJSOpeningElement', + start: 6, + end: 23, + attributes: [ + { + type: 'XJSSpreadAttribute', + start: 11, + end: 20, + argument: { + type: 'Identifier', + start: 15, + end: 19, + name: 'test' + } + } + ], + name: { + type: 'XJSIdentifier', + start: 7, + end: 10, + name: 'div' + }, + selfClosing: true + }, + closingElement: null, + children: [] + } + }] + } + }] } } }; From 29c028acf92422c40dce417718374a3d68d141a0 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 19 Nov 2014 18:54:15 +0200 Subject: [PATCH 059/198] Temporarily disable JSX parser. --- test/run.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/run.js b/test/run.js index 4075bc55fb..f394353d1e 100644 --- a/test/run.js +++ b/test/run.js @@ -50,7 +50,7 @@ config: { parse: (typeof require === "undefined" ? window.acorn : require("../acorn.js")).parse } - }, + }/*, Loose: { config: { parse: (typeof require === "undefined" ? window.acorn : require("../acorn_loose")).parse_dammit, @@ -62,7 +62,7 @@ return (opts.ecmaVersion || 5) <= 6; } } - } + }*/ }; function report(state, code, message) { From 731984ebc7ef899d357bba868a2b1a8efa000fec Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 20 Nov 2014 12:23:49 +0200 Subject: [PATCH 060/198] Update version. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e8cc1b2784..15f0240dff 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-jsx", "description": "Alternative React JSX parser", "main": "acorn.js", - "version": "0.9.1-3", + "version": "0.9.1-4", "maintainers": [ { "name": "Marijn Haverbeke", From b3ddc683a4bcd81e4f47697b7115d882336534fa Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Thu, 20 Nov 2014 21:25:43 +1100 Subject: [PATCH 061/198] 0.9.1-2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 50857a1bd3..1925185228 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.9.1-1", + "version": "0.9.1-2", "maintainers": [ { "name": "Marijn Haverbeke", From 16b298f38c1da1ced8daf9c3094d42ce8f23aad4 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Thu, 20 Nov 2014 21:26:45 +1100 Subject: [PATCH 062/198] 0.9.1-3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1925185228..82e35a281b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.9.1-2", + "version": "0.9.1-3", "maintainers": [ { "name": "Marijn Haverbeke", From f3f49cee80c34ce4fc1223cb059231a1b67b8e0b Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Thu, 20 Nov 2014 21:38:16 +1100 Subject: [PATCH 063/198] Fix #5 regression text --- test/tests-jsx.js | 123 ++++++++++++++++++++++------------------------ 1 file changed, 59 insertions(+), 64 deletions(-) diff --git a/test/tests-jsx.js b/test/tests-jsx.js index d0348a253e..39b1b0a112 100644 --- a/test/tests-jsx.js +++ b/test/tests-jsx.js @@ -3306,80 +3306,75 @@ var fbTestFixture = { }, '
    {
    }
    ': { - type: 'Program', + type: 'ExpressionStatement', start: 0, end: 30, - body: [{ - type: 'ExpressionStatement', + expression: { + type: 'XJSElement', start: 0, end: 30, - expression: { - type: 'XJSElement', + openingElement: { + type: 'XJSOpeningElement', start: 0, + end: 5, + attributes: [], + name: { + type: 'XJSIdentifier', + start: 1, + end: 4, + name: 'div' + }, + selfClosing: false + }, + closingElement: { + type: 'XJSClosingElement', + start: 24, end: 30, - openingElement: { - type: 'XJSOpeningElement', - start: 0, - end: 5, - attributes: [], - name: { - type: 'XJSIdentifier', - start: 1, - end: 4, - name: 'div' - }, - selfClosing: false - }, - closingElement: { - type: 'XJSClosingElement', - start: 24, - end: 30, - name: { - type: 'XJSIdentifier', - start: 26, - end: 29, - name: 'div' - } - }, - children: [{ - type: 'XJSExpressionContainer', - start: 5, - end: 24, - expression: { - type: 'XJSElement', + name: { + type: 'XJSIdentifier', + start: 26, + end: 29, + name: 'div' + } + }, + children: [{ + type: 'XJSExpressionContainer', + start: 5, + end: 24, + expression: { + type: 'XJSElement', + start: 6, + end: 23, + openingElement: { + type: 'XJSOpeningElement', start: 6, end: 23, - openingElement: { - type: 'XJSOpeningElement', - start: 6, - end: 23, - attributes: [ - { - type: 'XJSSpreadAttribute', - start: 11, - end: 20, - argument: { - type: 'Identifier', - start: 15, - end: 19, - name: 'test' - } + attributes: [ + { + type: 'XJSSpreadAttribute', + start: 11, + end: 20, + argument: { + type: 'Identifier', + start: 15, + end: 19, + name: 'test' } - ], - name: { - type: 'XJSIdentifier', - start: 7, - end: 10, - name: 'div' - }, - selfClosing: true + } + ], + name: { + type: 'XJSIdentifier', + start: 7, + end: 10, + name: 'div' }, - closingElement: null, - children: [] - } - }] - } - }] + selfClosing: true + }, + closingElement: null, + children: [] + } + }] + } } } }; From 7a3683de2b406762dfb42e0f3d5036a033f02a4b Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sat, 22 Nov 2014 11:51:28 +0200 Subject: [PATCH 064/198] Fix space not being skipped after object literal inside expression container. Fixes #7. --- acorn.js | 9 ++++--- package.json | 2 +- test/tests-jsx.js | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/acorn.js b/acorn.js index 1d357e5133..f777a4e39c 100644 --- a/acorn.js +++ b/acorn.js @@ -2549,6 +2549,8 @@ function parseObj() { var node = startNode(), first = true, propHash = {}; node.properties = []; + var origInXJSChildExpression = inXJSChildExpression; + inXJSChildExpression = false; next(); while (!eat(_braceR)) { if (!first) { @@ -2584,9 +2586,10 @@ checkPropClash(prop, propHash); node.properties.push(finishNode(prop, "Property")); - } + } + inXJSChildExpression = origInXJSChildExpression; return finishNode(node, "ObjectExpression"); - } + } function parsePropertyName(prop) { if (options.ecmaVersion >= 6) { @@ -3158,7 +3161,7 @@ inXJSTag = origInXJSTag; inXJSChild = origInXJSChild; inXJSChildExpression = false; - + expect(_braceR); return finishNode(node, "XJSExpressionContainer"); } diff --git a/package.json b/package.json index 15f0240dff..1ae847636b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-jsx", "description": "Alternative React JSX parser", "main": "acorn.js", - "version": "0.9.1-4", + "version": "0.9.1-5", "maintainers": [ { "name": "Marijn Haverbeke", diff --git a/test/tests-jsx.js b/test/tests-jsx.js index 39b1b0a112..a07f0aea2e 100644 --- a/test/tests-jsx.js +++ b/test/tests-jsx.js @@ -3375,6 +3375,72 @@ var fbTestFixture = { } }] } + }, + + '
    { {a} }
    ': { + type: "ExpressionStatement", + start: 0, + end: 18, + expression: { + type: "XJSElement", + start: 0, + end: 18, + openingElement: { + type: "XJSOpeningElement", + start: 0, + end: 5, + attributes: [], + name: { + type: "XJSIdentifier", + start: 1, + end: 4, + name: "div" + }, + selfClosing: false + }, + closingElement: { + type: "XJSClosingElement", + start: 12, + end: 18, + name: { + type: "XJSIdentifier", + start: 14, + end: 17, + name: "div" + } + }, + children: [{ + type: "XJSExpressionContainer", + start: 5, + end: 12, + expression: { + type: "ObjectExpression", + start: 7, + end: 10, + properties: [{ + type: "Property", + start: 8, + end: 9, + method: false, + shorthand: true, + computed: false, + key: { + type: "Identifier", + start: 8, + end: 9, + name: "a" + }, + kind: "init", + value: { + type: "Identifier", + start: 8, + end: 9, + name: "a" + } + }] + } + }] + } } } }; From 9b38a4826b3ca5732d1c871ec7581b299825b876 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 23 Nov 2014 17:43:46 +1100 Subject: [PATCH 065/198] add support for abstract references --- acorn.js | 24 +++++- test/tests-harmony.js | 188 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 209 insertions(+), 3 deletions(-) diff --git a/acorn.js b/acorn.js index fbcefa5c43..ddb433f0b5 100644 --- a/acorn.js +++ b/acorn.js @@ -428,6 +428,7 @@ var _arrow = {type: "=>", beforeExpr: true}, _bquote = {type: "`"}, _dollarBraceL = {type: "${", beforeExpr: true}; var _ltSlash = {type: "= 7) { + var next = input.charCodeAt(tokPos); + if (next === 58) { + ++tokPos; + return finishToken(_doubleColon); + } + } + return finishToken(_colon); + case 96: // '`' if (options.ecmaVersion >= 6) { ++tokPos; @@ -1865,6 +1877,7 @@ break; case "SpreadElement": + case "VirtualPropertyExpression": break; default: @@ -2407,7 +2420,12 @@ } function parseSubscripts(base, start, noCalls) { - if (eat(_dot)) { + if (eat(_doubleColon)) { + var node = startNodeAt(start); + node.object = base; + node.property = parseIdent(true); + return parseSubscripts(finishNode(node, "VirtualPropertyExpression"), start, noCalls); + } else if (eat(_dot)) { var node = startNodeAt(start); node.object = base; node.property = parseIdent(true); diff --git a/test/tests-harmony.js b/test/tests-harmony.js index ebb51f6d4c..c3c080673a 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -13605,6 +13605,194 @@ test("/[a-z]/u", { ecmaVersion: 6 }); +// ES7: Abstract references + +test('foo::bar;', { + type: "Program", + start: 0, + end: 9, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 9, + expression: { + type: "VirtualPropertyExpression", + start: 0, + end: 8, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "foo" + }, + property: { + type: "Identifier", + start: 5, + end: 8, + name: "bar" + } + } + }] +}, { + ecmaVersion: 7 +}); + +test('foo::bar::baz;', { + type: "Program", + start: 0, + end: 14, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 14, + expression: { + type: "VirtualPropertyExpression", + start: 0, + end: 13, + object: { + type: "VirtualPropertyExpression", + start: 0, + end: 8, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "foo" + }, + property: { + type: "Identifier", + start: 5, + end: 8, + name: "bar" + } + }, + property: { + type: "Identifier", + start: 10, + end: 13, + name: "baz" + } + } + }] +}, { + ecmaVersion: 7 +}); + +test('foo::baz();', { + type: "Program", + start: 0, + end: 11, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 11, + expression: { + type: "CallExpression", + start: 0, + end: 10, + callee: { + type: "VirtualPropertyExpression", + start: 0, + end: 8, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "foo" + }, + property: { + type: "Identifier", + start: 5, + end: 8, + name: "baz" + } + }, + arguments: [] + } + }] +}, { + ecmaVersion: 7 +}); + +test('foo::bar = "baz";', { + type: "Program", + start: 0, + end: 17, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 17, + expression: { + type: "AssignmentExpression", + start: 0, + end: 16, + operator: "=", + left: { + type: "VirtualPropertyExpression", + start: 0, + end: 8, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "foo" + }, + property: { + type: "Identifier", + start: 5, + end: 8, + name: "bar" + } + }, + right: { + type: "Literal", + start: 11, + end: 16, + value: "baz" + } + } + }] +}, { + ecmaVersion: 7 +}); + +test('delete foo::bar;', { + type: "Program", + start: 0, + end: 16, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 16, + expression: { + type: "UnaryExpression", + start: 0, + end: 15, + operator: "delete", + prefix: true, + argument: { + type: "VirtualPropertyExpression", + start: 7, + end: 15, + object: { + type: "Identifier", + start: 7, + end: 10, + name: "foo" + }, + property: { + type: "Identifier", + start: 12, + end: 15, + name: "bar" + } + } + } + }] +}, { + ecmaVersion: 7 +}); + // ES7: Async Functions test('async function foo(promise) { await promise; }', { From 25c45a1e8eca6ec66f0ba6911e4890dd94f9f03e Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 23 Nov 2014 21:00:15 +1100 Subject: [PATCH 066/198] add support for es7 object/spread and move acorn-6to5 tests to a separate file --- README.md | 7 +- acorn.js | 17 +- package.json | 2 +- test/run.js | 3 +- test/tests-6to5.js | 1591 +++++++++++++++++++++++++++++++++++++++++ test/tests-harmony.js | 1187 ------------------------------ 6 files changed, 1614 insertions(+), 1193 deletions(-) create mode 100644 test/tests-6to5.js diff --git a/README.md b/README.md index 7ea245540a..9d4902fc83 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ # acorn-6to5 -Based on [acorn-jsx](https://github.com/RReverser/acorn-jsx). +Deviates from [acorn](https://github.com/marijnh/acorn) in the following ways: + + * JSX support via [acorn-jsx](https://github.com/RReverser/acorn-jsx) + * [ES7 Abstract references](https://github.com/zenparsing/es-abstract-refs) + * [ES7 Async/await](https://github.com/lukehoban/ecmascript-asyncawait) + * [ES7 Object Rest/Spread](https://github.com/sebmarkbage/ecmascript-rest-spread) diff --git a/acorn.js b/acorn.js index ddb433f0b5..911bb7c356 100644 --- a/acorn.js +++ b/acorn.js @@ -1757,7 +1757,7 @@ node.type = "ObjectPattern"; for (var i = 0; i < node.properties.length; i++) { var prop = node.properties[i]; - if (prop.kind !== "init") unexpected(prop.key.start); + if (prop.type === "Property" && prop.kind !== "init") unexpected(prop.key.start); toAssignable(prop.value, false, checkType); } break; @@ -1865,8 +1865,11 @@ if (!isBinding) break; case "ObjectPattern": - for (var i = 0; i < expr.properties.length; i++) - checkLVal(expr.properties[i].value, isBinding); + for (var i = 0; i < expr.properties.length; i++) { + var prop = expr.properties[i]; + if (prop.type === "Property") prop = prop.value; + checkLVal(prop, isBinding); + } break; case "ArrayPattern": @@ -1876,6 +1879,7 @@ } break; + case "SpreadProperty": case "SpreadElement": case "VirtualPropertyExpression": break; @@ -2644,6 +2648,13 @@ prop.shorthand = false; isGenerator = eat(_star); } + if (options.ecmaVersion >= 7 && tokType === _ellipsis) { + if (isAsync || isGenerator) unexpected(); + prop = parseMaybeUnary(); + prop.type = "SpreadProperty"; + node.properties.push(prop); + continue; + } parsePropertyName(prop); if (eat(_colon)) { prop.value = parseExpression(true); diff --git a/package.json b/package.json index 14d8eb67ec..1eec6d666b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.9.1-4", + "version": "0.9.1-5", "maintainers": [ { "name": "Marijn Haverbeke", diff --git a/test/run.js b/test/run.js index f394353d1e..13809aa265 100644 --- a/test/run.js +++ b/test/run.js @@ -6,6 +6,7 @@ require("./tests.js"); require("./tests-harmony.js"); require("./tests-jsx.js"); + require("./tests-6to5.js"); } else { driver = window; } @@ -76,7 +77,7 @@ function report(state, code, message) { group(name); var mode = modes[name]; stats = mode.stats = {testsRun: 0, failed: 0}; -var t0 = +new Date; + var t0 = +new Date; driver.runTests(mode.config, report); mode.stats.duration = +new Date - t0; groupEnd(); diff --git a/test/tests-6to5.js b/test/tests-6to5.js new file mode 100644 index 0000000000..01691cdf12 --- /dev/null +++ b/test/tests-6to5.js @@ -0,0 +1,1591 @@ +if (typeof exports != "undefined") { + var test = require("./driver.js").test; + var testFail = require("./driver.js").testFail; + var testAssert = require("./driver.js").testAssert; +} + +// ES7: Object Rest/Spread + +test('let {...x} = z', { + type: "Program", + start: 0, + end: 14, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 14, + declarations: [ + { + type: "VariableDeclarator", + start: 4, + end: 14, + id: { + type: "ObjectPattern", + start: 4, + end: 10, + properties: [ + { + type: "SpreadProperty", + start: 5, + end: 9, + argument: { + type: "Identifier", + start: 8, + end: 9, + name: "x" + } + } + ] + }, + init: { + type: "Identifier", + start: 13, + end: 14, + name: "z" + } + } + ], + kind: "let" + }] +}, { + ecmaVersion: 7 +}); + +test('let {x, ...y} = z', { + type: "Program", + start: 0, + end: 17, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 17, + declarations: [ + { + type: "VariableDeclarator", + start: 4, + end: 17, + id: { + type: "ObjectPattern", + start: 4, + end: 13, + properties: [ + { + type: "Property", + start: 5, + end: 6, + method: false, + shorthand: true, + computed: false, + key: { + type: "Identifier", + start: 5, + end: 6, + name: "x" + }, + kind: "init", + value: { + type: "Identifier", + start: 5, + end: 6, + name: "x" + } + }, + { + type: "SpreadProperty", + start: 8, + end: 12, + argument: { + type: "Identifier", + start: 11, + end: 12, + name: "y" + } + } + ] + }, + init: { + type: "Identifier", + start: 16, + end: 17, + name: "z" + } + } + ], + kind: "let" + }] +}, { + ecmaVersion: 7 +}); + +test('(function({x, ...y}) { })', { + type: "Program", + start: 0, + end: 25, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 25, + expression: { + type: "FunctionExpression", + start: 1, + end: 24, + id: null, + params: [ + { + type: "ObjectPattern", + start: 10, + end: 19, + properties: [ + { + type: "Property", + start: 11, + end: 12, + method: false, + shorthand: true, + computed: false, + key: { + type: "Identifier", + start: 11, + end: 12, + name: "x" + }, + kind: "init", + value: { + type: "Identifier", + start: 11, + end: 12, + name: "x" + } + }, + { + type: "SpreadProperty", + start: 14, + end: 18, + argument: { + type: "Identifier", + start: 17, + end: 18, + name: "y" + } + } + ] + } + ], + defaults: [], + rest: null, + generator: false, + async: false, + body: { + type: "BlockStatement", + start: 21, + end: 24, + body: [] + }, + expression: false + } + }] +}, { + ecmaVersion: 7 +}); + +test('let z = {...x}', { + type: "Program", + start: 0, + end: 14, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 14, + declarations: [ + { + type: "VariableDeclarator", + start: 4, + end: 14, + id: { + type: "Identifier", + start: 4, + end: 5, + name: "z" + }, + init: { + type: "ObjectExpression", + start: 8, + end: 14, + properties: [ + { + type: "SpreadProperty", + start: 9, + end: 13, + argument: { + type: "Identifier", + start: 12, + end: 13, + name: "x" + } + } + ] + } + } + ], + kind: "let" + }] +}, { + ecmaVersion: 7 +}); + +test('z = {x, ...y}', { + type: "Program", + start: 0, + end: 13, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 13, + expression: { + type: "AssignmentExpression", + start: 0, + end: 13, + operator: "=", + left: { + type: "Identifier", + start: 0, + end: 1, + name: "z" + }, + right: { + type: "ObjectExpression", + start: 4, + end: 13, + properties: [ + { + type: "Property", + start: 5, + end: 6, + method: false, + shorthand: true, + computed: false, + key: { + type: "Identifier", + start: 5, + end: 6, + name: "x" + }, + kind: "init", + value: { + type: "Identifier", + start: 5, + end: 6, + name: "x" + } + }, + { + type: "SpreadProperty", + start: 8, + end: 12, + argument: { + type: "Identifier", + start: 11, + end: 12, + name: "y" + } + } + ] + } + } + }] +}, { + ecmaVersion: 7 +}); + +test('({x, ...y, a, ...b, c})', { + type: "Program", + start: 0, + end: 23, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 23, + expression: { + type: "ObjectExpression", + start: 1, + end: 22, + properties: [ + { + type: "Property", + start: 2, + end: 3, + method: false, + shorthand: true, + computed: false, + key: { + type: "Identifier", + start: 2, + end: 3, + name: "x" + }, + kind: "init", + value: { + type: "Identifier", + start: 2, + end: 3, + name: "x" + } + }, + { + type: "SpreadProperty", + start: 5, + end: 9, + argument: { + type: "Identifier", + start: 8, + end: 9, + name: "y" + } + }, + { + type: "Property", + start: 11, + end: 12, + method: false, + shorthand: true, + computed: false, + key: { + type: "Identifier", + start: 11, + end: 12, + name: "a" + }, + kind: "init", + value: { + type: "Identifier", + start: 11, + end: 12, + name: "a" + } + }, + { + type: "SpreadProperty", + start: 14, + end: 18, + argument: { + type: "Identifier", + start: 17, + end: 18, + name: "b" + } + }, + { + type: "Property", + start: 20, + end: 21, + method: false, + shorthand: true, + computed: false, + key: { + type: "Identifier", + start: 20, + end: 21, + name: "c" + }, + kind: "init", + value: { + type: "Identifier", + start: 20, + end: 21, + name: "c" + } + } + ] + } + }] +}, { + ecmaVersion: 7 +}); + +// ES7: Async Functions + +test('async function foo(promise) { await promise; }', { + type: "Program", + body: [{ + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + loc: { + start: {line: 1, column: 15}, + end: {line: 1, column: 18} + } + }, + params: [{ + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 19}, + end: {line: 1, column: 26} + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [{ + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 36}, + end: {line: 1, column: 43} + } + }, + loc: { + start: {line: 1, column: 30}, + end: {line: 1, column: 43} + } + }, + loc: { + start: {line: 1, column: 30}, + end: {line: 1, column: 44} + } + }], + loc: { + start: {line: 1, column: 28}, + end: {line: 1, column: 46} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 46} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('(function(x) { async function inner() { await x } })', { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "x", + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 11} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "inner", + loc: { + start: {line: 1, column: 30}, + end: {line: 1, column: 35} + } + }, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "x", + loc: { + start: {line: 1, column: 46}, + end: {line: 1, column: 47} + } + }, + loc: { + start: {line: 1, column: 40}, + end: {line: 1, column: 47} + } + }, + loc: { + start: {line: 1, column: 40}, + end: {line: 1, column: 47} + } + } + ], + loc: { + start: {line: 1, column: 38}, + end: {line: 1, column: 49} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 15}, + end: {line: 1, column: 49} + } + } + ], + loc: { + start: {line: 1, column: 13}, + end: {line: 1, column: 51} + } + }, + rest: null, + generator: false, + expression: false, + loc: { + start: {line: 1, column: 1}, + end: {line: 1, column: 51} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 52} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('var foo = async function(promise) { await promise; }', { + type: "Program", + body: [{ + type: "VariableDeclaration", + declarations: [ + { + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "foo", + loc: { + start: {line: 1, column: 4}, + end: {line: 1, column: 7} + } + }, + init: { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 25}, + end: {line: 1, column: 32} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 42}, + end: {line: 1, column: 49} + } + }, + loc: { + start: {line: 1, column: 36}, + end: {line: 1, column: 49} + } + }, + loc: { + start: {line: 1, column: 36}, + end: {line: 1, column: 50} + } + } + ], + loc: { + start: {line: 1, column: 34}, + end: {line: 1, column: 52} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 52} + } + }, + loc: { + start: {line: 1, column: 4}, + end: {line: 1, column: 52} + } + } + ], + kind: "var", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 52} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('var o = { a: 1, async foo(promise) { await promise } }', { + type: "Program", + body: [{ + type: "VariableDeclaration", + declarations: [ + { + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "o", + loc: { + start: {line: 1, column: 4}, + end: {line: 1, column: 5} + } + }, + init: { + type: "ObjectExpression", + properties: [ + { + type: "Property", + key: { + type: "Identifier", + name: "a", + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 11} + } + }, + value: { + type: "Literal", + value: 1, + loc: { + start: {line: 1, column: 13}, + end: {line: 1, column: 14} + } + }, + kind: "init", + method: false, + shorthand: false, + computed: false, + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 14} + } + }, + { + type: "Property", + key: { + type: "Identifier", + name: "foo", + loc: { + start: {line: 1, column: 22}, + end: {line: 1, column: 25} + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 26}, + end: {line: 1, column: 33} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 43}, + end: {line: 1, column: 50} + } + }, + loc: { + start: {line: 1, column: 37}, + end: {line: 1, column: 50} + } + }, + loc: { + start: {line: 1, column: 37}, + end: {line: 1, column: 50} + } + } + ], + loc: { + start: {line: 1, column: 35}, + end: {line: 1, column: 52} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 25}, + end: {line: 1, column: 52} + } + }, + kind: "init", + method: true, + shorthand: false, + computed: false, + loc: { + start: {line: 1, column: 16}, + end: {line: 1, column: 52} + } + } + ], + loc: { + start: {line: 1, column: 8}, + end: {line: 1, column: 54} + } + }, + loc: { + start: {line: 1, column: 4}, + end: {line: 1, column: 54} + } + } + ], + kind: "var", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 54} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('class Foo { async bar(promise) { await promise } }', { + type: "Program", + body: [{ + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + loc: { + start: {line: 1, column: 6}, + end: {line: 1, column: 9} + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [ + { + type: "MethodDefinition", + key: { + type: "Identifier", + name: "bar", + loc: { + start: {line: 1, column: 18}, + end: {line: 1, column: 21} + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 22}, + end: {line: 1, column: 29} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 39}, + end: {line: 1, column: 46} + } + }, + loc: { + start: {line: 1, column: 33}, + end: {line: 1, column: 46} + } + }, + loc: { + start: {line: 1, column: 33}, + end: {line: 1, column: 46} + } + } + ], + loc: { + start: {line: 1, column: 31}, + end: {line: 1, column: 48} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 21}, + end: {line: 1, column: 48} + } + }, + kind: "", + static: false, + loc: { + start: {line: 1, column: 12}, + end: {line: 1, column: 48} + } + } + ], + loc: { + start: {line: 1, column: 10}, + end: {line: 1, column: 50} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 50} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('f(a, async promise => await promise)', { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "f", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 1} + } + }, + arguments: [ + { + type: "Identifier", + name: "a", + loc: { + start: {line: 1, column: 2}, + end: {line: 1, column: 3} + } + }, + { + type: "ArrowFunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 11}, + end: {line: 1, column: 18} + } + } + ], + defaults: [], + body: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 28}, + end: {line: 1, column: 35} + } + }, + loc: { + start: {line: 1, column: 22}, + end: {line: 1, column: 35} + } + }, + rest: null, + generator: false, + expression: true, + async: true, + loc: { + start: {line: 1, column: 5}, + end: {line: 1, column: 35} + } + } + ], + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 36} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 36} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('f(a, async(x, y) => await [x, y], b)', { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "f", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 1} + } + }, + arguments: [ + { + type: "Identifier", + name: "a", + loc: { + start: {line: 1, column: 2}, + end: {line: 1, column: 3} + } + }, + { + type: "ArrowFunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "x", + loc: { + start: {line: 1, column: 11}, + end: {line: 1, column: 12} + } + }, + { + type: "Identifier", + name: "y", + loc: { + start: {line: 1, column: 14}, + end: {line: 1, column: 15} + } + } + ], + defaults: [], + body: { + type: "AwaitExpression", + argument: { + type: "ArrayExpression", + elements: [ + { + type: "Identifier", + name: "x", + loc: { + start: {line: 1, column: 27}, + end: {line: 1, column: 28} + } + }, + { + type: "Identifier", + name: "y", + loc: { + start: {line: 1, column: 30}, + end: {line: 1, column: 31} + } + } + ], + loc: { + start: {line: 1, column: 26}, + end: {line: 1, column: 32} + } + }, + loc: { + start: {line: 1, column: 20}, + end: {line: 1, column: 32} + } + }, + rest: null, + generator: false, + expression: true, + async: true, + loc: { + start: {line: 1, column: 5}, + end: {line: 1, column: 32} + } + }, + { + type: "Identifier", + name: "b", + loc: { + start: {line: 1, column: 34}, + end: {line: 1, column: 35} + } + } + ], + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 36} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 36} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test('f(async function(promise) { await promise })', { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "f", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 1} + } + }, + arguments: [ + { + type: "FunctionExpression", + id: null, + params: [ + { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 17}, + end: {line: 1, column: 24} + } + } + ], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "Identifier", + name: "promise", + loc: { + start: {line: 1, column: 34}, + end: {line: 1, column: 41} + } + }, + loc: { + start: {line: 1, column: 28}, + end: {line: 1, column: 41} + } + }, + loc: { + start: {line: 1, column: 28}, + end: {line: 1, column: 41} + } + } + ], + loc: { + start: {line: 1, column: 26}, + end: {line: 1, column: 43} + } + }, + rest: null, + generator: false, + expression: false, + async: true, + loc: { + start: {line: 1, column: 2}, + end: {line: 1, column: 43} + } + } + ], + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 44} + } + }, + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 44} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test("f(a, async(1, 2), b);", { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "f", + loc: { + start: {line: 1, column: 0}, + end: {line: 1, column: 1} + } + }, + arguments: [ + { + type: "Identifier", + name: "a", + loc: { + start: {line: 1, column: 2}, + end: {line: 1, column: 3} + } + }, + { + type: "CallExpression", + callee: { + type: "Identifier", + name: "async", + loc: { + start: {line: 1, column: 5}, + end: {line: 1, column: 10} + } + }, + arguments: [ + { + type: "Literal", + value: 1, + loc: { + start: {line: 1,column: 11}, + end: {line: 1,column: 12} + } + }, + { + type: "Literal", + value: 2, + loc: { + start: {line: 1,column: 14}, + end: {line: 1,column: 15} + } + } + ], + loc: { + start: {line: 1,column: 5}, + end: {line: 1,column: 16} + } + }, + { + type: "Identifier", + name: "b", + loc: { + start: {line: 1,column: 18}, + end: {line: 1,column: 19} + } + } + ], + loc: { + start: {line: 1,column: 0}, + end: {line: 1,column: 20} + } + }, + loc: { + start: {line: 1,column: 0}, + end: {line: 1,column: 20} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test("var ok = async(x);", { + type: "Program", + body: [{ + type: "VariableDeclaration", + declarations: [ + { + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "ok", + loc: { + start: {line: 1,column: 4}, + end: {line: 1,column: 6} + } + }, + init: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "async", + loc: { + start: {line: 1,column: 9}, + end: {line: 1,column: 14} + } + }, + arguments: [ + { + type: "Identifier", + name: "x", + loc: { + start: {line: 1,column: 15}, + end: {line: 1,column: 16} + } + } + ], + loc: { + start: {line: 1,column: 9}, + end: {line: 1,column: 17} + } + }, + loc: { + start: {line: 1,column: 4}, + end: {line: 1,column: 17} + } + } + ], + kind: "var", + loc: { + start: {line: 1,column: 0}, + end: {line: 1,column: 17} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +test("var async; async = 10;", { + type: "Program", + body: [{ + type: "ExpressionStatement", + expression: { + type: "FunctionExpression", + id: null, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [ + { + type: "VariableDeclaration", + declarations: [ + { + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "async", + loc: { + start: {line: 1,column: 18}, + end: {line: 1,column: 23} + } + }, + init: null, + loc: { + start: {line: 1,column: 18}, + end: {line: 1,column: 23} + } + } + ], + kind: "var", + loc: { + start: {line: 1,column: 14}, + end: {line: 1,column: 24} + } + }, + { + type: "ExpressionStatement", + expression: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "Identifier", + name: "async", + loc: { + start: {line: 1,column: 25}, + end: {line: 1,column: 30} + } + }, + right: { + type: "Literal", + value: 10, + loc: { + start: {line: 1,column: 33}, + end: {line: 1,column: 35} + } + }, + loc: { + start: {line: 1,column: 25}, + end: {line: 1,column: 35} + } + }, + loc: { + start: {line: 1,column: 25}, + end: {line: 1,column: 36} + } + } + ], + loc: { + start: {line: 1,column: 12}, + end: {line: 1,column: 37} + } + }, + rest: null, + generator: false, + expression: false, + loc: { + start: {line: 1,column: 1}, + end: {line: 1,column: 37} + } + }, + loc: { + start: {line: 1,column: 0}, + end: {line: 1,column: 38} + } + }] +}, { + ecmaVersion: 7, + locations: true +}); + +// ES7: Abstract references + +test('foo::bar;', { + type: "Program", + start: 0, + end: 9, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 9, + expression: { + type: "VirtualPropertyExpression", + start: 0, + end: 8, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "foo" + }, + property: { + type: "Identifier", + start: 5, + end: 8, + name: "bar" + } + } + }] +}, { + ecmaVersion: 7 +}); + +test('foo::bar::baz;', { + type: "Program", + start: 0, + end: 14, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 14, + expression: { + type: "VirtualPropertyExpression", + start: 0, + end: 13, + object: { + type: "VirtualPropertyExpression", + start: 0, + end: 8, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "foo" + }, + property: { + type: "Identifier", + start: 5, + end: 8, + name: "bar" + } + }, + property: { + type: "Identifier", + start: 10, + end: 13, + name: "baz" + } + } + }] +}, { + ecmaVersion: 7 +}); + +test('foo::baz();', { + type: "Program", + start: 0, + end: 11, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 11, + expression: { + type: "CallExpression", + start: 0, + end: 10, + callee: { + type: "VirtualPropertyExpression", + start: 0, + end: 8, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "foo" + }, + property: { + type: "Identifier", + start: 5, + end: 8, + name: "baz" + } + }, + arguments: [] + } + }] +}, { + ecmaVersion: 7 +}); + +test('foo::bar = "baz";', { + type: "Program", + start: 0, + end: 17, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 17, + expression: { + type: "AssignmentExpression", + start: 0, + end: 16, + operator: "=", + left: { + type: "VirtualPropertyExpression", + start: 0, + end: 8, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "foo" + }, + property: { + type: "Identifier", + start: 5, + end: 8, + name: "bar" + } + }, + right: { + type: "Literal", + start: 11, + end: 16, + value: "baz" + } + } + }] +}, { + ecmaVersion: 7 +}); + +test('delete foo::bar;', { + type: "Program", + start: 0, + end: 16, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 16, + expression: { + type: "UnaryExpression", + start: 0, + end: 15, + operator: "delete", + prefix: true, + argument: { + type: "VirtualPropertyExpression", + start: 7, + end: 15, + object: { + type: "Identifier", + start: 7, + end: 10, + name: "foo" + }, + property: { + type: "Identifier", + start: 12, + end: 15, + name: "bar" + } + } + } + }] +}, { + ecmaVersion: 7 +}); + + +testFail("function foo(promise) { await promise; }", "Unexpected token (1:30)", {ecmaVersion: 7}); + +testFail("async function* foo(promise) { await promise; }", "Unexpected token (1:14)", {ecmaVersion: 7}); diff --git a/test/tests-harmony.js b/test/tests-harmony.js index c3c080673a..f5064c8a94 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -13605,1189 +13605,6 @@ test("/[a-z]/u", { ecmaVersion: 6 }); -// ES7: Abstract references - -test('foo::bar;', { - type: "Program", - start: 0, - end: 9, - body: [{ - type: "ExpressionStatement", - start: 0, - end: 9, - expression: { - type: "VirtualPropertyExpression", - start: 0, - end: 8, - object: { - type: "Identifier", - start: 0, - end: 3, - name: "foo" - }, - property: { - type: "Identifier", - start: 5, - end: 8, - name: "bar" - } - } - }] -}, { - ecmaVersion: 7 -}); - -test('foo::bar::baz;', { - type: "Program", - start: 0, - end: 14, - body: [{ - type: "ExpressionStatement", - start: 0, - end: 14, - expression: { - type: "VirtualPropertyExpression", - start: 0, - end: 13, - object: { - type: "VirtualPropertyExpression", - start: 0, - end: 8, - object: { - type: "Identifier", - start: 0, - end: 3, - name: "foo" - }, - property: { - type: "Identifier", - start: 5, - end: 8, - name: "bar" - } - }, - property: { - type: "Identifier", - start: 10, - end: 13, - name: "baz" - } - } - }] -}, { - ecmaVersion: 7 -}); - -test('foo::baz();', { - type: "Program", - start: 0, - end: 11, - body: [{ - type: "ExpressionStatement", - start: 0, - end: 11, - expression: { - type: "CallExpression", - start: 0, - end: 10, - callee: { - type: "VirtualPropertyExpression", - start: 0, - end: 8, - object: { - type: "Identifier", - start: 0, - end: 3, - name: "foo" - }, - property: { - type: "Identifier", - start: 5, - end: 8, - name: "baz" - } - }, - arguments: [] - } - }] -}, { - ecmaVersion: 7 -}); - -test('foo::bar = "baz";', { - type: "Program", - start: 0, - end: 17, - body: [{ - type: "ExpressionStatement", - start: 0, - end: 17, - expression: { - type: "AssignmentExpression", - start: 0, - end: 16, - operator: "=", - left: { - type: "VirtualPropertyExpression", - start: 0, - end: 8, - object: { - type: "Identifier", - start: 0, - end: 3, - name: "foo" - }, - property: { - type: "Identifier", - start: 5, - end: 8, - name: "bar" - } - }, - right: { - type: "Literal", - start: 11, - end: 16, - value: "baz" - } - } - }] -}, { - ecmaVersion: 7 -}); - -test('delete foo::bar;', { - type: "Program", - start: 0, - end: 16, - body: [{ - type: "ExpressionStatement", - start: 0, - end: 16, - expression: { - type: "UnaryExpression", - start: 0, - end: 15, - operator: "delete", - prefix: true, - argument: { - type: "VirtualPropertyExpression", - start: 7, - end: 15, - object: { - type: "Identifier", - start: 7, - end: 10, - name: "foo" - }, - property: { - type: "Identifier", - start: 12, - end: 15, - name: "bar" - } - } - } - }] -}, { - ecmaVersion: 7 -}); - -// ES7: Async Functions - -test('async function foo(promise) { await promise; }', { - type: "Program", - body: [{ - type: "FunctionDeclaration", - id: { - type: "Identifier", - name: "foo", - loc: { - start: {line: 1, column: 15}, - end: {line: 1, column: 18} - } - }, - params: [{ - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 19}, - end: {line: 1, column: 26} - } - }], - defaults: [], - body: { - type: "BlockStatement", - body: [{ - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 36}, - end: {line: 1, column: 43} - } - }, - loc: { - start: {line: 1, column: 30}, - end: {line: 1, column: 43} - } - }, - loc: { - start: {line: 1, column: 30}, - end: {line: 1, column: 44} - } - }], - loc: { - start: {line: 1, column: 28}, - end: {line: 1, column: 46} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 46} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('(function(x) { async function inner() { await x } })', { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "x", - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 11} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "FunctionDeclaration", - id: { - type: "Identifier", - name: "inner", - loc: { - start: {line: 1, column: 30}, - end: {line: 1, column: 35} - } - }, - params: [], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "x", - loc: { - start: {line: 1, column: 46}, - end: {line: 1, column: 47} - } - }, - loc: { - start: {line: 1, column: 40}, - end: {line: 1, column: 47} - } - }, - loc: { - start: {line: 1, column: 40}, - end: {line: 1, column: 47} - } - } - ], - loc: { - start: {line: 1, column: 38}, - end: {line: 1, column: 49} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 15}, - end: {line: 1, column: 49} - } - } - ], - loc: { - start: {line: 1, column: 13}, - end: {line: 1, column: 51} - } - }, - rest: null, - generator: false, - expression: false, - loc: { - start: {line: 1, column: 1}, - end: {line: 1, column: 51} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 52} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('var foo = async function(promise) { await promise; }', { - type: "Program", - body: [{ - type: "VariableDeclaration", - declarations: [ - { - type: "VariableDeclarator", - id: { - type: "Identifier", - name: "foo", - loc: { - start: {line: 1, column: 4}, - end: {line: 1, column: 7} - } - }, - init: { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 25}, - end: {line: 1, column: 32} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 42}, - end: {line: 1, column: 49} - } - }, - loc: { - start: {line: 1, column: 36}, - end: {line: 1, column: 49} - } - }, - loc: { - start: {line: 1, column: 36}, - end: {line: 1, column: 50} - } - } - ], - loc: { - start: {line: 1, column: 34}, - end: {line: 1, column: 52} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 52} - } - }, - loc: { - start: {line: 1, column: 4}, - end: {line: 1, column: 52} - } - } - ], - kind: "var", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 52} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('var o = { a: 1, async foo(promise) { await promise } }', { - type: "Program", - body: [{ - type: "VariableDeclaration", - declarations: [ - { - type: "VariableDeclarator", - id: { - type: "Identifier", - name: "o", - loc: { - start: {line: 1, column: 4}, - end: {line: 1, column: 5} - } - }, - init: { - type: "ObjectExpression", - properties: [ - { - type: "Property", - key: { - type: "Identifier", - name: "a", - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 11} - } - }, - value: { - type: "Literal", - value: 1, - loc: { - start: {line: 1, column: 13}, - end: {line: 1, column: 14} - } - }, - kind: "init", - method: false, - shorthand: false, - computed: false, - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 14} - } - }, - { - type: "Property", - key: { - type: "Identifier", - name: "foo", - loc: { - start: {line: 1, column: 22}, - end: {line: 1, column: 25} - } - }, - value: { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 26}, - end: {line: 1, column: 33} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 43}, - end: {line: 1, column: 50} - } - }, - loc: { - start: {line: 1, column: 37}, - end: {line: 1, column: 50} - } - }, - loc: { - start: {line: 1, column: 37}, - end: {line: 1, column: 50} - } - } - ], - loc: { - start: {line: 1, column: 35}, - end: {line: 1, column: 52} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 25}, - end: {line: 1, column: 52} - } - }, - kind: "init", - method: true, - shorthand: false, - computed: false, - loc: { - start: {line: 1, column: 16}, - end: {line: 1, column: 52} - } - } - ], - loc: { - start: {line: 1, column: 8}, - end: {line: 1, column: 54} - } - }, - loc: { - start: {line: 1, column: 4}, - end: {line: 1, column: 54} - } - } - ], - kind: "var", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 54} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('class Foo { async bar(promise) { await promise } }', { - type: "Program", - body: [{ - type: "ClassDeclaration", - id: { - type: "Identifier", - name: "Foo", - loc: { - start: {line: 1, column: 6}, - end: {line: 1, column: 9} - } - }, - superClass: null, - body: { - type: "ClassBody", - body: [ - { - type: "MethodDefinition", - key: { - type: "Identifier", - name: "bar", - loc: { - start: {line: 1, column: 18}, - end: {line: 1, column: 21} - } - }, - value: { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 22}, - end: {line: 1, column: 29} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 39}, - end: {line: 1, column: 46} - } - }, - loc: { - start: {line: 1, column: 33}, - end: {line: 1, column: 46} - } - }, - loc: { - start: {line: 1, column: 33}, - end: {line: 1, column: 46} - } - } - ], - loc: { - start: {line: 1, column: 31}, - end: {line: 1, column: 48} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 21}, - end: {line: 1, column: 48} - } - }, - kind: "", - static: false, - loc: { - start: {line: 1, column: 12}, - end: {line: 1, column: 48} - } - } - ], - loc: { - start: {line: 1, column: 10}, - end: {line: 1, column: 50} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 50} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('f(a, async promise => await promise)', { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "CallExpression", - callee: { - type: "Identifier", - name: "f", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 1} - } - }, - arguments: [ - { - type: "Identifier", - name: "a", - loc: { - start: {line: 1, column: 2}, - end: {line: 1, column: 3} - } - }, - { - type: "ArrowFunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 11}, - end: {line: 1, column: 18} - } - } - ], - defaults: [], - body: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 28}, - end: {line: 1, column: 35} - } - }, - loc: { - start: {line: 1, column: 22}, - end: {line: 1, column: 35} - } - }, - rest: null, - generator: false, - expression: true, - async: true, - loc: { - start: {line: 1, column: 5}, - end: {line: 1, column: 35} - } - } - ], - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 36} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 36} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('f(a, async(x, y) => await [x, y], b)', { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "CallExpression", - callee: { - type: "Identifier", - name: "f", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 1} - } - }, - arguments: [ - { - type: "Identifier", - name: "a", - loc: { - start: {line: 1, column: 2}, - end: {line: 1, column: 3} - } - }, - { - type: "ArrowFunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "x", - loc: { - start: {line: 1, column: 11}, - end: {line: 1, column: 12} - } - }, - { - type: "Identifier", - name: "y", - loc: { - start: {line: 1, column: 14}, - end: {line: 1, column: 15} - } - } - ], - defaults: [], - body: { - type: "AwaitExpression", - argument: { - type: "ArrayExpression", - elements: [ - { - type: "Identifier", - name: "x", - loc: { - start: {line: 1, column: 27}, - end: {line: 1, column: 28} - } - }, - { - type: "Identifier", - name: "y", - loc: { - start: {line: 1, column: 30}, - end: {line: 1, column: 31} - } - } - ], - loc: { - start: {line: 1, column: 26}, - end: {line: 1, column: 32} - } - }, - loc: { - start: {line: 1, column: 20}, - end: {line: 1, column: 32} - } - }, - rest: null, - generator: false, - expression: true, - async: true, - loc: { - start: {line: 1, column: 5}, - end: {line: 1, column: 32} - } - }, - { - type: "Identifier", - name: "b", - loc: { - start: {line: 1, column: 34}, - end: {line: 1, column: 35} - } - } - ], - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 36} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 36} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test('f(async function(promise) { await promise })', { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "CallExpression", - callee: { - type: "Identifier", - name: "f", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 1} - } - }, - arguments: [ - { - type: "FunctionExpression", - id: null, - params: [ - { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 17}, - end: {line: 1, column: 24} - } - } - ], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "AwaitExpression", - argument: { - type: "Identifier", - name: "promise", - loc: { - start: {line: 1, column: 34}, - end: {line: 1, column: 41} - } - }, - loc: { - start: {line: 1, column: 28}, - end: {line: 1, column: 41} - } - }, - loc: { - start: {line: 1, column: 28}, - end: {line: 1, column: 41} - } - } - ], - loc: { - start: {line: 1, column: 26}, - end: {line: 1, column: 43} - } - }, - rest: null, - generator: false, - expression: false, - async: true, - loc: { - start: {line: 1, column: 2}, - end: {line: 1, column: 43} - } - } - ], - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 44} - } - }, - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 44} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test("f(a, async(1, 2), b);", { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "CallExpression", - callee: { - type: "Identifier", - name: "f", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 1} - } - }, - arguments: [ - { - type: "Identifier", - name: "a", - loc: { - start: {line: 1, column: 2}, - end: {line: 1, column: 3} - } - }, - { - type: "CallExpression", - callee: { - type: "Identifier", - name: "async", - loc: { - start: {line: 1, column: 5}, - end: {line: 1, column: 10} - } - }, - arguments: [ - { - type: "Literal", - value: 1, - loc: { - start: {line: 1,column: 11}, - end: {line: 1,column: 12} - } - }, - { - type: "Literal", - value: 2, - loc: { - start: {line: 1,column: 14}, - end: {line: 1,column: 15} - } - } - ], - loc: { - start: {line: 1,column: 5}, - end: {line: 1,column: 16} - } - }, - { - type: "Identifier", - name: "b", - loc: { - start: {line: 1,column: 18}, - end: {line: 1,column: 19} - } - } - ], - loc: { - start: {line: 1,column: 0}, - end: {line: 1,column: 20} - } - }, - loc: { - start: {line: 1,column: 0}, - end: {line: 1,column: 20} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test("var ok = async(x);", { - type: "Program", - body: [{ - type: "VariableDeclaration", - declarations: [ - { - type: "VariableDeclarator", - id: { - type: "Identifier", - name: "ok", - loc: { - start: {line: 1,column: 4}, - end: {line: 1,column: 6} - } - }, - init: { - type: "CallExpression", - callee: { - type: "Identifier", - name: "async", - loc: { - start: {line: 1,column: 9}, - end: {line: 1,column: 14} - } - }, - arguments: [ - { - type: "Identifier", - name: "x", - loc: { - start: {line: 1,column: 15}, - end: {line: 1,column: 16} - } - } - ], - loc: { - start: {line: 1,column: 9}, - end: {line: 1,column: 17} - } - }, - loc: { - start: {line: 1,column: 4}, - end: {line: 1,column: 17} - } - } - ], - kind: "var", - loc: { - start: {line: 1,column: 0}, - end: {line: 1,column: 17} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test("var async; async = 10;", { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "FunctionExpression", - id: null, - params: [], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "VariableDeclaration", - declarations: [ - { - type: "VariableDeclarator", - id: { - type: "Identifier", - name: "async", - loc: { - start: {line: 1,column: 18}, - end: {line: 1,column: 23} - } - }, - init: null, - loc: { - start: {line: 1,column: 18}, - end: {line: 1,column: 23} - } - } - ], - kind: "var", - loc: { - start: {line: 1,column: 14}, - end: {line: 1,column: 24} - } - }, - { - type: "ExpressionStatement", - expression: { - type: "AssignmentExpression", - operator: "=", - left: { - type: "Identifier", - name: "async", - loc: { - start: {line: 1,column: 25}, - end: {line: 1,column: 30} - } - }, - right: { - type: "Literal", - value: 10, - loc: { - start: {line: 1,column: 33}, - end: {line: 1,column: 35} - } - }, - loc: { - start: {line: 1,column: 25}, - end: {line: 1,column: 35} - } - }, - loc: { - start: {line: 1,column: 25}, - end: {line: 1,column: 36} - } - } - ], - loc: { - start: {line: 1,column: 12}, - end: {line: 1,column: 37} - } - }, - rest: null, - generator: false, - expression: false, - loc: { - start: {line: 1,column: 1}, - end: {line: 1,column: 37} - } - }, - loc: { - start: {line: 1,column: 0}, - end: {line: 1,column: 38} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - // Harmony Invalid syntax testFail("0o", "Expected number in radix 8 (1:2)", {ecmaVersion: 6}); @@ -14900,10 +13717,6 @@ testFail("(10) => 00", "Unexpected token (1:1)", {ecmaVersion: 6}); testFail("(10, 20) => 00", "Unexpected token (1:1)", {ecmaVersion: 6}); -testFail("function foo(promise) { await promise; }", "Unexpected token (1:30)", {ecmaVersion: 7}); - -testFail("async function* foo(promise) { await promise; }", "Unexpected token (1:14)", {ecmaVersion: 7}); - testFail("yield v", "Unexpected token (1:6)", {ecmaVersion: 6}); testFail("yield 10", "Unexpected token (1:6)", {ecmaVersion: 6}); From f8ee0c306614b7da9279279e132724c751a28fd5 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 23 Nov 2014 21:45:56 +1100 Subject: [PATCH 067/198] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1eec6d666b..d125ff7f61 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.9.1-5", + "version": "0.9.1-6", "maintainers": [ { "name": "Marijn Haverbeke", From f9c642e2c5ecabe2700c20b1bfb036a92b6715f8 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 23 Nov 2014 22:56:24 +1100 Subject: [PATCH 068/198] add support for ES7 exponentiation operator --- README.md | 3 +- acorn.js | 33 +++++++++++++++++--- package.json | 2 +- test/tests-6to5.js | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9d4902fc83..4e5a45e1fa 100644 --- a/README.md +++ b/README.md @@ -5,4 +5,5 @@ Deviates from [acorn](https://github.com/marijnh/acorn) in the following ways: * JSX support via [acorn-jsx](https://github.com/RReverser/acorn-jsx) * [ES7 Abstract references](https://github.com/zenparsing/es-abstract-refs) * [ES7 Async/await](https://github.com/lukehoban/ecmascript-asyncawait) - * [ES7 Object Rest/Spread](https://github.com/sebmarkbage/ecmascript-rest-spread) + * [ES7 Exponentiation operator](https://github.com/rwaldron/exponentiation-operator) + * [ES7 Object rest/spread](https://github.com/sebmarkbage/ecmascript-rest-spread) diff --git a/acorn.js b/acorn.js index 911bb7c356..19bf0b0b08 100644 --- a/acorn.js +++ b/acorn.js @@ -462,6 +462,7 @@ // '*' may be multiply or have special meaning in ES6 var _star = {binop: 10, beforeExpr: true}; + var _exponent = {binop: 10, beforeExpr: true}; // '<', '>' may be relational or have special meaning in JSX var _lt = {binop: 7, beforeExpr: true}, _gt = {binop: 7, beforeExpr: true}; @@ -475,7 +476,7 @@ name: _name, eof: _eof, num: _num, regexp: _regexp, string: _string, arrow: _arrow, bquote: _bquote, dollarBraceL: _dollarBraceL, star: _star, assign: _assign, xjsName: _xjsName, xjsText: _xjsText, - doubleColon: _doubleColon}; + doubleColon: _doubleColon, exponent: _exponent}; for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw]; // This is a trick taken from Esprima. It turns out that, on @@ -751,10 +752,29 @@ return finishOp(_slash, 1); } - function readToken_mult_modulo(code) { // '%*' + function readToken_modulo() { // '%' var next = input.charCodeAt(tokPos + 1); if (next === 61) return finishOp(_assign, 2); - return finishOp(code === 42 ? _star : _modulo, 1); + return finishOp(_modulo, 1); + } + + function readToken_mult() { // '*' + var type = _star; + var width = 1; + var next = input.charCodeAt(tokPos + 1); + + if (options.ecmaVersion >= 7 && next === 42) { // '*' + width++; + next = input.charCodeAt(tokPos + 2); + type = _exponent; + } + + if (next === 61) { // '=' + width++; + type = _assign; + } + + return finishOp(type, width); } function readToken_pipe_amp(code) { // '|&' @@ -907,8 +927,11 @@ case 47: // '/' return readToken_slash(); - case 37: case 42: // '%*' - return readToken_mult_modulo(code); + case 37: // '%' + return readToken_modulo(); + + case 42: // '*' + return readToken_mult(); case 124: case 38: // '|&' return readToken_pipe_amp(code); diff --git a/package.json b/package.json index d125ff7f61..6a707fd72e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.9.1-6", + "version": "0.9.1-7", "maintainers": [ { "name": "Marijn Haverbeke", diff --git a/test/tests-6to5.js b/test/tests-6to5.js index 01691cdf12..6ce7d4f733 100644 --- a/test/tests-6to5.js +++ b/test/tests-6to5.js @@ -4,6 +4,82 @@ if (typeof exports != "undefined") { var testAssert = require("./driver.js").testAssert; } +// ES7: Exponentiation Operator + +test('a **= 2;', { + type: "Program", + start: 0, + end: 8, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 8, + expression: { + type: "AssignmentExpression", + start: 0, + end: 7, + operator: "**=", + left: { + type: "Identifier", + start: 0, + end: 1, + name: "a" + }, + right: { + type: "Literal", + start: 6, + end: 7, + value: 2 + } + } + }] +}, { + ecmaVersion: 7 +}); + +test('var squared = 2 ** 2;', { + type: "Program", + start: 0, + end: 21, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 21, + declarations: [{ + type: "VariableDeclarator", + start: 4, + end: 20, + id: { + type: "Identifier", + start: 4, + end: 11, + name: "squared" + }, + init: { + type: "BinaryExpression", + start: 14, + end: 20, + left: { + type: "Literal", + start: 14, + end: 15, + value: 2 + }, + operator: "**", + right: { + type: "Literal", + start: 19, + end: 20, + value: 2 + } + } + }], + kind: "var" + }] +}, { + ecmaVersion: 7 +}); + // ES7: Object Rest/Spread test('let {...x} = z', { From 33d50820435b771f62c9cec4ece4b44e5d59d572 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sun, 23 Nov 2014 14:06:13 +0200 Subject: [PATCH 069/198] Parse `import Thing ...` in the same way as `import {default as Thing} ...`. Adjusts with Reflect.parse output and simplifies handling of "default" case in external tools by providing regular named ImportSpecifier. --- acorn.js | 10 +++++----- acorn_loose.js | 7 ++++--- test/tests-harmony.js | 29 ++++++++++++++++++++++------- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/acorn.js b/acorn.js index daa502ae16..3055cc9aa0 100644 --- a/acorn.js +++ b/acorn.js @@ -2541,7 +2541,6 @@ if (tokType === _string) { node.specifiers = []; node.source = parseExprAtom(); - node.kind = ""; } else { node.specifiers = parseImportSpecifiers(); if (tokType !== _name || tokVal !== "from") unexpected(); @@ -2559,10 +2558,11 @@ if (tokType === _name) { // import defaultObj, { x, y as z } from '...' var node = startNode(); - node.id = parseIdent(); - checkLVal(node.id, true); - node.name = null; - node['default'] = true; + node.id = startNode(); + node.name = parseIdent(); + checkLVal(node.name, true); + node.id.name = "default"; + finishNode(node.id, "Identifier"); nodes.push(finishNode(node, "ImportSpecifier")); if (!eat(_comma)) return nodes; } diff --git a/acorn_loose.js b/acorn_loose.js index 649aec6241..4be08176f7 100644 --- a/acorn_loose.js +++ b/acorn_loose.js @@ -1016,9 +1016,10 @@ } else { if (token.type === tt.name && token.value !== "from") { var elt = startNode(); - elt.id = parseIdent(); - elt.name = null; - elt['default'] = true; + elt.id = startNode(); + elt.name = parseIdent(); + elt.id.name = "default"; + finishNode(elt.id, "Identifier"); finishNode(elt, "ImportSpecifier"); eat(tt.comma); } diff --git a/test/tests-harmony.js b/test/tests-harmony.js index 15e3b98545..bf11776e4a 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -5153,6 +5153,14 @@ test("import $ from \"jquery\"", { specifiers: [{ type: "ImportSpecifier", id: { + type: "Identifier", + name: "default", + loc: { + start: {line: 1, column: 7}, + end: {line: 1, column: 8} + } + }, + name: { type: "Identifier", name: "$", loc: { @@ -5160,7 +5168,6 @@ test("import $ from \"jquery\"", { end: {line: 1, column: 8} } }, - name: null, loc: { start: {line: 1, column: 7}, end: {line: 1, column: 8} @@ -5328,10 +5335,16 @@ test("import crypto, { decrypt, encrypt as enc } from \"crypto\"", { start: {line: 1, column: 7}, end: {line: 1, column: 13} }, - name: "crypto" + name: "default" }, - name: null, - default: true + name: { + type: "Identifier", + loc: { + start: {line: 1, column: 7}, + end: {line: 1, column: 13} + }, + name: "crypto" + } }, { type: "ImportSpecifier", @@ -14171,10 +14184,12 @@ test("import foo, * as bar from 'baz';", { type: "ImportSpecifier", id: { type: "Identifier", - name: "foo" + name: "default" }, - name: null, - default: true + name: { + type: "Identifier", + name: "foo" + } }, { type: "ImportBatchSpecifier", From 9e204a7fee1b9407a722073ee16f137d87c3169c Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Tue, 25 Nov 2014 23:48:48 +1100 Subject: [PATCH 070/198] add playground --- README.md | 4 + acorn.js | 20 ++- package.json | 2 +- test/driver.js | 2 +- test/run.js | 1 + test/tests-6to5-playground.js | 310 ++++++++++++++++++++++++++++++++++ test/tests-6to5.js | 239 +------------------------- 7 files changed, 340 insertions(+), 238 deletions(-) create mode 100644 test/tests-6to5-playground.js diff --git a/README.md b/README.md index 4e5a45e1fa..06704f7b00 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # acorn-6to5 +**acorn-6to5** is not supported outside of 6to5 usage. Do not expect support if +you use this in your own applications. + Deviates from [acorn](https://github.com/marijnh/acorn) in the following ways: * JSX support via [acorn-jsx](https://github.com/RReverser/acorn-jsx) @@ -7,3 +10,4 @@ Deviates from [acorn](https://github.com/marijnh/acorn) in the following ways: * [ES7 Async/await](https://github.com/lukehoban/ecmascript-asyncawait) * [ES7 Exponentiation operator](https://github.com/rwaldron/exponentiation-operator) * [ES7 Object rest/spread](https://github.com/sebmarkbage/ecmascript-rest-spread) + * [6to5 Playground features](https://6to5.github.io/playground.html) diff --git a/acorn.js b/acorn.js index 19bf0b0b08..84e3da283c 100644 --- a/acorn.js +++ b/acorn.js @@ -52,6 +52,7 @@ // the parser process. These options are recognized: var defaultOptions = exports.defaultOptions = { + playground: false, // `ecmaVersion` indicates the ECMAScript version to parse. Must // be either 3, or 5, or 6. This influences support for strict // mode, the set of reserved words, support for getters and @@ -2364,6 +2365,13 @@ var expr = parseExprOps(noIn); if (eat(_question)) { var node = startNodeAt(start); + if (eat(_eq)) { + var left = node.left = toAssignable(expr); + if (left.type !== "MemberExpression") raise(left.start, "You can only use member expressions in memoization assignment"); + node.right = parseMaybeAssign(noIn); + node.operator = "?="; + return finishNode(node, "AssignmentExpression"); + } node.test = expr; node.consequent = parseExpression(true); expect(_colon); @@ -2447,7 +2455,17 @@ } function parseSubscripts(base, start, noCalls) { - if (eat(_doubleColon)) { + if (options.playground && eat(_colon)) { + var node = startNodeAt(start); + node.object = base; + node.property = parseIdent(true); + if (eat(_parenL)) { + node.arguments = parseExprList(_parenR, false); + } else { + node.arguments = []; + } + return parseSubscripts(finishNode(node, "BindMemberExpression"), start, noCalls); + } else if (eat(_doubleColon)) { var node = startNodeAt(start); node.object = base; node.property = parseIdent(true); diff --git a/package.json b/package.json index 6a707fd72e..c83a0a970b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.9.1-7", + "version": "0.9.1-8", "maintainers": [ { "name": "Marijn Haverbeke", diff --git a/test/driver.js b/test/driver.js index c76b8f91a4..37f36dcb99 100644 --- a/test/driver.js +++ b/test/driver.js @@ -60,7 +60,7 @@ else callback("fail", test.code, "Expected error message: " + test.error + "\nGot error message: " + e.message); } else { - callback("error", test.code, e.message || e.toString()); + callback("error", test.code, e.stack || e.toString()); } } } diff --git a/test/run.js b/test/run.js index 13809aa265..b6608b8dd7 100644 --- a/test/run.js +++ b/test/run.js @@ -7,6 +7,7 @@ require("./tests-harmony.js"); require("./tests-jsx.js"); require("./tests-6to5.js"); + require("./tests-6to5-playground.js"); } else { driver = window; } diff --git a/test/tests-6to5-playground.js b/test/tests-6to5-playground.js new file mode 100644 index 0000000000..d5085b9dcb --- /dev/null +++ b/test/tests-6to5-playground.js @@ -0,0 +1,310 @@ +if (typeof exports != "undefined") { + var test = require("./driver.js").test; + var testFail = require("./driver.js").testFail; + var testAssert = require("./driver.js").testAssert; +} + +// Memoization assignment operator + +testFail("obj ?= 2;", "You can only use member expressions in memoization assignment (1:0)"); + +test("obj.x ?= 2;", { + type: "Program", + start: 0, + end: 11, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 11, + expression: { + type: "AssignmentExpression", + start: 0, + end: 10, + left: { + type: "MemberExpression", + start: 0, + end: 5, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "obj" + }, + property: { + type: "Identifier", + start: 4, + end: 5, + name: "x" + }, + computed: false + }, + right: { + type: "Literal", + start: 9, + end: 10, + value: 2, + raw: "2" + }, + operator: "?=" + } + }] +}, { + playground: true +}); + +// Method binding + +test("var fn = obj:method", { + type: "Program", + start: 0, + end: 19, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 19, + declarations: [{ + type: "VariableDeclarator", + start: 4, + end: 19, + id: { + type: "Identifier", + start: 4, + end: 6, + name: "fn" + }, + init: { + type: "BindMemberExpression", + start: 9, + end: 19, + object: { + type: "Identifier", + start: 9, + end: 12, + name: "obj" + }, + property: { + type: "Identifier", + start: 13, + end: 19, + name: "method" + }, + arguments: [] + } + }], + kind: "var" + }] +}, { + playground: true +}); + +test("var fn = obj:method('foo', 5)", { + type: "Program", + start: 0, + end: 29, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 29, + declarations: [{ + type: "VariableDeclarator", + start: 4, + end: 29, + id: { + type: "Identifier", + start: 4, + end: 6, + name: "fn" + }, + init: { + type: "BindMemberExpression", + start: 9, + end: 29, + object: { + type: "Identifier", + start: 9, + end: 12, + name: "obj" + }, + property: { + type: "Identifier", + start: 13, + end: 19, + name: "method" + }, + arguments: [ + { + type: "Literal", + start: 20, + end: 25, + value: "foo", + raw: "'foo'" + }, + { + type: "Literal", + start: 27, + end: 28, + value: 5, + raw: "5" + } + ] + } + }], + kind: "var" + }] +}, { + playground: true +}); + +test("var fn = obj[foob]:method('foo', 5)", { + type: "Program", + start: 0, + end: 35, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 35, + declarations: [{ + type: "VariableDeclarator", + start: 4, + end: 35, + id: { + type: "Identifier", + start: 4, + end: 6, + name: "fn" + }, + init: { + type: "BindMemberExpression", + start: 9, + end: 35, + object: { + type: "MemberExpression", + start: 9, + end: 18, + object: { + type: "Identifier", + start: 9, + end: 12, + name: "obj" + }, + property: { + type: "Identifier", + start: 13, + end: 17, + name: "foob" + }, + computed: true + }, + property: { + type: "Identifier", + start: 19, + end: 25, + name: "method" + }, + arguments: [ + { + type: "Literal", + start: 26, + end: 31, + value: "foo", + raw: "'foo'" + }, + { + type: "Literal", + start: 33, + end: 34, + value: 5, + raw: "5" + } + ] + } + }], + kind: "var" + }] +}, { + playground: true +}); + +test("var fn = obj[foob].test:method('foo', 5)", { + type: "Program", + start: 0, + end: 40, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 40, + declarations: [ + { + type: "VariableDeclarator", + start: 4, + end: 40, + id: { + type: "Identifier", + start: 4, + end: 6, + name: "fn" + }, + init: { + type: "BindMemberExpression", + start: 9, + end: 40, + object: { + type: "MemberExpression", + start: 9, + end: 23, + object: { + type: "MemberExpression", + start: 9, + end: 18, + object: { + type: "Identifier", + start: 9, + end: 12, + name: "obj" + }, + property: { + type: "Identifier", + start: 13, + end: 17, + name: "foob" + }, + computed: true + }, + property: { + type: "Identifier", + start: 19, + end: 23, + name: "test" + }, + computed: false + }, + property: { + type: "Identifier", + start: 24, + end: 30, + name: "method" + }, + arguments: [ + { + type: "Literal", + start: 31, + end: 36, + value: "foo", + raw: "'foo'" + }, + { + type: "Literal", + start: 38, + end: 39, + value: 5, + raw: "5" + } + ] + } + } + ], + kind: "var" + }] +}, { + playground: true +}); diff --git a/test/tests-6to5.js b/test/tests-6to5.js index 6ce7d4f733..183ae8e6ef 100644 --- a/test/tests-6to5.js +++ b/test/tests-6to5.js @@ -480,6 +480,10 @@ test('({x, ...y, a, ...b, c})', { // ES7: Async Functions +testFail("function foo(promise) { await promise; }", "Unexpected token (1:30)", {ecmaVersion: 7}); + +testFail("async function* foo(promise) { await promise; }", "Unexpected token (1:14)", {ecmaVersion: 7}); + test('async function foo(promise) { await promise; }', { type: "Program", body: [{ @@ -1243,236 +1247,6 @@ test('f(async function(promise) { await promise })', { locations: true }); -test("f(a, async(1, 2), b);", { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "CallExpression", - callee: { - type: "Identifier", - name: "f", - loc: { - start: {line: 1, column: 0}, - end: {line: 1, column: 1} - } - }, - arguments: [ - { - type: "Identifier", - name: "a", - loc: { - start: {line: 1, column: 2}, - end: {line: 1, column: 3} - } - }, - { - type: "CallExpression", - callee: { - type: "Identifier", - name: "async", - loc: { - start: {line: 1, column: 5}, - end: {line: 1, column: 10} - } - }, - arguments: [ - { - type: "Literal", - value: 1, - loc: { - start: {line: 1,column: 11}, - end: {line: 1,column: 12} - } - }, - { - type: "Literal", - value: 2, - loc: { - start: {line: 1,column: 14}, - end: {line: 1,column: 15} - } - } - ], - loc: { - start: {line: 1,column: 5}, - end: {line: 1,column: 16} - } - }, - { - type: "Identifier", - name: "b", - loc: { - start: {line: 1,column: 18}, - end: {line: 1,column: 19} - } - } - ], - loc: { - start: {line: 1,column: 0}, - end: {line: 1,column: 20} - } - }, - loc: { - start: {line: 1,column: 0}, - end: {line: 1,column: 20} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test("var ok = async(x);", { - type: "Program", - body: [{ - type: "VariableDeclaration", - declarations: [ - { - type: "VariableDeclarator", - id: { - type: "Identifier", - name: "ok", - loc: { - start: {line: 1,column: 4}, - end: {line: 1,column: 6} - } - }, - init: { - type: "CallExpression", - callee: { - type: "Identifier", - name: "async", - loc: { - start: {line: 1,column: 9}, - end: {line: 1,column: 14} - } - }, - arguments: [ - { - type: "Identifier", - name: "x", - loc: { - start: {line: 1,column: 15}, - end: {line: 1,column: 16} - } - } - ], - loc: { - start: {line: 1,column: 9}, - end: {line: 1,column: 17} - } - }, - loc: { - start: {line: 1,column: 4}, - end: {line: 1,column: 17} - } - } - ], - kind: "var", - loc: { - start: {line: 1,column: 0}, - end: {line: 1,column: 17} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - -test("var async; async = 10;", { - type: "Program", - body: [{ - type: "ExpressionStatement", - expression: { - type: "FunctionExpression", - id: null, - params: [], - defaults: [], - body: { - type: "BlockStatement", - body: [ - { - type: "VariableDeclaration", - declarations: [ - { - type: "VariableDeclarator", - id: { - type: "Identifier", - name: "async", - loc: { - start: {line: 1,column: 18}, - end: {line: 1,column: 23} - } - }, - init: null, - loc: { - start: {line: 1,column: 18}, - end: {line: 1,column: 23} - } - } - ], - kind: "var", - loc: { - start: {line: 1,column: 14}, - end: {line: 1,column: 24} - } - }, - { - type: "ExpressionStatement", - expression: { - type: "AssignmentExpression", - operator: "=", - left: { - type: "Identifier", - name: "async", - loc: { - start: {line: 1,column: 25}, - end: {line: 1,column: 30} - } - }, - right: { - type: "Literal", - value: 10, - loc: { - start: {line: 1,column: 33}, - end: {line: 1,column: 35} - } - }, - loc: { - start: {line: 1,column: 25}, - end: {line: 1,column: 35} - } - }, - loc: { - start: {line: 1,column: 25}, - end: {line: 1,column: 36} - } - } - ], - loc: { - start: {line: 1,column: 12}, - end: {line: 1,column: 37} - } - }, - rest: null, - generator: false, - expression: false, - loc: { - start: {line: 1,column: 1}, - end: {line: 1,column: 37} - } - }, - loc: { - start: {line: 1,column: 0}, - end: {line: 1,column: 38} - } - }] -}, { - ecmaVersion: 7, - locations: true -}); - // ES7: Abstract references test('foo::bar;', { @@ -1660,8 +1434,3 @@ test('delete foo::bar;', { }, { ecmaVersion: 7 }); - - -testFail("function foo(promise) { await promise; }", "Unexpected token (1:30)", {ecmaVersion: 7}); - -testFail("async function* foo(promise) { await promise; }", "Unexpected token (1:14)", {ecmaVersion: 7}); From 2ec2a4b5af4ebbdb67664fc595195a04ca33ca40 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 26 Nov 2014 16:16:47 +1100 Subject: [PATCH 071/198] add pretzel maps --- acorn.js | 19 +++++++ package.json | 2 +- test/tests-6to5-playground.js | 104 ++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index 84e3da283c..ed628ec5d5 100644 --- a/acorn.js +++ b/acorn.js @@ -2615,11 +2615,30 @@ case _lt: return parseXJSElement(); + case _colon: + return parsePretzelMap(); + default: unexpected(); } } + function parsePretzelMap() { + var node = startNode(); + next(); + + var start = storeCurrentPos(); + node.callee = parseSubscripts(parseExprAtom(), start, true); + + if (eat(_parenL)) { + node.arguments = parseExprList(_parenR, false); + } else { + node.arguments = []; + } + + return finishNode(node, "PretzelMapExpression"); + } + // New's precedence is slightly tricky. It must allow its argument // to be a `[]` or dot subscript expression, but not a call — at // least, not without wrapping it in parentheses. Thus, it uses the diff --git a/package.json b/package.json index c83a0a970b..05226d8805 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.9.1-8", + "version": "0.9.1-9", "maintainers": [ { "name": "Marijn Haverbeke", diff --git a/test/tests-6to5-playground.js b/test/tests-6to5-playground.js index d5085b9dcb..6e14bc445a 100644 --- a/test/tests-6to5-playground.js +++ b/test/tests-6to5-playground.js @@ -4,6 +4,110 @@ if (typeof exports != "undefined") { var testAssert = require("./driver.js").testAssert; } +// Pretzel map + +test("arr.map(:toUpperCase)", { + type: "Program", + start: 0, + end: 21, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 21, + expression: { + type: "CallExpression", + start: 0, + end: 21, + callee: { + type: "MemberExpression", + start: 0, + end: 7, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "arr" + }, + property: { + type: "Identifier", + start: 4, + end: 7, + name: "map" + }, + computed: false + }, + arguments: [{ + type: "PretzelMapExpression", + start: 8, + end: 20, + callee: { + type: "Identifier", + start: 9, + end: 20, + name: "toUpperCase" + }, + arguments: [] + }] + } + }] +}, { + playground: true +}); + +test("arr.map(:toFixed(2))", { + type: "Program", + start: 0, + end: 20, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 20, + expression: { + type: "CallExpression", + start: 0, + end: 20, + callee: { + type: "MemberExpression", + start: 0, + end: 7, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "arr" + }, + property: { + type: "Identifier", + start: 4, + end: 7, + name: "map" + }, + computed: false + }, + arguments: [{ + type: "PretzelMapExpression", + start: 8, + end: 19, + callee: { + type: "Identifier", + start: 9, + end: 16, + name: "toFixed" + }, + arguments: [{ + type: "Literal", + start: 17, + end: 18, + value: 2, + raw: "2" + }] + }] + } + }] +}, { + playground: true +}); + // Memoization assignment operator testFail("obj ?= 2;", "You can only use member expressions in memoization assignment (1:0)"); From d14f4461775e863d27875e4ce2e4ff7e9a6da356 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 26 Nov 2014 17:23:11 +1100 Subject: [PATCH 072/198] rename PretzelMap to BindFunctionExpression --- acorn.js | 6 +- package.json | 2 +- test/tests-6to5-playground.js | 207 +++++++++++++++++----------------- 3 files changed, 107 insertions(+), 108 deletions(-) diff --git a/acorn.js b/acorn.js index ed628ec5d5..6d9db1d7d9 100644 --- a/acorn.js +++ b/acorn.js @@ -2616,14 +2616,14 @@ return parseXJSElement(); case _colon: - return parsePretzelMap(); + return parseBindFunctionExpression(); default: unexpected(); } } - function parsePretzelMap() { + function parseBindFunctionExpression() { var node = startNode(); next(); @@ -2636,7 +2636,7 @@ node.arguments = []; } - return finishNode(node, "PretzelMapExpression"); + return finishNode(node, "BindFunctionExpression"); } // New's precedence is slightly tricky. It must allow its argument diff --git a/package.json b/package.json index 05226d8805..0d2fc14208 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.9.1-9", + "version": "0.9.1-10", "maintainers": [ { "name": "Marijn Haverbeke", diff --git a/test/tests-6to5-playground.js b/test/tests-6to5-playground.js index 6e14bc445a..8bcddaad88 100644 --- a/test/tests-6to5-playground.js +++ b/test/tests-6to5-playground.js @@ -4,110 +4,6 @@ if (typeof exports != "undefined") { var testAssert = require("./driver.js").testAssert; } -// Pretzel map - -test("arr.map(:toUpperCase)", { - type: "Program", - start: 0, - end: 21, - body: [{ - type: "ExpressionStatement", - start: 0, - end: 21, - expression: { - type: "CallExpression", - start: 0, - end: 21, - callee: { - type: "MemberExpression", - start: 0, - end: 7, - object: { - type: "Identifier", - start: 0, - end: 3, - name: "arr" - }, - property: { - type: "Identifier", - start: 4, - end: 7, - name: "map" - }, - computed: false - }, - arguments: [{ - type: "PretzelMapExpression", - start: 8, - end: 20, - callee: { - type: "Identifier", - start: 9, - end: 20, - name: "toUpperCase" - }, - arguments: [] - }] - } - }] -}, { - playground: true -}); - -test("arr.map(:toFixed(2))", { - type: "Program", - start: 0, - end: 20, - body: [{ - type: "ExpressionStatement", - start: 0, - end: 20, - expression: { - type: "CallExpression", - start: 0, - end: 20, - callee: { - type: "MemberExpression", - start: 0, - end: 7, - object: { - type: "Identifier", - start: 0, - end: 3, - name: "arr" - }, - property: { - type: "Identifier", - start: 4, - end: 7, - name: "map" - }, - computed: false - }, - arguments: [{ - type: "PretzelMapExpression", - start: 8, - end: 19, - callee: { - type: "Identifier", - start: 9, - end: 16, - name: "toFixed" - }, - arguments: [{ - type: "Literal", - start: 17, - end: 18, - value: 2, - raw: "2" - }] - }] - } - }] -}, { - playground: true -}); - // Memoization assignment operator testFail("obj ?= 2;", "You can only use member expressions in memoization assignment (1:0)"); @@ -412,3 +308,106 @@ test("var fn = obj[foob].test:method('foo', 5)", { }, { playground: true }); + + +test("arr.map(:toUpperCase)", { + type: "Program", + start: 0, + end: 21, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 21, + expression: { + type: "CallExpression", + start: 0, + end: 21, + callee: { + type: "MemberExpression", + start: 0, + end: 7, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "arr" + }, + property: { + type: "Identifier", + start: 4, + end: 7, + name: "map" + }, + computed: false + }, + arguments: [{ + type: "BindFunctionExpression", + start: 8, + end: 20, + callee: { + type: "Identifier", + start: 9, + end: 20, + name: "toUpperCase" + }, + arguments: [] + }] + } + }] +}, { + playground: true +}); + +test("arr.map(:toFixed(2))", { + type: "Program", + start: 0, + end: 20, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 20, + expression: { + type: "CallExpression", + start: 0, + end: 20, + callee: { + type: "MemberExpression", + start: 0, + end: 7, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "arr" + }, + property: { + type: "Identifier", + start: 4, + end: 7, + name: "map" + }, + computed: false + }, + arguments: [{ + type: "BindFunctionExpression", + start: 8, + end: 19, + callee: { + type: "Identifier", + start: 9, + end: 16, + name: "toFixed" + }, + arguments: [{ + type: "Literal", + start: 17, + end: 18, + value: 2, + raw: "2" + }] + }] + } + }] +}, { + playground: true +}); From 879d40989a46b5246a8b2c20c0fb5ab51b3b51b7 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 28 Nov 2014 16:51:50 +0200 Subject: [PATCH 073/198] Fix #9 by removing invalid logic introduced with #1. --- acorn.js | 21 ++++++++------------- package.json | 2 +- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/acorn.js b/acorn.js index f777a4e39c..00e9e7eaee 100644 --- a/acorn.js +++ b/acorn.js @@ -296,7 +296,7 @@ // `strict` indicates whether strict mode is on. var inFunction, inGenerator, labels, strict, - inXJSChild, inXJSTag, inXJSChildExpression; + inXJSChild, inXJSTag; // This counter is used for checking that arrow expressions did // not contain nested parentheses in argument list. @@ -618,9 +618,7 @@ tokEnd = tokPos; if (options.locations) tokEndLoc = new Position; tokType = type; - if (shouldSkipSpace !== false && !(inXJSChild && tokType !== _braceL)) { - skipSpace(); - } + if (shouldSkipSpace !== false) skipSpace(); tokVal = val; tokRegexpAllowed = type.beforeExpr; if (options.onToken) { @@ -846,7 +844,7 @@ case 91: ++tokPos; return finishToken(_bracketL); case 93: ++tokPos; return finishToken(_bracketR); case 123: ++tokPos; return finishToken(_braceL); - case 125: ++tokPos; return finishToken(_braceR, undefined, !inXJSChildExpression); + case 125: ++tokPos; return finishToken(_braceR, undefined, !inXJSChild); case 58: ++tokPos; return finishToken(_colon); case 63: ++tokPos; return finishToken(_question); @@ -2549,8 +2547,6 @@ function parseObj() { var node = startNode(), first = true, propHash = {}; node.properties = []; - var origInXJSChildExpression = inXJSChildExpression; - inXJSChildExpression = false; next(); while (!eat(_braceR)) { if (!first) { @@ -2587,7 +2583,6 @@ checkPropClash(prop, propHash); node.properties.push(finishNode(prop, "Property")); } - inXJSChildExpression = origInXJSChildExpression; return finishNode(node, "ObjectExpression"); } @@ -3153,15 +3148,16 @@ inXJSTag = false; inXJSChild = false; - inXJSChildExpression = origInXJSChild; next(); node.expression = tokType === _braceR ? parseXJSEmptyExpression() : parseExpression(); inXJSTag = origInXJSTag; inXJSChild = origInXJSChild; - inXJSChildExpression = false; + if (inXJSChild) { + tokPos = tokEnd; + } expect(_braceR); return finishNode(node, "XJSExpressionContainer"); } @@ -3172,14 +3168,13 @@ if (tokType === _braceL) { var tokStart1 = tokStart, tokStartLoc1 = tokStartLoc; - var origInXJSTag = inXJSTag, origInXJSChildExpression = inXJSChildExpression; - inXJSTag = inXJSChildExpression = false; + var origInXJSTag = inXJSTag; + inXJSTag = false; next(); if (tokType !== _ellipsis) unexpected(); var node = parseMaybeUnary(); - inXJSChildExpression = origInXJSChildExpression; inXJSTag = origInXJSTag; expect(_braceR); diff --git a/package.json b/package.json index 1ae847636b..68ff13bc04 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-jsx", "description": "Alternative React JSX parser", "main": "acorn.js", - "version": "0.9.1-5", + "version": "0.9.1-6", "maintainers": [ { "name": "Marijn Haverbeke", From 7a0fb32064b8b21fd562627d03e89bcce95ecd61 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Fri, 5 Dec 2014 14:46:51 +1100 Subject: [PATCH 074/198] Add playground conditionals check --- test/tests-6to5-playground.js | 88 +++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/test/tests-6to5-playground.js b/test/tests-6to5-playground.js index 8bcddaad88..48386298cb 100644 --- a/test/tests-6to5-playground.js +++ b/test/tests-6to5-playground.js @@ -6,6 +6,94 @@ if (typeof exports != "undefined") { // Memoization assignment operator +// Make sure conditionals still work + +test("y ? 1 : 2", { + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "ConditionalExpression", + test: { + type: "Identifier", + name: "y", + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 1 + } + } + }, + consequent: { + type: "Literal", + value: 1, + loc: { + start: { + line: 1, + column: 4 + }, + end: { + line: 1, + column: 5 + } + } + }, + alternate: { + type: "Literal", + value: 2, + loc: { + start: { + line: 1, + column: 8 + }, + end: { + line: 1, + column: 9 + } + } + }, + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 9 + } + } + }, + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 9 + } + } + } + ], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 9 + } + } +}, { + playground: true +}); + testFail("obj ?= 2;", "You can only use member expressions in memoization assignment (1:0)"); test("obj.x ?= 2;", { From ac197399bb5abcede65973ff3bc356303282602e Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Fri, 5 Dec 2014 14:46:56 +1100 Subject: [PATCH 075/198] Add @ token --- acorn.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index 55f24739be..46d430a819 100644 --- a/acorn.js +++ b/acorn.js @@ -430,6 +430,7 @@ var _ltSlash = {type: " this.foo case _yield: if (inGenerator) return parseYield(); From 404058f9dad0c7da92b338987e301a1d7661c9a1 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 6 Dec 2014 20:43:32 +1100 Subject: [PATCH 076/198] Add object memo getters, this expressions and improve tenary syntax in playground --- acorn.js | 39 +++++-- package.json | 2 +- test/tests-6to5-playground.js | 195 +++++++++++++++++++++++++++++++++- 3 files changed, 226 insertions(+), 10 deletions(-) diff --git a/acorn.js b/acorn.js index 46d430a819..a440be64ac 100644 --- a/acorn.js +++ b/acorn.js @@ -885,7 +885,12 @@ case 123: ++tokPos; return finishToken(_braceL); case 125: ++tokPos; return finishToken(_braceR, undefined, !inXJSChild); case 63: ++tokPos; return finishToken(_question); - case 64: ++tokPos; return finishToken(_at); + + case 64: + if (options.playground) { + ++tokPos; + return finishToken(_at); + } case 58: ++tokPos; @@ -1707,7 +1712,6 @@ node.loc.end = lastEndLoc; if (options.ranges) node.range[1] = lastEnd; - console.log(node); return node; } @@ -2374,9 +2378,23 @@ return finishNode(node, "AssignmentExpression"); } node.test = expr; - node.consequent = parseExpression(true); - expect(_colon); - node.alternate = parseExpression(true, noIn); + var consequent = node.consequent = parseExpression(true); + if (consequent.type === "BindMemberExpression" && tokType !== _colon) { + // this is a hack to make, revisit at a later date + if (consequent.arguments.length) { + node.alternate = { + type: "CallExpression", + arguments: consequent.arguments, + callee: consequent.property + }; + } else { + node.alternate = consequent.property; + } + node.consequent = consequent.object; + } else { + expect(_colon); + node.alternate = parseExpression(true, noIn); + } return finishNode(node, "ConditionalExpression"); } return expr; @@ -2510,7 +2528,12 @@ return finishNode(node, "ThisExpression"); case _at: - unexpected(); // todo: @foo -> this.foo + var node = startNode(); + next(); + node.object = { type: "ThisExpression" } + node.property = parseExprSubscripts(); + node.computed = false; + return finishNode(node, "MemberExpression"); case _yield: if (inGenerator) return parseYield(); @@ -2726,7 +2749,7 @@ prop.method = true; prop.value = parseMethod(isGenerator, isAsync); } else if (options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && - (prop.key.name === "get" || prop.key.name === "set")) { + (prop.key.name === "get" || prop.key.name === "set" || (options.playground && prop.key.name === "memo"))) { if (isGenerator || isAsync) unexpected(); prop.kind = prop.key.name; parsePropertyName(prop); @@ -2934,7 +2957,7 @@ var isGenerator = eat(_star); parsePropertyName(method); if (tokType !== _parenL && !method.computed && method.key.type === "Identifier" && - (method.key.name === "get" || method.key.name === "set")) { + (method.key.name === "get" || method.key.name === "set" || (options.playground && method.key.name === "memo"))) { if (isGenerator || isAsync) unexpected(); method.kind = method.key.name; parsePropertyName(method); diff --git a/package.json b/package.json index c97fcd0a72..1e3a5bbb6a 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.9.1-11", + "version": "0.9.1-12", "maintainers": [ { "name": "Marijn Haverbeke", diff --git a/test/tests-6to5-playground.js b/test/tests-6to5-playground.js index 48386298cb..85b016d2cc 100644 --- a/test/tests-6to5-playground.js +++ b/test/tests-6to5-playground.js @@ -4,9 +4,202 @@ if (typeof exports != "undefined") { var testAssert = require("./driver.js").testAssert; } +// This shorthand + +test("@foo", { + "type": "Program", + "start": 0, + "end": 4, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 4, + "expression": { + "type": "MemberExpression", + "start": 0, + "end": 4, + "object": { + "type": "ThisExpression" + }, + "property": { + "type": "Identifier", + "start": 1, + "end": 4, + "name": "foo" + }, + "computed": false + } + } + ] +}, { + playground: true +}); + +test("@foo();", { + "type": "Program", + "start": 0, + "end": 7, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 7, + "expression": { + "type": "MemberExpression", + "start": 0, + "end": 6, + "object": { + "type": "ThisExpression" + }, + "property": { + "type": "CallExpression", + "start": 1, + "end": 6, + "callee": { + "type": "Identifier", + "start": 1, + "end": 4, + "name": "foo" + }, + "arguments": [] + }, + "computed": false + } + } + ] +}, { + playground: true +}); + +// Object getter memoisation + +test("class Foo { memo bar() {} }", { + type: "Program", + start: 0, + end: 27, + body: [{ + type: "ClassDeclaration", + start: 0, + end: 27, + id: { + type: "Identifier", + start: 6, + end: 9, + name: "Foo" + }, + superClass: null, + body: { + type: "ClassBody", + start: 10, + end: 27, + body: [{ + type: "MethodDefinition", + start: 12, + end: 25, + static: false, + computed: false, + key: { + type: "Identifier", + start: 17, + end: 20, + name: "bar" + }, + kind: "memo", + value: { + type: "FunctionExpression", + start: 20, + end: 25, + id: null, + params: [], + defaults: [], + rest: null, + generator: false, + async: false, + body: { + type: "BlockStatement", + start: 23, + end: 25, + body: [] + }, + expression: false + } + }] + } + }] +}, { + playground: true, + ecmaVersion: 6 +}); + +test("var foo = { memo bar() {} };", +{ + type: "Program", + start: 0, + end: 28, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 28, + declarations: [{ + type: "VariableDeclarator", + start: 4, + end: 27, + id: { + type: "Identifier", + start: 4, + end: 7, + name: "foo" + }, + init: { + type: "ObjectExpression", + start: 10, + end: 27, + properties: [{ + type: "Property", + start: 12, + end: 25, + method: false, + shorthand: false, + computed: false, + key: { + type: "Identifier", + start: 17, + end: 20, + name: "bar" + }, + kind: "memo", + value: { + type: "FunctionExpression", + start: 20, + end: 25, + id: null, + params: [], + defaults: [], + rest: null, + generator: false, + async: false, + body: { + type: "BlockStatement", + start: 23, + end: 25, + body: [] + }, + expression: false + } + }] + } + }], + kind: "var" + }] +}, { + playground: true, + ecmaVersion: 6 +}); + // Memoization assignment operator -// Make sure conditionals still work +//- Make sure conditionals still work test("y ? 1 : 2", { type: "Program", From 49119b771444a3709036f9a2e80bf302bb672e14 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 10 Dec 2014 15:19:45 +1100 Subject: [PATCH 077/198] Make semicolon optional in do-while --- acorn.js | 2 +- test/tests.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index 401b9421c8..8c46695f69 100644 --- a/acorn.js +++ b/acorn.js @@ -1603,7 +1603,7 @@ labels.pop(); expect(_while); node.test = parseParenExpression(); - semicolon(); + eat(_semi); return finishNode(node, "DoWhileStatement"); } diff --git a/test/tests.js b/test/tests.js index 287d98f84d..8d972eedcf 100644 --- a/test/tests.js +++ b/test/tests.js @@ -17911,6 +17911,49 @@ test("do keep(); while (true);", { } }); +test("do {} while (false) foo();", { + type: "Program", + start: 0, + end: 26, + body: [ + { + type: "DoWhileStatement", + start: 0, + end: 19, + body: { + type: "BlockStatement", + start: 3, + end: 5, + body: [] + }, + test: { + type: "Literal", + start: 13, + end: 18, + value: false, + raw: "false" + } + }, + { + type: "ExpressionStatement", + start: 20, + end: 26, + expression: { + type: "CallExpression", + start: 20, + end: 25, + callee: { + type: "Identifier", + start: 20, + end: 23, + name: "foo" + }, + arguments: [] + } + } + ] +}); + test("do { x++; y--; } while (x < 10)", { type: "Program", body: [ From 876eed9c040721598ad7c6a08d929cd7399a9e69 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 10 Dec 2014 15:21:19 +1100 Subject: [PATCH 078/198] Add dot question token --- acorn.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/acorn.js b/acorn.js index a440be64ac..8cb360f419 100644 --- a/acorn.js +++ b/acorn.js @@ -431,6 +431,7 @@ var _ellipsis = {type: "...", prefix: true, beforeExpr: true}; var _doubleColon = { type: "::", beforeExpr: true }; var _at = { type: '@' }; + var _dotQuestion = { type: '.?' }; // Operators. These carry several kinds of properties to help the // parser use them properly (the presence of these properties is @@ -736,7 +737,10 @@ var next = input.charCodeAt(tokPos + 1); if (next >= 48 && next <= 57) return readNumber(true); var next2 = input.charCodeAt(tokPos + 2); - if (options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' + if (options.playground && next === 63) { // 63 + tokPos += 2; + return finishToken(_dotQuestion); + } else if (options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' tokPos += 3; return finishToken(_ellipsis); } else { @@ -2380,7 +2384,7 @@ node.test = expr; var consequent = node.consequent = parseExpression(true); if (consequent.type === "BindMemberExpression" && tokType !== _colon) { - // this is a hack to make, revisit at a later date + // this is a hack, revisit at a later date if (consequent.arguments.length) { node.alternate = { type: "CallExpression", From 841ab6802f572b1b2567497801249073261df1eb Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 10 Dec 2014 18:59:24 +1100 Subject: [PATCH 079/198] Make semicolon optional in do-while in >=ES6 --- acorn.js | 6 +++++- test/tests-harmony.js | 46 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index 401b9421c8..126ef8ad8c 100644 --- a/acorn.js +++ b/acorn.js @@ -1603,7 +1603,11 @@ labels.pop(); expect(_while); node.test = parseParenExpression(); - semicolon(); + if (options.ecmaVersion >= 6) { + eat(_semi); + } else { + semicolon(); + } return finishNode(node, "DoWhileStatement"); } diff --git a/test/tests-harmony.js b/test/tests-harmony.js index 539418f870..d1ca1c4571 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -13405,6 +13405,52 @@ test("/[a-z]/u", { ecmaVersion: 6 }); + +test("do {} while (false) foo();", { + type: "Program", + start: 0, + end: 26, + body: [ + { + type: "DoWhileStatement", + start: 0, + end: 19, + body: { + type: "BlockStatement", + start: 3, + end: 5, + body: [] + }, + test: { + type: "Literal", + start: 13, + end: 18, + value: false, + raw: "false" + } + }, + { + type: "ExpressionStatement", + start: 20, + end: 26, + expression: { + type: "CallExpression", + start: 20, + end: 25, + callee: { + type: "Identifier", + start: 20, + end: 23, + name: "foo" + }, + arguments: [] + } + } + ] +}, { + ecmaVersion: 6 +}); + // Harmony Invalid syntax testFail("0o", "Expected number in radix 8 (1:2)", {ecmaVersion: 6}); From c87a7a7095db39fc95da313f14d73a410a9717cd Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 10 Dec 2014 19:07:27 +1100 Subject: [PATCH 080/198] Revert "Merge branch 'do-optional-semicolon' of https://github.com/sebmck/acorn" This reverts commit c526814896711439b89f613fe0412aad4c1730a8, reversing changes made to e7fea263dac65061941a4cee25c7a84c4e50c8bf. --- acorn.js | 2 +- test/tests.js | 43 ------------------------------------------- 2 files changed, 1 insertion(+), 44 deletions(-) diff --git a/acorn.js b/acorn.js index 997a670ab9..f0740d8154 100644 --- a/acorn.js +++ b/acorn.js @@ -2027,7 +2027,7 @@ labels.pop(); expect(_while); node.test = parseParenExpression(); - eat(_semi); + semicolon(); return finishNode(node, "DoWhileStatement"); } diff --git a/test/tests.js b/test/tests.js index f40dcced6c..72b9340307 100644 --- a/test/tests.js +++ b/test/tests.js @@ -17911,49 +17911,6 @@ test("do keep(); while (true);", { } }); -test("do {} while (false) foo();", { - type: "Program", - start: 0, - end: 26, - body: [ - { - type: "DoWhileStatement", - start: 0, - end: 19, - body: { - type: "BlockStatement", - start: 3, - end: 5, - body: [] - }, - test: { - type: "Literal", - start: 13, - end: 18, - value: false, - raw: "false" - } - }, - { - type: "ExpressionStatement", - start: 20, - end: 26, - expression: { - type: "CallExpression", - start: 20, - end: 25, - callee: { - type: "Identifier", - start: 20, - end: 23, - name: "foo" - }, - arguments: [] - } - } - ] -}); - test("do { x++; y--; } while (x < 10)", { type: "Program", body: [ From 662375631214d70472c459df4c589cb168e9156f Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 10 Dec 2014 21:49:55 +1100 Subject: [PATCH 081/198] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1e3a5bbb6a..2010451e4f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.9.1-12", + "version": "0.9.1-13", "maintainers": [ { "name": "Marijn Haverbeke", From 71bb9d61230767be78e191acb2139ccf4538fa3d Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 13 Dec 2014 00:37:40 +1100 Subject: [PATCH 082/198] contextual async/await keywords - closes 6to5/6to5#157 --- acorn.js | 128 ++++----- test/tests-6to5-playground.js | 98 ++++--- test/tests-6to5.js | 486 ++++++++++++++++++++++++++++++++++ 3 files changed, 601 insertions(+), 111 deletions(-) diff --git a/acorn.js b/acorn.js index 5b7337aa6f..439d85aebc 100644 --- a/acorn.js +++ b/acorn.js @@ -169,9 +169,7 @@ if (options.strictMode) { strict = true; } - if (options.ecmaVersion >= 7) { - isKeyword = isEcma7Keyword; - } else if (options.ecmaVersion === 6) { + if (options.ecmaVersion >= 6) { isKeyword = isEcma6Keyword; } else { isKeyword = isEcma5AndLessKeyword; @@ -390,7 +388,6 @@ var _class = {keyword: "class"}, _extends = {keyword: "extends", beforeExpr: true}; var _export = {keyword: "export"}, _import = {keyword: "import"}; var _yield = {keyword: "yield", beforeExpr: true}; - var _async = {keyword: "async"}, _await = {keyword: "await", beforeExpr: true}; // The keywords that denote values. @@ -417,8 +414,7 @@ "void": {keyword: "void", prefix: true, beforeExpr: true}, "delete": {keyword: "delete", prefix: true, beforeExpr: true}, "class": _class, "extends": _extends, - "export": _export, "import": _import, "yield": _yield, - "await": _await, "async": _async}; + "export": _export, "import": _import, "yield": _yield}; // Punctuation token types. Again, the `type` property is purely for debugging. @@ -556,8 +552,6 @@ var isEcma6Keyword = makePredicate(ecma6AndLessKeywords); - var isEcma7Keyword = makePredicate(ecma6AndLessKeywords + " async await"); - var isKeyword = isEcma5AndLessKeyword; // ## Character categories @@ -1962,7 +1956,6 @@ case _debugger: return parseDebuggerStatement(node); case _do: return parseDoStatement(node); case _for: return parseForStatement(node); - case _async: return parseAsync(node, true); case _function: return parseFunctionStatement(node); case _class: return parseClass(node, true); case _if: return parseIfStatement(node); @@ -1985,9 +1978,18 @@ // Identifier node, we switch to interpreting it as a label. default: var maybeName = tokVal, expr = parseExpression(); - if (starttype === _name && expr.type === "Identifier" && eat(_colon)) - return parseLabeledStatement(node, maybeName, expr); - else return parseExpressionStatement(node, expr); + if (starttype === _name) { + if (expr.type === "FunctionExpression" && expr.async) { + expr.type = "FunctionDeclaration"; + return expr; + } else if (expr.type === "Identifier") { + if (eat(_colon)) { + return parseLabeledStatement(node, maybeName, expr); + } + } + } + + return parseExpressionStatement(node, expr); } } @@ -2071,42 +2073,12 @@ return parseFunction(node, true, false); } - function parseAsync(node, isStatement) { - if (options.ecmaVersion < 7) { - unexpected(); - } - - next(); - - switch (tokType) { - case _function: - next(); - return parseFunction(node, isStatement, true); - - if (!isStatement) unexpected(); - - case _name: - var id = parseIdent(tokType !== _name); - if (eat(_arrow)) { - return parseArrowExpression(node, [id], true); - } - - case _parenL: - var oldParenL = ++metParenL; - var exprList = []; - next(); - if (tokType !== _parenR) { - var val = parseExpression(); - exprList = val.type === "SequenceExpression" ? val.expressions : [val]; - } - expect(_parenR); - // if '=>' follows '(...)', convert contents to arguments - if (metParenL === oldParenL && eat(_arrow)) { - return parseArrowExpression(node, exprList, true); - } - - default: - unexpected(); + function eatAsync() { + if (tokType === _name && tokVal === "async") { + next(); + return true; + } else { + return false; } } @@ -2539,14 +2511,53 @@ case _yield: if (inGenerator) return parseYield(); - case _await: - if (inAsync) return parseAwait(); - case _name: var start = storeCurrentPos(); + var node = startNode(); var id = parseIdent(tokType !== _name); + + if (options.ecmaVersion >= 7) { + // async functions! + if (id.name === "async") { + // arrow functions + if (tokType === _parenL) { + next(); + var oldParenL = ++metParenL; + if (tokType !== _parenR) { + val = parseExpression(); + exprList = val.type === "SequenceExpression" ? val.expressions : [val]; + } else { + exprList = []; + } + expect(_parenR); + // if '=>' follows '(...)', convert contents to arguments + if (metParenL === oldParenL && eat(_arrow)) { + return parseArrowExpression(node, exprList, true); + } else { + node.callee = id; + node.arguments = exprList; + return parseSubscripts(finishNode(node, "CallExpression"), start); + } + } else if (tokType === _name) { + id = parseIdent(); + if (eat(_arrow)) { + return parseArrowExpression(node, [id], true); + } + return id; + } + + // normal functions + if (tokType === _function) { + next(); + return parseFunction(node, false, true); + } + } else if (id.name === "await") { + if (inAsync) return parseAwait(node); + } + } + if (eat(_arrow)) { - return parseArrowExpression(startNodeAt(start), [id]); + return parseArrowExpression(node, [id]); } return id; @@ -2623,9 +2634,6 @@ case _braceL: return parseObj(); - case _async: - return parseAsync(startNode(), false); - case _function: var node = startNode(); next(); @@ -2727,7 +2735,7 @@ var prop = startNode(), isGenerator, isAsync; if (options.ecmaVersion >= 7) { - isAsync = eat(_async); + isAsync = eatAsync(); if (isAsync && tokType === _star) unexpected(); } if (options.ecmaVersion >= 6) { @@ -2953,7 +2961,7 @@ } var isAsync = false; if (options.ecmaVersion >= 7) { - isAsync = eat(_async); + isAsync = eatAsync(); if (isAsync && tokType === _star) unexpected(); } var isGenerator = eat(_star); @@ -3024,7 +3032,7 @@ function parseExport(node) { next(); // export var|const|let|function|class ...; - if (tokType === _var || tokType === _const || tokType === _let || tokType === _function || tokType === _class || tokType === _async) { + if (tokType === _var || tokType === _const || tokType === _let || tokType === _function || tokType === _class) { node.declaration = parseStatement(); node['default'] = false; node.specifiers = null; @@ -3170,9 +3178,7 @@ // Parses await expression inside async function. - function parseAwait() { - var node = startNode(); - next(); + function parseAwait(node) { if (eat(_semi) || canInsertSemicolon()) { unexpected(); } diff --git a/test/tests-6to5-playground.js b/test/tests-6to5-playground.js index 85b016d2cc..d8076b886c 100644 --- a/test/tests-6to5-playground.js +++ b/test/tests-6to5-playground.js @@ -115,7 +115,6 @@ test("class Foo { memo bar() {} }", { defaults: [], rest: null, generator: false, - async: false, body: { type: "BlockStatement", start: 23, @@ -178,7 +177,6 @@ test("var foo = { memo bar() {} };", defaults: [], rest: null, generator: false, - async: false, body: { type: "BlockStatement", start: 23, @@ -199,6 +197,54 @@ test("var foo = { memo bar() {} };", // Memoization assignment operator +testFail("obj ?= 2;", "You can only use member expressions in memoization assignment (1:0)"); + +test("obj.x ?= 2;", { + type: "Program", + start: 0, + end: 11, + body: [{ + type: "ExpressionStatement", + start: 0, + end: 11, + expression: { + type: "AssignmentExpression", + start: 0, + end: 10, + left: { + type: "MemberExpression", + start: 0, + end: 5, + object: { + type: "Identifier", + start: 0, + end: 3, + name: "obj" + }, + property: { + type: "Identifier", + start: 4, + end: 5, + name: "x" + }, + computed: false + }, + right: { + type: "Literal", + start: 9, + end: 10, + value: 2, + raw: "2" + }, + operator: "?=" + } + }] +}, { + playground: true +}); + +// Method binding + //- Make sure conditionals still work test("y ? 1 : 2", { @@ -287,54 +333,6 @@ test("y ? 1 : 2", { playground: true }); -testFail("obj ?= 2;", "You can only use member expressions in memoization assignment (1:0)"); - -test("obj.x ?= 2;", { - type: "Program", - start: 0, - end: 11, - body: [{ - type: "ExpressionStatement", - start: 0, - end: 11, - expression: { - type: "AssignmentExpression", - start: 0, - end: 10, - left: { - type: "MemberExpression", - start: 0, - end: 5, - object: { - type: "Identifier", - start: 0, - end: 3, - name: "obj" - }, - property: { - type: "Identifier", - start: 4, - end: 5, - name: "x" - }, - computed: false - }, - right: { - type: "Literal", - start: 9, - end: 10, - value: 2, - raw: "2" - }, - operator: "?=" - } - }] -}, { - playground: true -}); - -// Method binding - test("var fn = obj:method", { type: "Program", start: 0, diff --git a/test/tests-6to5.js b/test/tests-6to5.js index 183ae8e6ef..757e67762d 100644 --- a/test/tests-6to5.js +++ b/test/tests-6to5.js @@ -1247,6 +1247,492 @@ test('f(async function(promise) { await promise })', { locations: true }); +test('f(a, async(1, 2), b)', { + type: "Program", + body: [{ + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "f", + "range": [ + 0, + 1 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "a", + "range": [ + 2, + 3 + ], + "loc": { + "start": { + "line": 1, + "column": 2 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "async", + "range": [ + 5, + 10 + ], + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 10 + } + } + }, + "arguments": [ + { + "type": "Literal", + "value": 1, + "raw": "1", + "range": [ + 11, + 12 + ], + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 12 + } + } + }, + { + "type": "Literal", + "value": 2, + "raw": "2", + "range": [ + 14, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 14 + }, + "end": { + "line": 1, + "column": 15 + } + } + } + ], + "range": [ + 5, + 16 + ], + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 16 + } + } + }, + { + "type": "Identifier", + "name": "b", + "range": [ + 18, + 19 + ], + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 19 + } + } + } + ], + "range": [ + 0, + 20 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 20 + } + } + }, + "range": [ + 0, + 20 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 20 + } + } + }] +}, { + ecmaVersion: 7, + locations: true, + ranges: true +}); + +test('var ok = async(x)', { + type: "Program", + body: [{ + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "ok", + "range": [ + 4, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "async", + "range": [ + 9, + 14 + ], + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 14 + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "x", + "range": [ + 15, + 16 + ], + "loc": { + "start": { + "line": 1, + "column": 15 + }, + "end": { + "line": 1, + "column": 16 + } + } + } + ], + "range": [ + 9, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + "range": [ + 4, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 17 + } + } + } + ], + "kind": "var", + "range": [ + 0, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 17 + } + } + }] +}, { + ecmaVersion: 7, + locations: true, + ranges: true +}); + +test('(function() { var async; async = 10 })', { + type: "Program", + body: [{ + "type": "ExpressionStatement", + "expression": { + "type": "FunctionExpression", + "id": null, + "params": [], + "defaults": [], + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "async", + "range": [ + 18, + 23 + ], + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 23 + } + } + }, + "init": null, + "range": [ + 18, + 23 + ], + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 23 + } + } + } + ], + "kind": "var", + "range": [ + 14, + 24 + ], + "loc": { + "start": { + "line": 1, + "column": 14 + }, + "end": { + "line": 1, + "column": 24 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "async", + "range": [ + 25, + 30 + ], + "loc": { + "start": { + "line": 1, + "column": 25 + }, + "end": { + "line": 1, + "column": 30 + } + } + }, + "right": { + "type": "Literal", + "value": 10, + "raw": "10", + "range": [ + 33, + 35 + ], + "loc": { + "start": { + "line": 1, + "column": 33 + }, + "end": { + "line": 1, + "column": 35 + } + } + }, + "range": [ + 25, + 35 + ], + "loc": { + "start": { + "line": 1, + "column": 25 + }, + "end": { + "line": 1, + "column": 35 + } + } + }, + "range": [ + 25, + 35 + ], + "loc": { + "start": { + "line": 1, + "column": 25 + }, + "end": { + "line": 1, + "column": 35 + } + } + } + ], + "range": [ + 12, + 37 + ], + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 37 + } + } + }, + "rest": null, + "generator": false, + "expression": false, + "range": [ + 1, + 37 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 37 + } + } + }, + "range": [ + 0, + 38 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 38 + } + } + }] +}, { + ecmaVersion: 7, + locations: true, + ranges: true +}); + // ES7: Abstract references test('foo::bar;', { From 8bef320d58a6ae5c569ca9c1972f3143dc5adc79 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 13 Dec 2014 00:47:13 +1100 Subject: [PATCH 083/198] change bind member operator to a hash - fixes #6 --- acorn.js | 41 ++++++-------- test/tests-6to5-playground.js | 100 ++-------------------------------- 2 files changed, 23 insertions(+), 118 deletions(-) diff --git a/acorn.js b/acorn.js index 439d85aebc..9da6054829 100644 --- a/acorn.js +++ b/acorn.js @@ -425,9 +425,9 @@ var _arrow = {type: "=>", beforeExpr: true}, _bquote = {type: "`"}, _dollarBraceL = {type: "${", beforeExpr: true}; var _ltSlash = {type: "= 7) { var next = input.charCodeAt(tokPos); if (next === 58) { ++tokPos; - return finishToken(_doubleColon); + return finishToken(_paamayimNekudotayim); } } return finishToken(_colon); @@ -2351,23 +2358,9 @@ return finishNode(node, "AssignmentExpression"); } node.test = expr; - var consequent = node.consequent = parseExpression(true); - if (consequent.type === "BindMemberExpression" && tokType !== _colon) { - // this is a hack, revisit at a later date - if (consequent.arguments.length) { - node.alternate = { - type: "CallExpression", - arguments: consequent.arguments, - callee: consequent.property - }; - } else { - node.alternate = consequent.property; - } - node.consequent = consequent.object; - } else { - expect(_colon); - node.alternate = parseExpression(true, noIn); - } + node.consequent = parseExpression(true); + expect(_colon); + node.alternate = parseExpression(true, noIn); return finishNode(node, "ConditionalExpression"); } return expr; @@ -2447,7 +2440,7 @@ } function parseSubscripts(base, start, noCalls) { - if (options.playground && eat(_colon)) { + if (options.playground && eat(_hash)) { var node = startNodeAt(start); node.object = base; node.property = parseIdent(true); @@ -2457,7 +2450,7 @@ node.arguments = []; } return parseSubscripts(finishNode(node, "BindMemberExpression"), start, noCalls); - } else if (eat(_doubleColon)) { + } else if (eat(_paamayimNekudotayim)) { var node = startNodeAt(start); node.object = base; node.property = parseIdent(true); @@ -2651,7 +2644,7 @@ case _lt: return parseXJSElement(); - case _colon: + case _hash: return parseBindFunctionExpression(); default: diff --git a/test/tests-6to5-playground.js b/test/tests-6to5-playground.js index d8076b886c..9412804de7 100644 --- a/test/tests-6to5-playground.js +++ b/test/tests-6to5-playground.js @@ -245,95 +245,7 @@ test("obj.x ?= 2;", { // Method binding -//- Make sure conditionals still work - -test("y ? 1 : 2", { - type: "Program", - body: [ - { - type: "ExpressionStatement", - expression: { - type: "ConditionalExpression", - test: { - type: "Identifier", - name: "y", - loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 1 - } - } - }, - consequent: { - type: "Literal", - value: 1, - loc: { - start: { - line: 1, - column: 4 - }, - end: { - line: 1, - column: 5 - } - } - }, - alternate: { - type: "Literal", - value: 2, - loc: { - start: { - line: 1, - column: 8 - }, - end: { - line: 1, - column: 9 - } - } - }, - loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 9 - } - } - }, - loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 9 - } - } - } - ], - loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 9 - } - } -}, { - playground: true -}); - -test("var fn = obj:method", { +test("var fn = obj#method", { type: "Program", start: 0, end: 19, @@ -376,7 +288,7 @@ test("var fn = obj:method", { playground: true }); -test("var fn = obj:method('foo', 5)", { +test("var fn = obj#method('foo', 5)", { type: "Program", start: 0, end: 29, @@ -434,7 +346,7 @@ test("var fn = obj:method('foo', 5)", { playground: true }); -test("var fn = obj[foob]:method('foo', 5)", { +test("var fn = obj[foob]#method('foo', 5)", { type: "Program", start: 0, end: 35, @@ -504,7 +416,7 @@ test("var fn = obj[foob]:method('foo', 5)", { playground: true }); -test("var fn = obj[foob].test:method('foo', 5)", { +test("var fn = obj[foob].test#method('foo', 5)", { type: "Program", start: 0, end: 40, @@ -589,7 +501,7 @@ test("var fn = obj[foob].test:method('foo', 5)", { }); -test("arr.map(:toUpperCase)", { +test("arr.map(#toUpperCase)", { type: "Program", start: 0, end: 21, @@ -637,7 +549,7 @@ test("arr.map(:toUpperCase)", { playground: true }); -test("arr.map(:toFixed(2))", { +test("arr.map(#toFixed(2))", { type: "Program", start: 0, end: 20, From f188613e09349eed12fbd0a9352d95111493847e Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 12 Dec 2014 18:46:58 +0200 Subject: [PATCH 084/198] Add support for unknown entities (treat as ampersand + regular text). Fixes #10. --- acorn.js | 30 ++++++++++---- package.json | 2 +- test/tests-jsx.js | 101 ++++++++++++++-------------------------------- 3 files changed, 53 insertions(+), 80 deletions(-) diff --git a/acorn.js b/acorn.js index 00e9e7eaee..d1fda1ad68 100644 --- a/acorn.js +++ b/acorn.js @@ -553,6 +553,9 @@ var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); + var decimalNumber = /^\d+$/; + var hexNumber = /^[\da-fA-F]+$/; + // Whether a single character denotes a newline. var newline = /[\n\r\u2028\u2029]/; @@ -1421,22 +1424,33 @@ var str = '', count = 0, entity; var ch = nextChar(); if (ch !== '&') raise(tokPos, "Entity must start with an ampersand"); - tokPos++; + var startPos = ++tokPos; while (tokPos < inputLen && count++ < 10) { ch = nextChar(); tokPos++; if (ch === ';') { + if (str[0] === '#') { + if (str[1] === 'x') { + str = str.substr(2); + if (hexNumber.test(str)) { + entity = String.fromCharCode(parseInt(str, 16)); + } + } else { + str = str.substr(1); + if (decimalNumber.test(str)) { + entity = String.fromCharCode(parseInt(str, 10)); + } + } + } else { + entity = XHTMLEntities[str]; + } break; } str += ch; } - - if (str[0] === '#' && str[1] === 'x') { - entity = String.fromCharCode(parseInt(str.substr(2), 16)); - } else if (str[0] === '#') { - entity = String.fromCharCode(parseInt(str.substr(1), 10)); - } else { - entity = XHTMLEntities[str]; + if (!entity) { + tokPos = startPos; + return '&'; } return entity; } diff --git a/package.json b/package.json index 68ff13bc04..3c795c66b2 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-jsx", "description": "Alternative React JSX parser", "main": "acorn.js", - "version": "0.9.1-6", + "version": "0.9.1-7", "maintainers": [ { "name": "Marijn Haverbeke", diff --git a/test/tests-jsx.js b/test/tests-jsx.js index a07f0aea2e..1d76af0f14 100644 --- a/test/tests-jsx.js +++ b/test/tests-jsx.js @@ -330,7 +330,7 @@ var fbTestFixture = { end: { line: 1, column: 40 } } }, - '': { + '': { type: "ExpressionStatement", expression: { type: "XJSElement", @@ -339,11 +339,7 @@ var fbTestFixture = { name: { type: "XJSIdentifier", name: "a", - range: [1, 2], - loc: { - start: { line: 1, column: 1 }, - end: { line: 1, column: 2 } - } + range: [1, 2] }, selfClosing: true, attributes: [ @@ -352,11 +348,7 @@ var fbTestFixture = { name: { type: "XJSIdentifier", name: "b", - range: [3, 4], - loc: { - start: { line: 1, column: 3 }, - end: { line: 1, column: 4 } - } + range: [3, 4] }, value: { type: "XJSExpressionContainer", @@ -364,98 +356,65 @@ var fbTestFixture = { type: "Literal", value: " ", raw: "\" \"", - range: [6, 9], - loc: { - start: { line: 1, column: 6 }, - end: { line: 1, column: 9 } - } + range: [6, 9] }, - range: [5, 10], - loc: { - start: { line: 1, column: 5 }, - end: { line: 1, column: 10 } - } + range: [5, 10] }, - range: [3, 10], - loc: { - start: { line: 1, column: 3 }, - end: { line: 1, column: 10 } - } + range: [3, 10] }, { type: "XJSAttribute", name: { type: "XJSIdentifier", name: "c", - range: [11, 12], - loc: { - start: { line: 1, column: 11 }, - end: { line: 1, column: 12 } - } + range: [11, 12] }, value: { type: "Literal", value: " ", raw: "\" \"", - range: [13, 16], - loc: { - start: { line: 1, column: 13 }, - end: { line: 1, column: 16 } - } + range: [13, 16] }, - range: [11, 16], - loc: { - start: { line: 1, column: 11 }, - end: { line: 1, column: 16 } - } + range: [11, 16] }, { type: "XJSAttribute", name: { type: "XJSIdentifier", name: "d", - range: [17, 18], - loc: { - start: { line: 1, column: 17 }, - end: { line: 1, column: 18 } - } + range: [17, 18] }, value: { type: "Literal", value: "&", raw: "\"&\"", - range: [19, 26], - loc: { - start: { line: 1, column: 19 }, - end: { line: 1, column: 26 } - } + range: [19, 26] }, - range: [17, 26], - loc: { - start: { line: 1, column: 17 }, - end: { line: 1, column: 26 } - } + range: [17, 26] + }, + { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "e", + range: [27, 28] + }, + value: { + type: "Literal", + value: "&r;", + raw: "\"&r;\"", + range: [29, 37] + }, + range: [27, 37] } ], - range: [0, 29], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 29 } - } + range: [0, 40] }, closingElement: null, children: [], - range: [0, 29], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 29 } - } + range: [0, 40] }, - range: [0, 29], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 29 } - } + range: [0, 40] }, '': { type: "ExpressionStatement", From 24115acee0aa11b39a30bf1643d7899877f5cb18 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 13 Dec 2014 04:52:53 +1100 Subject: [PATCH 085/198] Add flow type support --- acorn.js | 723 ++- test/tests-jsx.js | 13770 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 12003 insertions(+), 2490 deletions(-) diff --git a/acorn.js b/acorn.js index d1fda1ad68..f52a97fea7 100644 --- a/acorn.js +++ b/acorn.js @@ -296,7 +296,7 @@ // `strict` indicates whether strict mode is on. var inFunction, inGenerator, labels, strict, - inXJSChild, inXJSTag; + inXJSChild, inXJSTag, inType; // This counter is used for checking that arrow expressions did // not contain nested parentheses in argument list. @@ -610,7 +610,7 @@ } tokRegexpAllowed = true; metParenL = 0; - inTemplate = inXJSChild = inXJSTag = false; + inTemplate = inType = inXJSChild = inXJSTag = false; } // Called at the end of every token. Sets `tokEnd`, `tokVal`, and @@ -773,7 +773,7 @@ function readToken_lt_gt(code) { // '<>' var next = input.charCodeAt(tokPos + 1); var size = 1; - if (next === code) { + if (!inType && next === code) { size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2; if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1); return finishOp(_bitShift, size); @@ -1941,9 +1941,25 @@ // Identifier node, we switch to interpreting it as a label. default: var maybeName = tokVal, expr = parseExpression(); - if (starttype === _name && expr.type === "Identifier" && eat(_colon)) - return parseLabeledStatement(node, maybeName, expr); - else return parseExpressionStatement(node, expr); + if (starttype === _name && expr.type === "Identifier") { + if (eat(_colon)) { + return parseLabeledStatement(node, maybeName, expr); + } + + if (expr.name === "declare") { + if (tokType === _class || tokType === _name || tokType === _function || tokType === _var) { + return parseDeclare(node); + } + } else if (tokType === _name) { + if (expr.name === "interface") { + return parseInterface(node); + } else if (expr.name === "type") { + return parseTypeAlias(node); + } + } + } + + return parseExpressionStatement(node, expr); } } @@ -2228,6 +2244,12 @@ var decl = startNode(); decl.id = options.ecmaVersion >= 6 ? toAssignable(parseExprAtom()) : parseIdent(); checkLVal(decl.id, true); + + if (tokType === _colon) { + decl.id.typeAnnotation = parseTypeAnnotation(); + finishNode(decl.id, decl.id.type); + } + decl.init = eat(_eq) ? parseExpression(true, noIn) : (kind === _const.keyword ? unexpected() : null); node.declarations.push(finishNode(decl, "VariableDeclarator")); if (!eat(_comma)) break; @@ -2262,9 +2284,9 @@ // Parse an assignment expression. This includes applications of // operators like `+=`. - function parseMaybeAssign(noIn) { + function parseMaybeAssign(noIn, noLess) { var start = storeCurrentPos(); - var left = parseMaybeConditional(noIn); + var left = parseMaybeConditional(noIn, noLess); if (tokType.isAssign) { var node = startNodeAt(start); node.operator = tokVal; @@ -2279,9 +2301,9 @@ // Parse a ternary conditional (`?:`) operator. - function parseMaybeConditional(noIn) { + function parseMaybeConditional(noIn, noLess) { var start = storeCurrentPos(); - var expr = parseExprOps(noIn); + var expr = parseExprOps(noIn, noLess); if (eat(_question)) { var node = startNodeAt(start); node.test = expr; @@ -2295,9 +2317,9 @@ // Start the precedence parser. - function parseExprOps(noIn) { + function parseExprOps(noIn, noLess) { var start = storeCurrentPos(); - return parseExprOp(parseMaybeUnary(), start, -1, noIn); + return parseExprOp(parseMaybeUnary(), start, -1, noIn, noLess); } // Parse binary operators with the operator precedence parsing @@ -2306,9 +2328,9 @@ // defer further parser to one of its callers when it encounters an // operator that has a lower precedence than the set it is parsing. - function parseExprOp(left, leftStart, minPrec, noIn) { + function parseExprOp(left, leftStart, minPrec, noIn, noLess) { var prec = tokType.binop; - if (prec != null && (!noIn || tokType !== _in)) { + if (prec != null && (!noIn || tokType !== _in) && (!noLess || tokType !== _lt)) { if (prec > minPrec) { var node = startNodeAt(leftStart); node.left = left; @@ -2575,6 +2597,11 @@ isGenerator = eat(_star); } parsePropertyName(prop); + var typeParameters + if (tokType === _lt) { + typeParameters = parseTypeParameterDeclaration(); + if (tokType !== _parenL) unexpected(); + } if (eat(_colon)) { prop.value = parseExpression(true); prop.kind = "init"; @@ -2594,6 +2621,7 @@ prop.shorthand = true; } else unexpected(); + prop.value.typeParameters = typeParameters; checkPropClash(prop, propHash); node.properties.push(finishNode(prop, "Property")); } @@ -2637,6 +2665,9 @@ if (isStatement || tokType === _name) { node.id = parseIdent(); } + if (tokType === _lt) { + node.typeParameters = parseTypeParameterDeclaration(); + } parseFunctionParams(node); parseFunctionBody(node, allowExpressionBody); return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression"); @@ -2695,7 +2726,7 @@ function parseFunctionParams(node) { var defaults = [], hasDefaults = false; - + expect(_parenL); for (;;) { if (eat(_parenR)) { @@ -2703,11 +2734,15 @@ } else if (options.ecmaVersion >= 6 && eat(_ellipsis)) { node.rest = toAssignable(parseExprAtom(), false, true); checkSpreadAssign(node.rest); + parseFunctionParam(node.rest); expect(_parenR); defaults.push(null); break; } else { - node.params.push(options.ecmaVersion >= 6 ? toAssignable(parseExprAtom(), false, true) : parseIdent()); + var param = options.ecmaVersion >= 6 ? toAssignable(parseExprAtom(), false, true) : parseIdent(); + parseFunctionParam(param); + node.params.push(param); + if (options.ecmaVersion >= 6) { if (eat(_eq)) { hasDefaults = true; @@ -2724,6 +2759,19 @@ } if (hasDefaults) node.defaults = defaults; + + if (tokType === _colon) { + node.returnType = parseTypeAnnotation(); + } + } + + function parseFunctionParam(param) { + if (tokType === _colon) { + param.typeAnnotation = parseTypeAnnotation(); + } else if (eat(_question)) { + param.optional = true; + } + finishNode(param, param.type); } // Parse function body and check parameters. @@ -2739,7 +2787,7 @@ // flag (restore them to their old value afterwards). var oldInFunc = inFunction, oldInGen = inGenerator, oldLabels = labels; inFunction = true; inGenerator = node.generator; labels = []; - node.body = parseBlock(true); + node.body = parseBlock(true); node.expression = false; inFunction = oldInFunc; inGenerator = oldInGen; labels = oldLabels; } @@ -2764,7 +2812,17 @@ function parseClass(node, isStatement) { next(); node.id = tokType === _name ? parseIdent() : isStatement ? unexpected() : null; - node.superClass = eat(_extends) ? parseExpression() : null; + if (tokType === _lt) { + node.typeParameters = parseTypeParameterDeclaration(); + } + node.superClass = eat(_extends) ? parseMaybeAssign(false, true) : null; + if (node.superClass && tokType === _lt) { + node.superTypeParameters = parseTypeParameterInstantiation(); + } + if (tokType === _name && tokVal === "implements") { + next(); + node.implements = parseClassImplements(); + } var classBody = startNode(); classBody.body = []; expect(_braceL); @@ -2786,14 +2844,42 @@ } else { method.kind = ""; } - method.value = parseMethod(isGenerator); - classBody.body.push(finishNode(method, "MethodDefinition")); - eat(_semi); + if (tokType === _colon) { + method.typeAnnotation = parseTypeAnnotation(); + semicolon(); + classBody.body.push(finishNode(method, "ClassProperty")); + } else { + var typeParameters; + if (tokType === _lt) { + typeParameters = parseTypeParameterDeclaration(); + } + method.value = parseMethod(isGenerator); + method.value.typeParameters = typeParameters; + classBody.body.push(finishNode(method, "MethodDefinition")); + eat(_semi); + } } node.body = finishNode(classBody, "ClassBody"); return finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression"); } + function parseClassImplements() { + var implemented = []; + + do { + var node = startNode(); + node.id = parseIdent(); + if (tokType === _lt) { + node.typeParameters = parseTypeParameterInstantiation(); + } else { + node.typeParameters = null; + } + implemented.push(finishNode(node, "ClassImplements")); + } while(eat(_comma)); + + return implemented; + } + // Parses a comma-separated list of expressions, and returns them as // an array. `close` is the token type that ends the list, and // `allowEmpty` can be turned on to allow subsequent commas with @@ -3338,4 +3424,599 @@ return finishNode(node, "XJSElement"); } + // Declare + + function parseDeclareClass(node) { + next(); + parseInterfaceish(node, true); + return finishNode(node, "DeclareClass"); + } + + function parseDeclareFunction(node) { + next(); + + var id = node.id = parseIdent(); + + var typeNode = startNode(); + var typeContainer = startNode(); + + if (tokType === _lt) { + typeNode.typeParameters = parseTypeParameterDeclaration(); + } else { + typeNode.typeParameters = null; + } + + expect(_parenL); + var tmp = parseFunctionTypeParams(); + typeNode.params = tmp.params; + typeNode.rest = tmp.rest; + expect(_parenR); + + expect(_colon); + typeNode.returnType = parseType(); + + typeContainer.typeAnnotation = finishNode(typeNode, "FunctionTypeAnnotation"); + id.typeAnnotation = finishNode(typeContainer, "TypeAnnotation"); + + finishNode(id, id.type); + + semicolon(); + + return finishNode(node, "DeclareFunction"); + } + + function parseDeclare(node) { + if (tokType === _class) { + return parseDeclareClass(node); + } else if (tokType === _function) { + return parseDeclareFunction(node); + } else if (tokType === _var) { + return parseDeclareVariable(node); + } else if (tokType === _name && tokVal === "module") { + return parseDeclareModule(node); + } else { + unexpected(); + } + } + + function parseDeclareVariable(node) { + next(); + node.id = parseTypeAnnotatableIdentifier(); + semicolon(); + return finishNode(node, "DeclareVariable"); + } + + function parseDeclareModule(node) { + next(); + + if (tokType === _string) { + node.id = parseExprAtom(); + } else { + node.id = parseIdent(); + } + + var bodyNode = node.body = startNode(); + var body = bodyNode.body = []; + expect(_braceL); + while (tokType !== _braceR) { + var node2 = startNode(); + + // todo: declare check + next(); + + body.push(parseDeclare(node2)); + } + expect(_braceR); + + finishNode(bodyNode, "BlockStatement"); + return finishNode(node, "DeclareModule"); + } + + + // Interfaces + + function parseInterfaceish(node, allowStatic) { + node.id = parseIdent(); + if (tokType === _lt) { + node.typeParameters = parseTypeParameterDeclaration(); + } else { + node.typeParameters = null; + } + + node.extends = []; + + if (eat(_extends)) { + do { + node.extends.push(parseInterfaceExtends()); + } while(eat(_comma)); + } + + node.body = parseObjectType(allowStatic); + } + + function parseInterfaceExtends() { + var node = startNode(); + + node.id = parseIdent(); + if (tokType === _lt) { + node.typeParameters = parseTypeParameterInstantiation(); + } else { + node.typeParameters = null; + } + + return finishNode(node, "InterfaceExtends"); + } + + function parseInterface(node) { + parseInterfaceish(node, false); + return finishNode(node, "InterfaceDeclaration"); + } + + // Type aliases + + function parseTypeAlias(node) { + node.id = parseIdent(); + + if (tokType === _lt) { + node.typeParameters = parseTypeParameterDeclaration(); + } else { + node.typeParameters = null; + } + + expect(_eq); + + node.right = parseType(); + + semicolon(); + + return finishNode(node, "TypeAlias"); + } + + // Type annotations + + function parseTypeParameterDeclaration() { + var node = startNode(); + node.params = []; + + expect(_lt); + while (tokType !== _gt) { + node.params.push(parseIdent()); + if (tokType !== _gt) { + expect(_comma); + } + } + expect(_gt); + + return finishNode(node, "TypeParameterDeclaration"); + } + + function parseTypeParameterInstantiation() { + var node = startNode(), oldInType = inType; + node.params = []; + + inType = true; + + expect(_lt); + while (tokType !== _gt) { + node.params.push(parseType()); + if (tokType !== _gt) { + expect(_comma); + } + } + expect(_gt); + + inType = oldInType; + + return finishNode(node, "TypeParameterInstantiation"); + } + + function parseObjectPropertyKey() { + return (tokType === _num || tokType === _string) ? parseExprAtom() : parseIdent(true);; + } + + function parseObjectTypeIndexer(node, isStatic) { + node.static = isStatic; + + expect(_bracketL); + node.id = parseObjectPropertyKey(); + expect(_colon); + node.key = parseType(); + expect(_bracketR); + expect(_colon); + node.value = parseType(); + + return finishNode(node, "ObjectTypeIndexer"); + } + + function parseObjectTypeMethodish(node) { + node.params = []; + node.rest = null; + node.typeParameters = null; + + if (tokType === _lt) { + node.typeParameters = parseTypeParameterDeclaration(); + } + + expect(_parenL); + while (tokType === _name) { + node.params.push(parseFunctionTypeParam()); + if (tokType !== _parenR) { + expect(_comma); + } + } + + if (eat(_ellipsis)) { + node.rest = parseFunctionTypeParam(); + } + expect(_parenR); + expect(_colon); + node.returnType = parseType(); + + return finishNode(node, "FunctionTypeAnnotation"); + } + + function parseObjectTypeMethod(start, isStatic, key) { + var node = startNodeAt(start); + node.value = parseObjectTypeMethodish(startNodeAt(start)); + node.static = isStatic; + node.key = key; + node.optional = false; + return finishNode(node, "ObjectTypeProperty"); + } + + function parseObjectTypeCallProperty(node, isStatic) { + var valueNode = startNode(); + node.static = isStatic; + node.value = parseObjectTypeMethodish(valueNode); + return finishNode(node, "ObjectTypeCallProperty"); + } + + function parseObjectType(allowStatic) { + var nodeStart = startNode(); + var node; + var optional = false; + var property; + var propertyKey; + var propertyTypeAnnotation; + var token; + var isStatic; + + nodeStart.callProperties = []; + nodeStart.properties = []; + nodeStart.indexers = []; + + expect(_braceL); + + while (tokType !== _braceR) { + var start = storeCurrentPos(); + node = startNode(); + if (allowStatic && tokType === _name && tokVal === "static") { + next(); + isStatic = true; + } + + if (tokType === _bracketL) { + nodeStart.indexers.push(parseObjectTypeIndexer(node, isStatic)); + } else if (tokType === _parenL || tokType === _lt) { + nodeStart.callProperties.push(parseObjectTypeCallProperty(node, allowStatic)); + } else { + if (isStatic && tokType === _colon) { + propertyKey = parseIdent(); + } else { + propertyKey = parseObjectPropertyKey(); + } + if (tokType === _lt || tokType === _parenL) { + // This is a method property + nodeStart.properties.push(parseObjectTypeMethod(start, isStatic, propertyKey)); + } else { + if (eat(_question)) { + optional = true; + } + expect(_colon); + node.key = propertyKey; + node.value = parseType(); + node.optional = optional; + node.static = isStatic; + nodeStart.properties.push(finishNode(node, "ObjectTypeProperty")); + } + } + + if (!eat(_semi) && tokType !== _braceR) { + unexpected(); + } + } + + expect(_braceR); + + return finishNode(nodeStart, "ObjectTypeAnnotation") + } + + function parseGenericType(start, id) { + var node = startNodeAt(start); + + node.typeParameters = null; + node.id = id; + + while (eat(_dot)) { + var node2 = startNodeAt(start); + node2.qualification = node.id; + node2.id = parseIdent(); + node.id = finishNode(node2, "QualifiedTypeIdentifier"); + } + + if (tokType === _lt) { + node.typeParameters = parseTypeParameterInstantiation(); + } + + return finishNode(node, "GenericTypeAnnotation"); + } + + function parseVoidType() { + var node = startNode(); + expect(keywordTypes["void"]); + return finishNode(node, "VoidTypeAnnotation"); + } + + function parseTypeofType() { + var node = startNode(); + expect(keywordTypes["typeof"]); + node.argument = parsePrimaryType(); + return finishNode(node, "TypeofTypeAnnotation"); + } + + function parseTupleType() { + var node = startNode(); + node.types = []; + expect(_bracketL); + // We allow trailing commas + while (tokPos < inputLen && tokType !== _bracketR) { + node.types.push(parseType()); + if (tokType === _bracketR) break; + expect(_comma); + } + expect(_bracketR); + return finishNode(node, "TupleTypeAnnotation"); + } + + function parseFunctionTypeParam() { + var optional = false; + var node = startNode(); + node.name = parseIdent(); + if (eat(_question)) { + optional = true; + } + expect(_colon); + node.optional = optional; + node.typeAnnotation = parseType(); + return finishNode(node, "FunctionTypeParam"); + } + + function parseFunctionTypeParams() { + var ret = { params: [], rest: null }; + while (tokType === _name) { + ret.params.push(parseFunctionTypeParam()); + if (tokType !== _parenR) { + expect(_comma); + } + } + + if (eat(_ellipsis)) { + ret.rest = parseFunctionTypeParam(); + } + return ret; + } + + function identToTypeAnnotation(start, node, id) { + switch (id.name) { + case 'any': + return finishNode(node, "AnyTypeAnnotation"); + + case 'bool': + case 'boolean': + return finishNode(node, "BooleanTypeAnnotation"); + + case 'number': + return finishNode(node, "NumberTypeAnnotation"); + + case 'string': + return finishNode(node, "StringTypeAnnotation"); + + default: + return parseGenericType(start, id); + } + } + + // The parsing of types roughly parallels the parsing of expressions, and + // primary types are kind of like primary expressions...they're the + // primitives with which other types are constructed. + function parsePrimaryType() { + var typeIdentifier = null; + var params = null; + var returnType = null; + var start = storeCurrentPos(); + var node = startNode(); + var rest = null; + var tmp; + var typeParameters; + var token; + var type; + var isGroupedType = false; + + switch (tokType) { + case _name: + return identToTypeAnnotation(start, node, parseIdent()); + + case _braceL: + return parseObjectType(); + + case _bracketL: + return parseTupleType(); + + case _lt: + node.typeParameters = parseTypeParameterDeclaration(); + expect(_parenL); + tmp = parseFunctionTypeParams(); + node.params = tmp.params; + node.rest = tmp.rest; + expect(_parenR); + + expect(_arrow); + + node.returnType = parseType(); + + return finishNode(node, "FunctionTypeAnnotation"); + + case _parenL: + next(); + + var tmpId; + + // Check to see if this is actually a grouped type + if (tokType !== _parenR && tokType !== _ellipsis) { + if (tokType === _name) { + //tmpId = identToTypeAnnotation(start, node, parseIdent()); + //next(); + //isGroupedType = tokType !== _question && tokType !== _colon; + } else { + isGroupedType = true; + } + } + + if (isGroupedType) { + if (tmpId && _parenR) { + type = tmpId; + } else { + type = parseType(); + expect(_parenR); + } + + // If we see a => next then someone was probably confused about + // function types, so we can provide a better error message + if (eat(_arrow)) { + raise(node, + 'Unexpected token =>. It looks like ' + + 'you are trying to write a function type, but you ended up ' + + 'writing a grouped type followed by an =>, which is a syntax ' + + 'error. Remember, function type parameters are named so function ' + + 'types look like (name1: type1, name2: type2) => returnType. You ' + + 'probably wrote (type1) => returnType' + ); + } + + return type; + } + + tmp = parseFunctionTypeParams(); + node.params = tmp.params; + node.rest = tmp.rest; + + expect(_parenR); + + expect(_arrow); + + node.returnType = parseType(); + node.typeParameters = null; + + return finishNode(node, "FunctionTypeAnnotation"); + + case _string: + node.value = tokVal; + node.raw = input.slice(tokStart, tokEnd); + next(); + return finishNode(node, "StringLiteralTypeAnnotation"); + + default: + if (tokType.keyword) { + switch (tokType.keyword) { + case 'void': + return parseVoidType(); + + case 'typeof': + return parseTypeofType(); + } + } + } + + unexpected(); + } + + function parsePostfixType() { + var node = startNode(); + var type = node.elementType = parsePrimaryType(); + if (tokType === _bracketL) { + expect(_bracketL); + expect(_bracketR); + return finishNode(node, "ArrayTypeAnnotation"); + } + return type; + } + + function parsePrefixType() { + var node = startNode(); + if (eat(_question)) { + node.typeAnnotation = parsePrefixType(); + return finishNode(node, "NullableTypeAnnotation"); + } + return parsePostfixType(); + } + + function parseIntersectionType() { + var node = startNode(); + var type = parsePrefixType(); + node.types = [type]; + while (eat(_bitwiseAND)) { + node.types.push(parsePrefixType()); + } + return node.types.length === 1 ? type : finishNode(node, "IntersectionTypeAnnotation"); + } + + function parseUnionType() { + var node = startNode(); + var type = parseIntersectionType(); + node.types = [type]; + while (eat(_bitwiseOR)) { + node.types.push(parseIntersectionType()); + } + return node.types.length === 1 ? type : finishNode(node, "UnionTypeAnnotation"); + } + + function parseType() { + var oldInType = inType; + inType = true; + var type = parseUnionType(); + inType = oldInType; + return type; + } + + function parseTypeAnnotation() { + var node = startNode(); + + expect(_colon); + node.typeAnnotation = parseType(); + + return finishNode(node, "TypeAnnotation"); + } + + function parseTypeAnnotatableIdentifier(requireTypeAnnotation, canBeOptionalParam) { + var node = startNode(); + var ident = parseIdent(); + var isOptionalParam = false; + + if (canBeOptionalParam && eat(_question)) { + expect(_question); + isOptionalParam = true; + } + + if (requireTypeAnnotation || tokType === _colon) { + ident.typeAnnotation = parseTypeAnnotation(); + finishNode(ident, ident.type); + } + + if (isOptionalParam) { + ident.optional = true; + finishNode(ident, ident.type); + } + + return ident; + } }); diff --git a/test/tests-jsx.js b/test/tests-jsx.js index 1d76af0f14..8d45dbf1e7 100644 --- a/test/tests-jsx.js +++ b/test/tests-jsx.js @@ -1,9 +1,9 @@ // React JSX tests var fbTestFixture = { - // Taken and adapted from esprima-fb/fbtest.js. - 'XJS': { - '': { + // Taken and adapted from esprima-fb/fbtest.rec.js. + "XJS": { + "": { type: "ExpressionStatement", expression: { type: "XJSElement", @@ -40,17 +40,17 @@ var fbTestFixture = { end: { line: 1, column: 5 } } }, - '': { - type: 'ExpressionStatement', + "": { + type: "ExpressionStatement", expression: { - type: 'XJSElement', + type: "XJSElement", openingElement: { - type: 'XJSOpeningElement', + type: "XJSOpeningElement", name: { - type: 'XJSNamespacedName', + type: "XJSNamespacedName", namespace: { - type: 'XJSIdentifier', - name: 'n', + type: "XJSIdentifier", + name: "n", range: [1, 2], loc: { start: { line: 1, column: 1 }, @@ -58,8 +58,8 @@ var fbTestFixture = { } }, name: { - type: 'XJSIdentifier', - name: 'a', + type: "XJSIdentifier", + name: "a", range: [3, 4], loc: { start: { line: 1, column: 3 }, @@ -74,12 +74,12 @@ var fbTestFixture = { }, selfClosing: true, attributes: [{ - type: 'XJSAttribute', + type: "XJSAttribute", name: { - type: 'XJSNamespacedName', + type: "XJSNamespacedName", namespace: { - type: 'XJSIdentifier', - name: 'n', + type: "XJSIdentifier", + name: "n", range: [5, 6], loc: { start: { line: 1, column: 5 }, @@ -87,8 +87,8 @@ var fbTestFixture = { } }, name: { - type: 'XJSIdentifier', - name: 'v', + type: "XJSIdentifier", + name: "v", range: [7, 8], loc: { start: { line: 1, column: 7 }, @@ -129,14 +129,14 @@ var fbTestFixture = { } }, ' {value} ': { - type: 'ExpressionStatement', + type: "ExpressionStatement", expression: { - type: 'XJSElement', + type: "XJSElement", openingElement: { - type: 'XJSOpeningElement', + type: "XJSOpeningElement", name: { - type: 'XJSIdentifier', - name: 'a', + type: "XJSIdentifier", + name: "a", range: [1, 2], loc: { start: { line: 1, column: 1 }, @@ -145,12 +145,12 @@ var fbTestFixture = { }, selfClosing: false, attributes: [{ - type: 'XJSAttribute', + type: "XJSAttribute", name: { - type: 'XJSNamespacedName', + type: "XJSNamespacedName", namespace: { - type: 'XJSIdentifier', - name: 'n', + type: "XJSIdentifier", + name: "n", range: [3, 4], loc: { start: { line: 1, column: 3 }, @@ -158,8 +158,8 @@ var fbTestFixture = { } }, name: { - type: 'XJSIdentifier', - name: 'foo', + type: "XJSIdentifier", + name: "foo", range: [5, 8], loc: { start: { line: 1, column: 5 }, @@ -173,8 +173,8 @@ var fbTestFixture = { } }, value: { - type: 'Literal', - value: 'bar', + type: "Literal", + value: "bar", raw: '"bar"', range: [9, 14], loc: { @@ -195,10 +195,10 @@ var fbTestFixture = { } }, closingElement: { - type: 'XJSClosingElement', + type: "XJSClosingElement", name: { - type: 'XJSIdentifier', - name: 'a', + type: "XJSIdentifier", + name: "a", range: [38, 39], loc: { start: { line: 1, column: 38 }, @@ -212,19 +212,19 @@ var fbTestFixture = { } }, children: [{ - type: 'Literal', - value: ' ', - raw: ' ', + type: "Literal", + value: " ", + raw: " ", range: [15, 16], loc: { start: { line: 1, column: 15 }, end: { line: 1, column: 16 } } }, { - type: 'XJSExpressionContainer', + type: "XJSExpressionContainer", expression: { - type: 'Identifier', - name: 'value', + type: "Identifier", + name: "value", range: [17, 22], loc: { start: { line: 1, column: 17 }, @@ -237,21 +237,21 @@ var fbTestFixture = { end: { line: 1, column: 23 } } }, { - type: 'Literal', - value: ' ', - raw: ' ', + type: "Literal", + value: " ", + raw: " ", range: [23, 24], loc: { start: { line: 1, column: 23 }, end: { line: 1, column: 24 } } }, { - type: 'XJSElement', + type: "XJSElement", openingElement: { - type: 'XJSOpeningElement', + type: "XJSOpeningElement", name: { - type: 'XJSIdentifier', - name: 'b', + type: "XJSIdentifier", + name: "b", range: [25, 26], loc: { start: { line: 1, column: 25 }, @@ -267,10 +267,10 @@ var fbTestFixture = { } }, closingElement: { - type: 'XJSClosingElement', + type: "XJSClosingElement", name: { - type: 'XJSIdentifier', - name: 'b', + type: "XJSIdentifier", + name: "b", range: [34, 35], loc: { start: { line: 1, column: 34 }, @@ -284,12 +284,12 @@ var fbTestFixture = { } }, children: [{ - type: 'XJSElement', + type: "XJSElement", openingElement: { - type: 'XJSOpeningElement', + type: "XJSOpeningElement", name: { - type: 'XJSIdentifier', - name: 'c', + type: "XJSIdentifier", + name: "c", range: [28, 29], loc: { start: { line: 1, column: 28 }, @@ -330,7 +330,7 @@ var fbTestFixture = { end: { line: 1, column: 40 } } }, - '': { + '': { type: "ExpressionStatement", expression: { type: "XJSElement", @@ -342,445 +342,218 @@ var fbTestFixture = { range: [1, 2] }, selfClosing: true, - attributes: [ - { - type: "XJSAttribute", - name: { - type: "XJSIdentifier", - name: "b", - range: [3, 4] - }, - value: { - type: "XJSExpressionContainer", - expression: { - type: "Literal", - value: " ", - raw: "\" \"", - range: [6, 9] - }, - range: [5, 10] - }, - range: [3, 10] + attributes: [{ + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "b", + range: [3, 4], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } }, - { - type: "XJSAttribute", - name: { - type: "XJSIdentifier", - name: "c", - range: [11, 12] - }, - value: { + value: { + type: "XJSExpressionContainer", + expression: { type: "Literal", value: " ", - raw: "\" \"", - range: [13, 16] - }, - range: [11, 16] - }, - { - type: "XJSAttribute", - name: { - type: "XJSIdentifier", - name: "d", - range: [17, 18] - }, - value: { - type: "Literal", - value: "&", - raw: "\"&\"", - range: [19, 26] - }, - range: [17, 26] - }, - { - type: "XJSAttribute", - name: { - type: "XJSIdentifier", - name: "e", - range: [27, 28] - }, - value: { - type: "Literal", - value: "&r;", - raw: "\"&r;\"", - range: [29, 37] - }, - range: [27, 37] - } - ], - range: [0, 40] - }, - closingElement: null, - children: [], - range: [0, 40] - }, - range: [0, 40] - }, - '': { - type: "ExpressionStatement", - expression: { - type: "XJSElement", - openingElement: { - type: "XJSOpeningElement", - name: { - type: "XJSIdentifier", - name: "a", - range: [ - 1, - 2 - ], - loc: { - start: { - line: 1, - column: 1 - }, - end: { - line: 1, - column: 2 - } - } - }, - selfClosing: true, - attributes: [], - range: [ - 0, - 5 - ], - loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 2, - column: 2 - } - } - }, - closingElement: null, - children: [], - range: [ - 0, - 5 - ], - loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 2, - column: 2 - } - } - }, - range: [ - 0, - 5 - ], - loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 2, - column: 2 - } - } - }, - '<日本語>': { - type: "ExpressionStatement", - expression: { - type: "XJSElement", - openingElement: { - type: "XJSOpeningElement", - name: { - type: "XJSIdentifier", - name: "日本語", - range: [ - 1, - 4 - ], - loc: { - start: { - line: 1, - column: 1 - }, - end: { - line: 1, - column: 4 - } - } - }, - selfClosing: false, - attributes: [], - range: [ - 0, - 5 - ], - loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 5 - } - } - }, - closingElement: { - type: "XJSClosingElement", - name: { - type: "XJSIdentifier", - name: "日本語", - range: [ - 7, - 10 - ], - loc: { - start: { - line: 1, - column: 7 - }, - end: { - line: 1, - column: 10 - } - } - }, - range: [ - 5, - 11 - ], - loc: { - start: { - line: 1, - column: 5 - }, - end: { - line: 1, - column: 11 - } - } - }, - children: [], - range: [ - 0, - 11 - ], - loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 11 - } - } - }, - range: [ - 0, - 11 - ], - loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 11 - } - } - }, - - '\nbar\nbaz\n': { - type: "ExpressionStatement", - expression: { - type: "XJSElement", - openingElement: { - type: "XJSOpeningElement", - name: { - type: "XJSIdentifier", - name: "AbC-def", - range: [ - 1, - 8 - ], - loc: { - start: { - line: 1, - column: 1 - }, - end: { - line: 1, - column: 8 - } - } - }, - selfClosing: false, - attributes: [ - { - type: "XJSAttribute", - name: { - type: "XJSIdentifier", - name: "test", - range: [ - 11, - 15 - ], + raw: '" "', + range: [6, 9], loc: { - start: { - line: 2, - column: 2 - }, - end: { - line: 2, - column: 6 - } + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } } }, - value: { - type: "Literal", - value: "&&", - raw: "\"&&\"", - range: [ - 16, - 31 - ], - loc: { - start: { - line: 2, - column: 7 - }, - end: { - line: 2, - column: 22 - } - } - }, - range: [ - 11, - 31 - ], + range: [5, 10], loc: { - start: { - line: 2, - column: 2 - }, - end: { - line: 2, - column: 22 - } + start: { line: 1, column: 5 }, + end: { line: 1, column: 10 } } - } - ], - range: [ - 0, - 32 - ], - loc: { - start: { - line: 1, - column: 0 }, - end: { - line: 2, - column: 23 + range: [3, 10], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 10 } } + }, { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "c", + range: [11, 12], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + value: { + type: "Literal", + value: " ", + raw: '" "', + range: [13, 16], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 16 } + } + }, + range: [11, 16], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 16 } + } + }, { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "d", + range: [17, 18], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }, + value: { + type: "Literal", + value: "&", + raw: '"&"', + range: [19, 26], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 26 } + } + }, + range: [17, 26], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 26 } + } + }, { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "e", + range: [27, 28], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 28 } + } + }, + value: { + type: "Literal", + value: "id=1&group=2", + raw: '"id=1&group=2"', + range: [29, 43], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 43 } + } + }, + range: [27, 43], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 43 } + } + }, { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "f", + range: [44, 45], + loc: { + start: { line: 1, column: 44 }, + end: { line: 1, column: 45 } + } + }, + value: { + type: "Literal", + value: "�", + raw: '"�"', + range: [46, 59], + loc: { + start: { line: 1, column: 46 }, + end: { line: 1, column: 59 } + } + }, + range: [44, 59], + loc: { + start: { line: 1, column: 44 }, + end: { line: 1, column: 59 } + } + }, { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "g", + range: [60, 61], + loc: { + start: { line: 1, column: 60 }, + end: { line: 1, column: 61 } + } + }, + value: { + type: "Literal", + value: "{*;", + raw: '"{*;"', + range: [62, 71], + loc: { + start: { line: 1, column: 62 }, + end: { line: 1, column: 71 } + } + }, + range: [60, 71], + loc: { + start: { line: 1, column: 60 }, + end: { line: 1, column: 71 } + } + }, { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "h", + range: [72, 73], + loc: { + start: { line: 1, column: 72 }, + end: { line: 1, column: 73 } + } + }, + value: { + type: "Literal", + value: "&#x;", + raw: '"&#x;"', + range: [74, 80], + loc: { + start: { line: 1, column: 74 }, + end: { line: 1, column: 80 } + } + }, + range: [72, 80], + loc: { + start: { line: 1, column: 72 }, + end: { line: 1, column: 80 } + } + }], + range: [0, 83], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 83 } } }, - closingElement: { - type: "XJSClosingElement", - name: { - type: "XJSIdentifier", - name: "AbC-def", - range: [ - 43, - 50 - ], - loc: { - start: { - line: 5, - column: 2 - }, - end: { - line: 5, - column: 9 - } - } - }, - range: [ - 41, - 51 - ], - loc: { - start: { - line: 5, - column: 0 - }, - end: { - line: 5, - column: 10 - } - } - }, - children: [ - { - type: "Literal", - value: "\nbar\nbaz\n", - raw: "\nbar\nbaz\n", - range: [ - 32, - 41 - ], - loc: { - start: { - line: 2, - column: 23 - }, - end: { - line: 5, - column: 0 - } - } - } - ], - range: [ - 0, - 51 - ], + closingElement: null, + children: [], + range: [0, 83], loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 5, - column: 10 - } + start: { line: 1, column: 0 }, + end: { line: 1, column: 83 } } }, - range: [ - 0, - 51 - ], + range: [0, 83], loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 5, - column: 10 - } + start: { line: 1, column: 0 }, + end: { line: 1, column: 83 } } }, - - ' : } />': { + '': { type: "ExpressionStatement", expression: { type: "XJSElement", @@ -789,280 +562,383 @@ var fbTestFixture = { name: { type: "XJSIdentifier", name: "a", - range: [ - 1, - 2 - ], + range: [1, 2], loc: { - start: { - line: 1, - column: 1 - }, - end: { - line: 1, - column: 2 - } + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } } }, selfClosing: true, - attributes: [ - { - type: "XJSAttribute", - name: { - type: "XJSIdentifier", - name: "b", - range: [ - 3, - 4 - ], - loc: { - start: { - line: 1, - column: 3 - }, - end: { - line: 1, - column: 4 - } - } - }, - value: { - type: "XJSExpressionContainer", - expression: { - type: "ConditionalExpression", - test: { - type: "Identifier", - name: "x", - range: [ - 6, - 7 - ], - loc: { - start: { - line: 1, - column: 6 - }, - end: { - line: 1, - column: 7 - } - } - }, - consequent: { - type: "XJSElement", - openingElement: { - type: "XJSOpeningElement", - name: { - type: "XJSIdentifier", - name: "c", - range: [ - 11, - 12 - ], - loc: { - start: { - line: 1, - column: 11 - }, - end: { - line: 1, - column: 12 - } - } - }, - selfClosing: true, - attributes: [], - range: [ - 10, - 15 - ], - loc: { - start: { - line: 1, - column: 10 - }, - end: { - line: 1, - column: 15 - } - } - }, - closingElement: null, - children: [], - range: [ - 10, - 15 - ], - loc: { - start: { - line: 1, - column: 10 - }, - end: { - line: 1, - column: 15 - } - } - }, - alternate: { - type: "XJSElement", - openingElement: { - type: "XJSOpeningElement", - name: { - type: "XJSIdentifier", - name: "d", - range: [ - 19, - 20 - ], - loc: { - start: { - line: 1, - column: 19 - }, - end: { - line: 1, - column: 20 - } - } - }, - selfClosing: true, - attributes: [], - range: [ - 18, - 23 - ], - loc: { - start: { - line: 1, - column: 18 - }, - end: { - line: 1, - column: 23 - } - } - }, - closingElement: null, - children: [], - range: [ - 18, - 23 - ], - loc: { - start: { - line: 1, - column: 18 - }, - end: { - line: 1, - column: 23 - } - } - }, - range: [ - 6, - 23 - ], + attributes: [{ + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "b", + range: [3, 4], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + value: { + type: "Literal", + value: "¬anentity;", + raw: '"¬anentity;"', + range: [5, 20], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 20 } + } + }, + range: [3, 20], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 20 } + } + }], + range: [0, 23], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + } + }, + closingElement: null, + children: [], + range: [0, 23], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + } + }, + range: [0, 23], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + } + }, + "": { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "a", + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + selfClosing: true, + attributes: [], + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 2 } + } + }, + closingElement: null, + children: [], + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 2 } + } + }, + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 2 } + } + }, + "<日本語>": { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "日本語", + range: [1, 4], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 4 } + } + }, + selfClosing: false, + attributes: [], + range: [0, 5], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + closingElement: { + type: "XJSClosingElement", + name: { + type: "XJSIdentifier", + name: "日本語", + range: [7, 10], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 10 } + } + }, + range: [5, 11], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 11 } + } + }, + children: [], + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + '\nbar\nbaz\r\n': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "AbC-def", + range: [1, 8], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 8 } + } + }, + selfClosing: false, + attributes: [{ + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "test", + range: [11, 15], + loc: { + start: { line: 2, column: 2 }, + end: { line: 2, column: 6 } + } + }, + value: { + type: "Literal", + value: "&&", + raw: '"&&"', + range: [16, 31], + loc: { + start: { line: 2, column: 7 }, + end: { line: 2, column: 22 } + } + }, + range: [11, 31], + loc: { + start: { line: 2, column: 2 }, + end: { line: 2, column: 22 } + } + }], + range: [0, 32], + loc: { + start: { line: 1, column: 0 }, + end: { line: 2, column: 23 } + } + }, + closingElement: { + type: "XJSClosingElement", + name: { + type: "XJSIdentifier", + name: "AbC-def", + range: [44, 51], + loc: { + start: { line: 5, column: 2 }, + end: { line: 5, column: 9 } + } + }, + range: [42, 52], + loc: { + start: { line: 5, column: 0 }, + end: { line: 5, column: 10 } + } + }, + children: [{ + type: "Literal", + value: "\nbar\nbaz\r\n", + raw: "\nbar\nbaz\r\n", + range: [32, 42], + loc: { + start: { line: 2, column: 23 }, + end: { line: 5, column: 0 } + } + }], + range: [0, 52], + loc: { + start: { line: 1, column: 0 }, + end: { line: 5, column: 10 } + } + }, + range: [0, 52], + loc: { + start: { line: 1, column: 0 }, + end: { line: 5, column: 10 } + } + }, + " : } />": { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "a", + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + selfClosing: true, + attributes: [{ + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "b", + range: [3, 4], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + value: { + type: "XJSExpressionContainer", + expression: { + type: "ConditionalExpression", + test: { + type: "Identifier", + name: "x", + range: [6, 7], loc: { - start: { - line: 1, - column: 6 - }, - end: { - line: 1, - column: 23 - } + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } } }, - range: [ - 5, - 24 - ], - loc: { - start: { - line: 1, - column: 5 + consequent: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "c", + range: [11, 12], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + selfClosing: true, + attributes: [], + range: [10, 15], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 15 } + } }, - end: { - line: 1, - column: 24 + closingElement: null, + children: [], + range: [10, 15], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 15 } } + }, + alternate: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "d", + range: [19, 20], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 20 } + } + }, + selfClosing: true, + attributes: [], + range: [18, 23], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 23 } + } + }, + closingElement: null, + children: [], + range: [18, 23], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 23 } + } + }, + range: [6, 23], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 23 } } }, - range: [ - 3, - 24 - ], + range: [5, 24], loc: { - start: { - line: 1, - column: 3 - }, - end: { - line: 1, - column: 24 - } + start: { line: 1, column: 5 }, + end: { line: 1, column: 24 } } - } - ], - range: [ - 0, - 27 - ], - loc: { - start: { - line: 1, - column: 0 }, - end: { - line: 1, - column: 27 + range: [3, 24], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 24 } } + }], + range: [0, 27], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } } }, closingElement: null, children: [], - range: [ - 0, - 27 - ], + range: [0, 27], loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 27 - } + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } } }, - range: [ - 0, - 27 - ], + range: [0, 27], loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 27 - } + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } } }, - - '{}': { - type: 'ExpressionStatement', + "{}": { + type: "ExpressionStatement", expression: { - type: 'XJSElement', + type: "XJSElement", openingElement: { - type: 'XJSOpeningElement', + type: "XJSOpeningElement", name: { - type: 'XJSIdentifier', - name: 'a', + type: "XJSIdentifier", + name: "a", range: [1, 2], loc: { start: { line: 1, column: 1 }, @@ -1078,10 +954,10 @@ var fbTestFixture = { } }, closingElement: { - type: 'XJSClosingElement', + type: "XJSClosingElement", name: { - type: 'XJSIdentifier', - name: 'a', + type: "XJSIdentifier", + name: "a", range: [7, 8], loc: { start: { line: 1, column: 7 }, @@ -1095,9 +971,9 @@ var fbTestFixture = { } }, children: [{ - type: 'XJSExpressionContainer', + type: "XJSExpressionContainer", expression: { - type: 'XJSEmptyExpression', + type: "XJSEmptyExpression", range: [4, 4], loc: { start: { line: 1, column: 4 }, @@ -1122,16 +998,15 @@ var fbTestFixture = { end: { line: 1, column: 9 } } }, - - '{/* this is a comment */}': { - type: 'ExpressionStatement', + "{/* this is a comment */}": { + type: "ExpressionStatement", expression: { - type: 'XJSElement', + type: "XJSElement", openingElement: { - type: 'XJSOpeningElement', + type: "XJSOpeningElement", name: { - type: 'XJSIdentifier', - name: 'a', + type: "XJSIdentifier", + name: "a", range: [1, 2], loc: { start: { line: 1, column: 1 }, @@ -1147,10 +1022,10 @@ var fbTestFixture = { } }, closingElement: { - type: 'XJSClosingElement', + type: "XJSClosingElement", name: { - type: 'XJSIdentifier', - name: 'a', + type: "XJSIdentifier", + name: "a", range: [30, 31], loc: { start: { line: 1, column: 30 }, @@ -1164,9 +1039,9 @@ var fbTestFixture = { } }, children: [{ - type: 'XJSExpressionContainer', + type: "XJSExpressionContainer", expression: { - type: 'XJSEmptyExpression', + type: "XJSEmptyExpression", range: [4, 27], loc: { start: { line: 1, column: 4 }, @@ -1191,16 +1066,15 @@ var fbTestFixture = { end: { line: 1, column: 32 } } }, - - '
    @test content
    ': { - type: 'ExpressionStatement', + "
    @test content
    ": { + type: "ExpressionStatement", expression: { - type: 'XJSElement', + type: "XJSElement", openingElement: { - type: 'XJSOpeningElement', + type: "XJSOpeningElement", name: { - type: 'XJSIdentifier', - name: 'div', + type: "XJSIdentifier", + name: "div", range: [1, 4], loc: { start: { line: 1, column: 1 }, @@ -1216,10 +1090,10 @@ var fbTestFixture = { } }, closingElement: { - type: 'XJSClosingElement', + type: "XJSClosingElement", name: { - type: 'XJSIdentifier', - name: 'div', + type: "XJSIdentifier", + name: "div", range: [20, 23], loc: { start: { line: 1, column: 20 }, @@ -1233,9 +1107,9 @@ var fbTestFixture = { } }, children: [{ - type: 'Literal', - value: '@test content', - raw: '@test content', + type: "Literal", + value: "@test content", + raw: "@test content", range: [5, 18], loc: { start: { line: 1, column: 5 }, @@ -1254,510 +1128,259 @@ var fbTestFixture = { end: { line: 1, column: 24 } } }, - - '

    7x invalid-js-identifier
    ': { - type: 'ExpressionStatement', + "

    7x invalid-js-identifier
    ": { + type: "ExpressionStatement", expression: { - type: 'XJSElement', + type: "XJSElement", openingElement: { - type: 'XJSOpeningElement', + type: "XJSOpeningElement", name: { - type: 'XJSIdentifier', - name: 'div', - range: [ - 1, - 4 - ], + type: "XJSIdentifier", + name: "div", + range: [1, 4], loc: { - start: { - line: 1, - column: 1 - }, - end: { - line: 1, - column: 4 - } + start: { line: 1, column: 1 }, + end: { line: 1, column: 4 } } }, selfClosing: false, attributes: [], - range: [ - 0, - 5 - ], + range: [0, 5], loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 5 - } + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } } }, closingElement: { - type: 'XJSClosingElement', + type: "XJSClosingElement", name: { - type: 'XJSIdentifier', - name: 'div', - range: [ - 37, - 40 - ], + type: "XJSIdentifier", + name: "div", + range: [37, 40], loc: { - start: { - line: 1, - column: 37 - }, - end: { - line: 1, - column: 40 - } + start: { line: 1, column: 37 }, + end: { line: 1, column: 40 } } }, - range: [ - 35, - 41 - ], + range: [35, 41], loc: { - start: { - line: 1, - column: 35 - }, - end: { - line: 1, - column: 41 - } + start: { line: 1, column: 35 }, + end: { line: 1, column: 41 } } }, children: [{ - type: 'XJSElement', + type: "XJSElement", openingElement: { - type: 'XJSOpeningElement', + type: "XJSOpeningElement", name: { - type: 'XJSIdentifier', - name: 'br', - range: [ - 6, - 8 - ], + type: "XJSIdentifier", + name: "br", + range: [6, 8], loc: { - start: { - line: 1, - column: 6 - }, - end: { - line: 1, - column: 8 - } + start: { line: 1, column: 6 }, + end: { line: 1, column: 8 } } }, selfClosing: true, attributes: [], - range: [ - 5, - 11 - ], + range: [5, 11], loc: { - start: { - line: 1, - column: 5 - }, - end: { - line: 1, - column: 11 - } + start: { line: 1, column: 5 }, + end: { line: 1, column: 11 } } }, closingElement: null, children: [], - range: [ - 5, - 11 - ], + range: [5, 11], loc: { - start: { - line: 1, - column: 5 - }, - end: { - line: 1, - column: 11 - } + start: { line: 1, column: 5 }, + end: { line: 1, column: 11 } } }, { - type: 'Literal', - value: '7x invalid-js-identifier', - raw: '7x invalid-js-identifier', - range: [ - 11, - 35 - ], + type: "Literal", + value: "7x invalid-js-identifier", + raw: "7x invalid-js-identifier", + range: [11, 35], loc: { - start: { - line: 1, - column: 11 - }, - end: { - line: 1, - column: 35 - } + start: { line: 1, column: 11 }, + end: { line: 1, column: 35 } } }], - range: [ - 0, - 41 - ], + range: [0, 41], loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 41 - } + start: { line: 1, column: 0 }, + end: { line: 1, column: 41 } } }, - range: [ - 0, - 41 - ], + range: [0, 41], loc: { - start: { - line: 1, - column: 0 - }, - end: { - line: 1, - column: 41 - } + start: { line: 1, column: 0 }, + end: { line: 1, column: 41 } } }, - - ' right=monkeys /> gorillas />': { - "type": "ExpressionStatement", - "expression": { - "type": "XJSElement", - "openingElement": { - "type": "XJSOpeningElement", - "name": { - "type": "XJSIdentifier", - "name": "LeftRight", - "range": [ - 1, - 10 - ], - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 10 - } + " right=monkeys /> gorillas />": { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "LeftRight", + range: [1, 10], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 10 } } }, - "selfClosing": true, - "attributes": [ - { - "type": "XJSAttribute", - "name": { - "type": "XJSIdentifier", - "name": "left", - "range": [ - 11, - 15 - ], - "loc": { - "start": { - "line": 1, - "column": 11 - }, - "end": { - "line": 1, - "column": 15 - } - } - }, - "value": { - "type": "XJSElement", - "openingElement": { - "type": "XJSOpeningElement", - "name": { - "type": "XJSIdentifier", - "name": "a", - "range": [ - 17, - 18 - ], - "loc": { - "start": { - "line": 1, - "column": 17 - }, - "end": { - "line": 1, - "column": 18 - } - } - }, - "selfClosing": true, - "attributes": [], - "range": [ - 16, - 21 - ], - "loc": { - "start": { - "line": 1, - "column": 16 - }, - "end": { - "line": 1, - "column": 21 - } - } - }, - closingElement: null, - "children": [], - "range": [ - 16, - 21 - ], - "loc": { - "start": { - "line": 1, - "column": 16 - }, - "end": { - "line": 1, - "column": 21 - } - } - }, - "range": [ - 11, - 21 - ], - "loc": { - "start": { - "line": 1, - "column": 11 - }, - "end": { - "line": 1, - "column": 21 - } + selfClosing: true, + attributes: [{ + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "left", + range: [11, 15], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 15 } } }, - { - "type": "XJSAttribute", - "name": { - "type": "XJSIdentifier", - "name": "right", - "range": [ - 22, - 27 - ], - "loc": { - "start": { - "line": 1, - "column": 22 - }, - "end": { - "line": 1, - "column": 27 + value: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "a", + range: [17, 18], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } } + }, + selfClosing: true, + attributes: [], + range: [16, 21], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 21 } } }, - "value": { - "type": "XJSElement", - "openingElement": { - "type": "XJSOpeningElement", - "name": { - "type": "XJSIdentifier", - "name": "b", - "range": [ - 29, - 30 - ], - "loc": { - "start": { - "line": 1, - "column": 29 - }, - "end": { - "line": 1, - "column": 30 - } - } - }, - "selfClosing": false, - "attributes": [], - "range": [ - 28, - 31 - ], - "loc": { - "start": { - "line": 1, - "column": 28 - }, - "end": { - "line": 1, - "column": 31 - } - } - }, - "closingElement": { - "type": "XJSClosingElement", - "name": { - "type": "XJSIdentifier", - "name": "b", - "range": [ - 52, - 53 - ], - "loc": { - "start": { - "line": 1, - "column": 52 - }, - "end": { - "line": 1, - "column": 53 - } - } - }, - "range": [ - 50, - 54 - ], - "loc": { - "start": { - "line": 1, - "column": 50 - }, - "end": { - "line": 1, - "column": 54 - } - } - }, - "children": [ - { - "type": "Literal", - "value": "monkeys /> gorillas", - "raw": "monkeys /> gorillas", - "range": [ - 31, - 50 - ], - "loc": { - "start": { - "line": 1, - "column": 31 - }, - "end": { - "line": 1, - "column": 50 - } - } - } - ], - "range": [ - 28, - 54 - ], - "loc": { - "start": { - "line": 1, - "column": 28 - }, - "end": { - "line": 1, - "column": 54 - } - } - }, - "range": [ - 22, - 54 - ], - "loc": { - "start": { - "line": 1, - "column": 22 - }, - "end": { - "line": 1, - "column": 54 - } + closingElement: null, + children: [], + range: [16, 21], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 21 } } - } - ], - "range": [ - 0, - 57 - ], - "loc": { - "start": { - "line": 1, - "column": 0 }, - "end": { - "line": 1, - "column": 57 + range: [11, 21], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 21 } } + }, { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "right", + range: [22, 27], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 27 } + } + }, + value: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "b", + range: [29, 30], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 30 } + } + }, + selfClosing: false, + attributes: [], + range: [28, 31], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 31 } + } + }, + closingElement: { + type: "XJSClosingElement", + name: { + type: "XJSIdentifier", + name: "b", + range: [52, 53], + loc: { + start: { line: 1, column: 52 }, + end: { line: 1, column: 53 } + } + }, + range: [50, 54], + loc: { + start: { line: 1, column: 50 }, + end: { line: 1, column: 54 } + } + }, + children: [{ + type: "Literal", + value: "monkeys /> gorillas", + raw: "monkeys /> gorillas", + range: [31, 50], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 50 } + } + }], + range: [28, 54], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 54 } + } + }, + range: [22, 54], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 54 } + } + }], + range: [0, 57], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 57 } } }, closingElement: null, - "children": [], - "range": [ - 0, - 57 - ], - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 57 - } + children: [], + range: [0, 57], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 57 } } }, - "range": [ - 0, - 57 - ], - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 57 - } + range: [0, 57], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 57 } } }, - - '': { - type: 'ExpressionStatement', + "": { + type: "ExpressionStatement", expression: { - type: 'XJSElement', + type: "XJSElement", openingElement: { - type: 'XJSOpeningElement', + type: "XJSOpeningElement", name: { - type: 'XJSMemberExpression', + type: "XJSMemberExpression", object: { - type: 'XJSIdentifier', - name: 'a', + type: "XJSIdentifier", + name: "a", range: [1, 2], loc: { start: { line: 1, column: 1 }, @@ -1765,8 +1388,8 @@ var fbTestFixture = { } }, property: { - type: 'XJSIdentifier', - name: 'b', + type: "XJSIdentifier", + name: "b", range: [3, 4], loc: { start: { line: 1, column: 3 }, @@ -1788,12 +1411,12 @@ var fbTestFixture = { } }, closingElement: { - type: 'XJSClosingElement', + type: "XJSClosingElement", name: { - type: 'XJSMemberExpression', + type: "XJSMemberExpression", object: { - type: 'XJSIdentifier', - name: 'a', + type: "XJSIdentifier", + name: "a", range: [7, 8], loc: { start: { line: 1, column: 7 }, @@ -1801,8 +1424,8 @@ var fbTestFixture = { } }, property: { - type: 'XJSIdentifier', - name: 'b', + type: "XJSIdentifier", + name: "b", range: [9, 10], loc: { start: { line: 1, column: 9 }, @@ -1834,20 +1457,19 @@ var fbTestFixture = { end: { line: 1, column: 11 } } }, - - '': { - type: 'ExpressionStatement', + "": { + type: "ExpressionStatement", expression: { - type: 'XJSElement', + type: "XJSElement", openingElement: { - type: 'XJSOpeningElement', + type: "XJSOpeningElement", name: { - type: 'XJSMemberExpression', + type: "XJSMemberExpression", object: { - type: 'XJSMemberExpression', + type: "XJSMemberExpression", object: { - type: 'XJSIdentifier', - name: 'a', + type: "XJSIdentifier", + name: "a", range: [1, 2], loc: { start: { line: 1, column: 1 }, @@ -1855,8 +1477,8 @@ var fbTestFixture = { } }, property: { - type: 'XJSIdentifier', - name: 'b', + type: "XJSIdentifier", + name: "b", range: [3, 4], loc: { start: { line: 1, column: 3 }, @@ -1870,8 +1492,8 @@ var fbTestFixture = { } }, property: { - type: 'XJSIdentifier', - name: 'c', + type: "XJSIdentifier", + name: "c", range: [5, 6], loc: { start: { line: 1, column: 5 }, @@ -1893,14 +1515,14 @@ var fbTestFixture = { } }, closingElement: { - type: 'XJSClosingElement', + type: "XJSClosingElement", name: { - type: 'XJSMemberExpression', + type: "XJSMemberExpression", object: { - type: 'XJSMemberExpression', + type: "XJSMemberExpression", object: { - type: 'XJSIdentifier', - name: 'a', + type: "XJSIdentifier", + name: "a", range: [9, 10], loc: { start: { line: 1, column: 9 }, @@ -1908,8 +1530,8 @@ var fbTestFixture = { } }, property: { - type: 'XJSIdentifier', - name: 'b', + type: "XJSIdentifier", + name: "b", range: [11, 12], loc: { start: { line: 1, column: 11 }, @@ -1923,8 +1545,8 @@ var fbTestFixture = { } }, property: { - type: 'XJSIdentifier', - name: 'c', + type: "XJSIdentifier", + name: "c", range: [13, 14], loc: { start: { line: 1, column: 13 }, @@ -1956,22 +1578,18 @@ var fbTestFixture = { end: { line: 1, column: 15 } } }, - - // In order to more useful parse errors, we disallow following an - // XJSElement by a less-than symbol. In the rare case that the binary - // operator was intended, the tag can be wrapped in parentheses: - '(
    ) < x;': { - type: 'ExpressionStatement', + "(
    ) < x;": { + type: "ExpressionStatement", expression: { - type: 'BinaryExpression', - operator: '<', + type: "BinaryExpression", + operator: "<", left: { - type: 'XJSElement', + type: "XJSElement", openingElement: { - type: 'XJSOpeningElement', + type: "XJSOpeningElement", name: { - type: 'XJSIdentifier', - name: 'div', + type: "XJSIdentifier", + name: "div", range: [2, 5], loc: { start: { line: 1, column: 2 }, @@ -1995,8 +1613,8 @@ var fbTestFixture = { } }, right: { - type: 'Identifier', - name: 'x', + type: "Identifier", + name: "x", range: [12, 13], loc: { start: { line: 1, column: 12 }, @@ -2015,1255 +1633,10077 @@ var fbTestFixture = { end: { line: 1, column: 14 } } }, - - '
    ': { - "type": "ExpressionStatement", - "expression": { - "type": "XJSElement", - "openingElement": { - "type": "XJSOpeningElement", - "name": { - "type": "XJSIdentifier", - "name": "div", - "range": [ - 1, - 4 - ], - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 4 - } - } - }, - "selfClosing": true, - "attributes": [ - { - "type": "XJSSpreadAttribute", - "argument": { - "type": "Identifier", - "name": "props", - "range": [ - 9, - 14 - ], - "loc": { - "start": { - "line": 1, - "column": 9 - }, - "end": { - "line": 1, - "column": 14 - } - } - }, - "range": [ - 5, - 15 - ], - "loc": { - "start": { - "line": 1, - "column": 5 - }, - "end": { - "line": 1, - "column": 15 - } - } - } - ], - "range": [ - 0, - 18 - ], - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 18 - } - } - }, - closingElement: null, - "children": [], - "range": [ - 0, - 18 - ], - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 18 - } - } - }, - "range": [ - 0, - 18 - ], - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 18 - } - } - }, - - '
    ': { - "type": "ExpressionStatement", - "expression": { - "type": "XJSElement", - "openingElement": { - "type": "XJSOpeningElement", - "name": { - "type": "XJSIdentifier", - "name": "div", - "range": [ - 1, - 4 - ], - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 4 - } - } - }, - "selfClosing": true, - "attributes": [ - { - "type": "XJSSpreadAttribute", - "argument": { - "type": "Identifier", - "name": "props", - "range": [ - 9, - 14 - ], - "loc": { - "start": { - "line": 1, - "column": 9 - }, - "end": { - "line": 1, - "column": 14 - } - } - }, - "range": [ - 5, - 15 - ], - "loc": { - "start": { - "line": 1, - "column": 5 - }, - "end": { - "line": 1, - "column": 15 - } - } - }, - { - "type": "XJSAttribute", - "name": { - "type": "XJSIdentifier", - "name": "post", - "range": [ - 16, - 20 - ], - "loc": { - "start": { - "line": 1, - "column": 16 - }, - "end": { - "line": 1, - "column": 20 - } - } - }, - "value": { - "type": "Literal", - "value": "attribute", - "raw": "\"attribute\"", - "range": [ - 21, - 32 - ], - "loc": { - "start": { - "line": 1, - "column": 21 - }, - "end": { - "line": 1, - "column": 32 - } - } - }, - "range": [ - 16, - 32 - ], - "loc": { - "start": { - "line": 1, - "column": 16 - }, - "end": { - "line": 1, - "column": 32 - } - } - } - ], - "range": [ - 0, - 35 - ], - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 35 - } - } - }, - closingElement: null, - "children": [], - "range": [ - 0, - 35 - ], - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 35 - } - } - }, - "range": [ - 0, - 35 - ], - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 35 - } - } - }, - - '
    ': { - "type": "ExpressionStatement", - "expression": { - "type": "XJSElement", - "openingElement": { - "type": "XJSOpeningElement", - "name": { - "type": "XJSIdentifier", - "name": "div", - "range": [ - 1, - 4 - ], - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 4 - } - } - }, - "selfClosing": false, - "attributes": [ - { - "type": "XJSAttribute", - "name": { - "type": "XJSIdentifier", - "name": "pre", - "range": [ - 5, - 8 - ], - "loc": { - "start": { - "line": 1, - "column": 5 - }, - "end": { - "line": 1, - "column": 8 - } - } - }, - "value": { - "type": "Literal", - "value": "leading", - "raw": "\"leading\"", - "range": [ - 9, - 18 - ], - "loc": { - "start": { - "line": 1, - "column": 9 - }, - "end": { - "line": 1, - "column": 18 - } - } - }, - "range": [ - 5, - 18 - ], - "loc": { - "start": { - "line": 1, - "column": 5 - }, - "end": { - "line": 1, - "column": 18 - } - } - }, - { - "type": "XJSAttribute", - "name": { - "type": "XJSIdentifier", - "name": "pre2", - "range": [ - 19, - 23 - ], - "loc": { - "start": { - "line": 1, - "column": 19 - }, - "end": { - "line": 1, - "column": 23 - } - } - }, - "value": { - "type": "Literal", - "value": "attribute", - "raw": "\"attribute\"", - "range": [ - 24, - 35 - ], - "loc": { - "start": { - "line": 1, - "column": 24 - }, - "end": { - "line": 1, - "column": 35 - } - } - }, - "range": [ - 19, - 35 - ], - "loc": { - "start": { - "line": 1, - "column": 19 - }, - "end": { - "line": 1, - "column": 35 - } - } - }, - { - "type": "XJSSpreadAttribute", - "argument": { - "type": "Identifier", - "name": "props", - "range": [ - 40, - 45 - ], - "loc": { - "start": { - "line": 1, - "column": 40 - }, - "end": { - "line": 1, - "column": 45 - } - } - }, - "range": [ - 36, - 46 - ], - "loc": { - "start": { - "line": 1, - "column": 36 - }, - "end": { - "line": 1, - "column": 46 - } - } - } - ], - "range": [ - 0, - 47 - ], - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 47 - } - } - }, - "closingElement": { - "type": "XJSClosingElement", - "name": { - "type": "XJSIdentifier", - "name": "div", - "range": [ - 49, - 52 - ], - "loc": { - "start": { - "line": 1, - "column": 49 - }, - "end": { - "line": 1, - "column": 52 - } - } - }, - "range": [ - 47, - 53 - ], - "loc": { - "start": { - "line": 1, - "column": 47 - }, - "end": { - "line": 1, - "column": 53 - } - } - }, - "children": [], - "range": [ - 0, - 53 - ], - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 53 - } - } - }, - "range": [ - 0, - 53 - ], - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 53 - } - } - }, - '
    {aa.b}
    ': { - "type": "ExpressionStatement", - "start": 0, - "end": 52, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 52 - } - }, - "range": [ - 0, - 52 - ], - "expression": { - "type": "XJSElement", - "start": 0, - "end": 52, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 52 - } - }, - "range": [ - 0, - 52 - ], - "openingElement": { - "type": "XJSOpeningElement", - "start": 0, - "end": 31, - "loc": { - "start": { - "line": 1, - "column": 0 - }, - "end": { - "line": 1, - "column": 31 - } - }, - "range": [ - 0, - 31 - ], - "attributes": [ - { - "type": "XJSAttribute", - "start": 3, - "end": 16, - "loc": { - "start": { - "line": 1, - "column": 3 - }, - "end": { - "line": 1, - "column": 16 - } - }, - "range": [ - 3, - 16 - ], - "name": { - "type": "XJSIdentifier", - "start": 3, - "end": 5, - "loc": { - "start": { - "line": 1, - "column": 3 - }, - "end": { - "line": 1, - "column": 5 - } - }, - "range": [ - 3, - 5 - ], - "name": "aa" - }, - "value": { - "type": "XJSExpressionContainer", - "start": 6, - "end": 16, - "loc": { - "start": { - "line": 1, - "column": 6 - }, - "end": { - "line": 1, - "column": 16 - } - }, - "range": [ - 6, - 16 - ], - "expression": { - "type": "MemberExpression", - "start": 7, - "end": 15, - "loc": { - "start": { - "line": 1, - "column": 7 - }, - "end": { - "line": 1, - "column": 15 - } - }, - "range": [ - 7, - 15 - ], - "object": { - "type": "MemberExpression", - "start": 7, - "end": 12, - "loc": { - "start": { - "line": 1, - "column": 7 - }, - "end": { - "line": 1, - "column": 12 - } - }, - "range": [ - 7, - 12 - ], - "object": { - "type": "Identifier", - "start": 7, - "end": 9, - "loc": { - "start": { - "line": 1, - "column": 7 - }, - "end": { - "line": 1, - "column": 9 - } - }, - "range": [ - 7, - 9 - ], - "name": "aa" - }, - "property": { - "type": "Identifier", - "start": 10, - "end": 12, - "loc": { - "start": { - "line": 1, - "column": 10 - }, - "end": { - "line": 1, - "column": 12 - } - }, - "range": [ - 10, - 12 - ], - "name": "bb" - }, - "computed": false - }, - "property": { - "type": "Identifier", - "start": 13, - "end": 15, - "loc": { - "start": { - "line": 1, - "column": 13 - }, - "end": { - "line": 1, - "column": 15 - } - }, - "range": [ - 13, - 15 - ], - "name": "cc" - }, - "computed": false - } - } - }, - { - "type": "XJSAttribute", - "start": 17, - "end": 30, - "loc": { - "start": { - "line": 1, - "column": 17 - }, - "end": { - "line": 1, - "column": 30 - } - }, - "range": [ - 17, - 30 - ], - "name": { - "type": "XJSIdentifier", - "start": 17, - "end": 19, - "loc": { - "start": { - "line": 1, - "column": 17 - }, - "end": { - "line": 1, - "column": 19 - } - }, - "range": [ - 17, - 19 - ], - "name": "bb" - }, - "value": { - "type": "XJSExpressionContainer", - "start": 20, - "end": 30, - "loc": { - "start": { - "line": 1, - "column": 20 - }, - "end": { - "line": 1, - "column": 30 - } - }, - "range": [ - 20, - 30 - ], - "expression": { - "type": "MemberExpression", - "start": 21, - "end": 29, - "loc": { - "start": { - "line": 1, - "column": 21 - }, - "end": { - "line": 1, - "column": 29 - } - }, - "range": [ - 21, - 29 - ], - "object": { - "type": "MemberExpression", - "start": 21, - "end": 26, - "loc": { - "start": { - "line": 1, - "column": 21 - }, - "end": { - "line": 1, - "column": 26 - } - }, - "range": [ - 21, - 26 - ], - "object": { - "type": "Identifier", - "start": 21, - "end": 23, - "loc": { - "start": { - "line": 1, - "column": 21 - }, - "end": { - "line": 1, - "column": 23 - } - }, - "range": [ - 21, - 23 - ], - "name": "bb" - }, - "property": { - "type": "Identifier", - "start": 24, - "end": 26, - "loc": { - "start": { - "line": 1, - "column": 24 - }, - "end": { - "line": 1, - "column": 26 - } - }, - "range": [ - 24, - 26 - ], - "name": "cc" - }, - "computed": false - }, - "property": { - "type": "Identifier", - "start": 27, - "end": 29, - "loc": { - "start": { - "line": 1, - "column": 27 - }, - "end": { - "line": 1, - "column": 29 - } - }, - "range": [ - 27, - 29 - ], - "name": "dd" - }, - "computed": false - } - } - } - ], - "name": { - "type": "XJSIdentifier", - "start": 1, - "end": 2, - "loc": { - "start": { - "line": 1, - "column": 1 - }, - "end": { - "line": 1, - "column": 2 - } - }, - "range": [ - 1, - 2 - ], - "name": "A" - }, - "selfClosing": false - }, - "closingElement": { - "type": "XJSClosingElement", - "start": 48, - "end": 52, - "loc": { - "start": { - "line": 1, - "column": 48 - }, - "end": { - "line": 1, - "column": 52 - } - }, - "range": [ - 48, - 52 - ], - "name": { - "type": "XJSIdentifier", - "start": 50, - "end": 51, - "loc": { - "start": { - "line": 1, - "column": 50 - }, - "end": { - "line": 1, - "column": 51 - } - }, - "range": [ - 50, - 51 - ], - "name": "A" - } - }, - "children": [ - { - "type": "XJSElement", - "start": 31, - "end": 48, - "loc": { - "start": { - "line": 1, - "column": 31 - }, - "end": { - "line": 1, - "column": 48 - } - }, - "range": [ - 31, - 48 - ], - "openingElement": { - "type": "XJSOpeningElement", - "start": 31, - "end": 36, - "loc": { - "start": { - "line": 1, - "column": 31 - }, - "end": { - "line": 1, - "column": 36 - } - }, - "range": [ - 31, - 36 - ], - "attributes": [], - "name": { - "type": "XJSIdentifier", - "start": 32, - "end": 35, - "loc": { - "start": { - "line": 1, - "column": 32 - }, - "end": { - "line": 1, - "column": 35 - } - }, - "range": [ - 32, - 35 - ], - "name": "div" - }, - "selfClosing": false - }, - "closingElement": { - "type": "XJSClosingElement", - "start": 42, - "end": 48, - "loc": { - "start": { - "line": 1, - "column": 42 - }, - "end": { - "line": 1, - "column": 48 - } - }, - "range": [ - 42, - 48 - ], - "name": { - "type": "XJSIdentifier", - "start": 44, - "end": 47, - "loc": { - "start": { - "line": 1, - "column": 44 - }, - "end": { - "line": 1, - "column": 47 - } - }, - "range": [ - 44, - 47 - ], - "name": "div" - } - }, - "children": [ - { - "type": "XJSExpressionContainer", - "start": 36, - "end": 42, - "loc": { - "start": { - "line": 1, - "column": 36 - }, - "end": { - "line": 1, - "column": 42 - } - }, - "range": [ - 36, - 42 - ], - "expression": { - "type": "MemberExpression", - "start": 37, - "end": 41, - "loc": { - "start": { - "line": 1, - "column": 37 - }, - "end": { - "line": 1, - "column": 41 - } - }, - "range": [ - 37, - 41 - ], - "object": { - "type": "Identifier", - "start": 37, - "end": 39, - "loc": { - "start": { - "line": 1, - "column": 37 - }, - "end": { - "line": 1, - "column": 39 - } - }, - "range": [ - 37, - 39 - ], - "name": "aa" - }, - "property": { - "type": "Identifier", - "start": 40, - "end": 41, - "loc": { - "start": { - "line": 1, - "column": 40 - }, - "end": { - "line": 1, - "column": 41 - } - }, - "range": [ - 40, - 41 - ], - "name": "b" - }, - "computed": false - } - } - ] - } - ] - } - } - }, - 'Regression': { - '

    foo bar baz

    ;': { + "
    ": { type: "ExpressionStatement", - start: 0, - end: 40, expression: { type: "XJSElement", - start: 0, - end: 38, openingElement: { type: "XJSOpeningElement", - start: 0, - end: 3, - attributes: [], name: { type: "XJSIdentifier", - start: 1, - end: 2, - name: "p" + name: "div", + range: [1, 4], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 4 } + } }, - selfClosing: false + selfClosing: true, + attributes: [{ + type: "XJSSpreadAttribute", + argument: { + type: "Identifier", + name: "props", + range: [9, 14], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 14 } + } + }, + range: [5, 15], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 15 } + } + }], + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + }, + closingElement: null, + children: [], + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + }, + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + }, + '
    ': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "div", + range: [1, 4], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 4 } + } + }, + selfClosing: true, + attributes: [{ + type: "XJSSpreadAttribute", + argument: { + type: "Identifier", + name: "props", + range: [9, 14], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 14 } + } + }, + range: [5, 15], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 15 } + } + }, { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "post", + range: [16, 20], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 20 } + } + }, + value: { + type: "Literal", + value: "attribute", + raw: '"attribute"', + range: [21, 32], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 32 } + } + }, + range: [16, 32], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 32 } + } + }], + range: [0, 35], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 35 } + } + }, + closingElement: null, + children: [], + range: [0, 35], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 35 } + } + }, + range: [0, 35], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 35 } + } + }, + '
    ': { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "div", + range: [1, 4], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 4 } + } + }, + selfClosing: false, + attributes: [{ + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "pre", + range: [5, 8], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 8 } + } + }, + value: { + type: "Literal", + value: "leading", + raw: '"leading"', + range: [9, 18], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 18 } + } + }, + range: [5, 18], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 18 } + } + }, { + type: "XJSAttribute", + name: { + type: "XJSIdentifier", + name: "pre2", + range: [19, 23], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 23 } + } + }, + value: { + type: "Literal", + value: "attribute", + raw: '"attribute"', + range: [24, 35], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 35 } + } + }, + range: [19, 35], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 35 } + } + }, { + type: "XJSSpreadAttribute", + argument: { + type: "Identifier", + name: "props", + range: [40, 45], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 45 } + } + }, + range: [36, 46], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 46 } + } + }], + range: [0, 47], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 47 } + } }, closingElement: { type: "XJSClosingElement", - start: 34, - end: 38, name: { type: "XJSIdentifier", - start: 36, - end: 37, - name: "p" + name: "div", + range: [49, 52], + loc: { + start: { line: 1, column: 49 }, + end: { line: 1, column: 52 } + } + }, + range: [47, 53], + loc: { + start: { line: 1, column: 47 }, + end: { line: 1, column: 53 } } }, - children: [ - { - type: "Literal", - start: 3, - end: 7, - value: "foo ", - raw: "foo " - }, - { - type: "XJSElement", - start: 7, - end: 30, - openingElement: { - type: "XJSOpeningElement", - start: 7, - end: 22, - attributes: [{ - type: "XJSAttribute", - start: 10, - end: 21, - name: { - type: "XJSIdentifier", - start: 10, - end: 14, - name: "href" - }, - value: { - type: "Literal", - start: 15, - end: 21, - value: "test", - raw: "\"test\"" - } - }], - name: { - type: "XJSIdentifier", - start: 8, - end: 9, - name: "a" - }, - selfClosing: false - }, - closingElement: { - type: "XJSClosingElement", - start: 26, - end: 30, - name: { - type: "XJSIdentifier", - start: 28, - end: 29, - name: "a" - } - }, - children: [{ - type: "Literal", - start: 22, - end: 26, - value: " bar", - raw: " bar" - }] - }, - { - type: "Literal", - start: 30, - end: 34, - value: " baz", - raw: " baz" - } - ] + children: [], + range: [0, 53], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 53 } + } + }, + range: [0, 53], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 53 } + } + }, + " ": { + type: "ExpressionStatement", + expression: { + type: "XJSElement", + openingElement: { + type: "XJSOpeningElement", + name: { + type: "XJSIdentifier", + name: "a", + range: [1, 2], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + selfClosing: false, + attributes: [], + range: [0, 3], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + closingElement: { + type: "XJSClosingElement", + name: { + type: "XJSIdentifier", + name: "a", + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + range: [5, 9], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 9 } + } + }, + children: [{ + type: "Literal", + value: " ", + raw: " ", + range: [3, 5], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 5 } + } + }], + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + range: [0, 9], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + }, + "Type Annotations": { + "function foo(numVal: any){}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [{ + type: "Identifier", + name: "numVal", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "AnyTypeAnnotation", + range: [21, 24], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 24 } + } + }, + range: [19, 24], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 24 } + } + }, + range: [13, 24], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 24 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [25, 27], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 27 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 27], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + }, + "function foo(numVal: number){}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [{ + type: "Identifier", + name: "numVal", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [21, 27], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 27 } + } + }, + range: [19, 27], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 27 } + } + }, + range: [13, 27], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 27 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [28, 30], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 30 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 30], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 30 } + } + }, + "function foo(numVal: number, strVal: string){}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [{ + type: "Identifier", + name: "numVal", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [21, 27], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 27 } + } + }, + range: [19, 27], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 27 } + } + }, + range: [13, 27], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 27 } + } + }, { + type: "Identifier", + name: "strVal", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "StringTypeAnnotation", + range: [37, 43], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 43 } + } + }, + range: [35, 43], + loc: { + start: { line: 1, column: 35 }, + end: { line: 1, column: 43 } + } + }, + range: [29, 43], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 43 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [44, 46], + loc: { + start: { line: 1, column: 44 }, + end: { line: 1, column: 46 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 46], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 46 } + } + }, + "function foo(numVal: number, untypedVal){}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [{ + type: "Identifier", + name: "numVal", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [21, 27], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 27 } + } + }, + range: [19, 27], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 27 } + } + }, + range: [13, 27], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 27 } + } + }, { + type: "Identifier", + name: "untypedVal", + range: [29, 39], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 39 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [40, 42], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 42 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 42], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 42 } + } + }, + "function foo(untypedVal, numVal: number){}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [{ + type: "Identifier", + name: "untypedVal", + range: [13, 23], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 23 } + } + }, { + type: "Identifier", + name: "numVal", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [33, 39], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 39 } + } + }, + range: [31, 39], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 39 } + } + }, + range: [25, 39], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 39 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [40, 42], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 42 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 42], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 42 } + } + }, + "function foo(nullableNum: ?number){}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [{ + type: "Identifier", + name: "nullableNum", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NullableTypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [27, 33], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 33 } + } + }, + range: [26, 33], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 33 } + } + }, + range: [24, 33], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 33 } + } + }, + range: [13, 33], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 33 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [34, 36], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 36 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + "function foo(callback: () => void){}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [{ + type: "Identifier", + name: "callback", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "VoidTypeAnnotation", + range: [29, 33], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 33 } + } + }, + rest: null, + typeParameters: null, + range: [23, 33], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 33 } + } + }, + range: [21, 33], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 33 } + } + }, + range: [13, 33], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 33 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [34, 36], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 36 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + "function foo(callback: () => number){}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [{ + type: "Identifier", + name: "callback", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "NumberTypeAnnotation", + range: [29, 35], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 35 } + } + }, + rest: null, + typeParameters: null, + range: [23, 35], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 35 } + } + }, + range: [21, 35], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 35 } + } + }, + range: [13, 35], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 35 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [36, 38], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 38 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 38], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + } + }, + "function foo(callback: (_:bool) => number){}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [{ + type: "Identifier", + name: "callback", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [{ + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "_", + range: [24, 25], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 25 } + } + }, + typeAnnotation: { + type: "BooleanTypeAnnotation", + range: [26, 30], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 30 } + } + }, + optional: false, + range: [24, 30], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 30 } + } + }], + returnType: { + type: "NumberTypeAnnotation", + range: [35, 41], + loc: { + start: { line: 1, column: 35 }, + end: { line: 1, column: 41 } + } + }, + rest: null, + typeParameters: null, + range: [23, 41], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 41 } + } + }, + range: [21, 41], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 41 } + } + }, + range: [13, 41], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 41 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [42, 44], + loc: { + start: { line: 1, column: 42 }, + end: { line: 1, column: 44 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 44], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 44 } + } + }, + "function foo(callback: (_1:bool, _2:string) => number){}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [{ + type: "Identifier", + name: "callback", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [{ + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "_1", + range: [24, 26], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 26 } + } + }, + typeAnnotation: { + type: "BooleanTypeAnnotation", + range: [27, 31], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 31 } + } + }, + optional: false, + range: [24, 31], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 31 } + } + }, { + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "_2", + range: [33, 35], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 35 } + } + }, + typeAnnotation: { + type: "StringTypeAnnotation", + range: [36, 42], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 42 } + } + }, + optional: false, + range: [33, 42], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 42 } + } + }], + returnType: { + type: "NumberTypeAnnotation", + range: [47, 53], + loc: { + start: { line: 1, column: 47 }, + end: { line: 1, column: 53 } + } + }, + rest: null, + typeParameters: null, + range: [23, 53], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 53 } + } + }, + range: [21, 53], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 53 } + } + }, + range: [13, 53], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 53 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [54, 56], + loc: { + start: { line: 1, column: 54 }, + end: { line: 1, column: 56 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 56], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 56 } + } + }, + "function foo(callback: (_1:bool, ...foo:Array) => number){}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [{ + type: "Identifier", + name: "callback", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [{ + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "_1", + range: [24, 26], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 26 } + } + }, + typeAnnotation: { + type: "BooleanTypeAnnotation", + range: [27, 31], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 31 } + } + }, + optional: false, + range: [24, 31], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 31 } + } + }], + returnType: { + type: "NumberTypeAnnotation", + range: [58, 64], + loc: { + start: { line: 1, column: 58 }, + end: { line: 1, column: 64 } + } + }, + rest: { + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "foo", + range: [36, 39], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 39 } + } + }, + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Array", + range: [40, 45], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 45 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "NumberTypeAnnotation", + range: [46, 52], + loc: { + start: { line: 1, column: 46 }, + end: { line: 1, column: 52 } + } + }], + range: [45, 53], + loc: { + start: { line: 1, column: 45 }, + end: { line: 1, column: 53 } + } + }, + range: [40, 53], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 53 } + } + }, + optional: false, + range: [36, 53], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 53 } + } + }, + typeParameters: null, + range: [23, 64], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 64 } + } + }, + range: [21, 64], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 64 } + } + }, + range: [13, 64], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 64 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [65, 67], + loc: { + start: { line: 1, column: 65 }, + end: { line: 1, column: 67 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 67], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 67 } + } + }, + "function foo():number{}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [21, 23], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 23 } + } + }, + rest: null, + generator: false, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [15, 21], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 21 } + } + }, + range: [14, 21], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 21 } + } + }, + range: [0, 23], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + } + }, + "function foo():() => void{}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [25, 27], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 27 } + } + }, + rest: null, + generator: false, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "VoidTypeAnnotation", + range: [21, 25], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 25 } + } + }, + rest: null, + typeParameters: null, + range: [15, 25], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 25 } + } + }, + range: [14, 25], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 25 } + } + }, + range: [0, 27], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + }, + "function foo():(_:bool) => number{}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [33, 35], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 35 } + } + }, + rest: null, + generator: false, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [{ + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "_", + range: [16, 17], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + }, + typeAnnotation: { + type: "BooleanTypeAnnotation", + range: [18, 22], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 22 } + } + }, + optional: false, + range: [16, 22], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 22 } + } + }], + returnType: { + type: "NumberTypeAnnotation", + range: [27, 33], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 33 } + } + }, + rest: null, + typeParameters: null, + range: [15, 33], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 33 } + } + }, + range: [14, 33], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 33 } + } + }, + range: [0, 35], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 35 } + } + }, + "function foo():(_?:bool) => number{}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [34, 36], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 36 } + } + }, + rest: null, + generator: false, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [{ + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "_", + range: [16, 17], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + }, + typeAnnotation: { + type: "BooleanTypeAnnotation", + range: [19, 23], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 23 } + } + }, + optional: true, + range: [16, 23], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 23 } + } + }], + returnType: { + type: "NumberTypeAnnotation", + range: [28, 34], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 34 } + } + }, + rest: null, + typeParameters: null, + range: [15, 34], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 34 } + } + }, + range: [14, 34], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 34 } + } + }, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + "function foo(): {} {}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [19, 21], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 21 } + } + }, + rest: null, + generator: false, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [], + indexers: [], + callProperties: [], + range: [16, 18], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 18 } + } + }, + range: [14, 18], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 18 } + } + }, + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + "function foo() {}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [18, 20], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 20 } + } + }, + rest: null, + generator: false, + expression: false, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }], + range: [12, 15], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 15 } + } + }, + range: [0, 20], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + "function foo() {}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [20, 22], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 22 } + } + }, + rest: null, + generator: false, + expression: false, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }, { + type: "Identifier", + name: "S", + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }], + range: [12, 17], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 17 } + } + }, + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + "a=function() {}": { + type: "ExpressionStatement", + expression: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "Identifier", + name: "a", + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: "FunctionExpression", + id: null, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [18, 20], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 20 } + } + }, + rest: null, + generator: false, + expression: false, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [11, 12], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, { + type: "Identifier", + name: "S", + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }], + range: [10, 15], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 15 } + } + }, + range: [2, 20], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 20 } + } + }, + range: [0, 20], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + range: [0, 20], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + "a={set fooProp(value:number){}}": { + type: "ExpressionStatement", + expression: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "Identifier", + name: "a", + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: "ObjectExpression", + properties: [{ + type: "Property", + key: { + type: "Identifier", + name: "fooProp", + range: [7, 14], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [{ + type: "Identifier", + name: "value", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [21, 27], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 27 } + } + }, + range: [20, 27], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 27 } + } + }, + range: [15, 27], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 27 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [28, 30], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 30 } + } + }, + rest: null, + generator: false, + expression: false, + //range: [28, 30], + //loc: { + // start: { line: 1, column: 28 }, + // end: { line: 1, column: 30 } + //} + }, + kind: "set", + method: false, + shorthand: false, + computed: false, + range: [3, 30], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 30 } + } + }], + range: [2, 31], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 31 } + } + }, + range: [0, 31], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 31 } + } + }, + range: [0, 31], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 31 } + } + }, + "a={set fooProp(value:number):void{}}": { + type: "ExpressionStatement", + expression: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "Identifier", + name: "a", + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: "ObjectExpression", + properties: [{ + type: "Property", + key: { + type: "Identifier", + name: "fooProp", + range: [7, 14], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [{ + type: "Identifier", + name: "value", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [21, 27], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 27 } + } + }, + range: [20, 27], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 27 } + } + }, + range: [15, 27], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 27 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [33, 35], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 35 } + } + }, + rest: null, + generator: false, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "VoidTypeAnnotation", + range: [29, 33], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 33 } + } + }, + range: [28, 33], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 33 } + } + }, + //range: [33, 35], + //loc: { + // start: { line: 1, column: 33 }, + // end: { line: 1, column: 35 } + //} + }, + kind: "set", + method: false, + shorthand: false, + computed: false, + range: [3, 35], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 35 } + } + }], + range: [2, 36], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 36 } + } + }, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + "a={get fooProp():number{}}": { + type: "ExpressionStatement", + expression: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "Identifier", + name: "a", + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: "ObjectExpression", + properties: [{ + type: "Property", + key: { + type: "Identifier", + name: "fooProp", + range: [7, 14], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [23, 25], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 25 } + } + }, + rest: null, + generator: false, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [17, 23], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 23 } + } + }, + range: [16, 23], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 23 } + } + }, + //range: [23, 25], + //loc: { + // start: { line: 1, column: 23 }, + // end: { line: 1, column: 25 } + //} + }, + kind: "get", + method: false, + shorthand: false, + computed: false, + range: [3, 25], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 25 } + } + }], + range: [2, 26], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 26 } + } + }, + range: [0, 26], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 26 } + } + }, + range: [0, 26], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 26 } + } + }, + "a={id(x: T): T {}}": { + type: "ExpressionStatement", + expression: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "Identifier", + name: "a", + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: "ObjectExpression", + properties: [{ + type: "Property", + key: { + type: "Identifier", + name: "id", + range: [3, 5], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 5 } + } + }, + value: { + type: "FunctionExpression", + //id: null, + params: [{ + type: "Identifier", + name: "x", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + typeParameters: null, + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + range: [10, 13], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 13 } + } + }, + range: [9, 13], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 13 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [18, 20], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 20 } + } + }, + rest: null, + generator: false, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [16, 17], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + }, + typeParameters: null, + range: [16, 17], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + }, + range: [14, 17], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 17 } + } + }, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [6, 7], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }], + range: [5, 8], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 8 } + } + }, + //range: [18, 20], + //loc: { + // start: { line: 1, column: 18 }, + // end: { line: 1, column: 20 } + //} + }, + kind: "init", + method: true, + shorthand: false, + computed: false, + range: [3, 20], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 20 } + } + }], + range: [2, 21], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 21 } + } + }, + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + "a={*id(x: T): T {}}": { + type: "ExpressionStatement", + expression: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "Identifier", + name: "a", + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: "ObjectExpression", + properties: [{ + type: "Property", + key: { + type: "Identifier", + name: "id", + range: [4, 6], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 6 } + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [{ + type: "Identifier", + name: "x", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }, + typeParameters: null, + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }, + range: [11, 14], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 14 } + } + }, + range: [10, 14], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 14 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [19, 21], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 21 } + } + }, + rest: null, + generator: true, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [17, 18], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }, + typeParameters: null, + range: [17, 18], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }, + range: [15, 18], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 18 } + } + }, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }], + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + //range: [19, 21], + //loc: { + // start: { line: 1, column: 19 }, + // end: { line: 1, column: 21 } + //} + }, + kind: "init", + method: true, + shorthand: false, + computed: false, + //range: [3, 21], + //loc: { + // start: { line: 1, column: 3 }, + // end: { line: 1, column: 21 } + //} + }], + range: [2, 22], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 22 } + } + }, + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + "a={123(x: T): T {}}": { + type: "ExpressionStatement", + expression: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "Identifier", + name: "a", + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: "ObjectExpression", + properties: [{ + type: "Property", + key: { + type: "Literal", + value: 123, + raw: "123", + range: [3, 6], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 6 } + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [{ + type: "Identifier", + name: "x", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }, + typeParameters: null, + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }, + range: [11, 14], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 14 } + } + }, + range: [10, 14], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 14 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [19, 21], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 21 } + } + }, + rest: null, + generator: false, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [17, 18], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }, + typeParameters: null, + range: [17, 18], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }, + range: [15, 18], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 18 } + } + }, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [7, 8], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }], + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + //range: [19, 21], + //loc: { + // start: { line: 1, column: 19 }, + // end: { line: 1, column: 21 } + //} + }, + kind: "init", + method: true, + shorthand: false, + computed: false, + range: [3, 21], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 21 } + } + }], + range: [2, 22], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 22 } + } + }, + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + "class Foo {set fooProp(value:number){}}": { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [{ + type: "MethodDefinition", + key: { + type: "Identifier", + name: "fooProp", + range: [15, 22], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 22 } + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [{ + type: "Identifier", + name: "value", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [29, 35], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 35 } + } + }, + range: [28, 35], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 35 } + } + }, + range: [23, 35], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 35 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [36, 38], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 38 } + } + }, + rest: null, + generator: false, + expression: false, + //range: [36, 38], + //loc: { + // start: { line: 1, column: 36 }, + // end: { line: 1, column: 38 } + //} + }, + kind: "set", + "static": false, + computed: false, + range: [11, 38], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 38 } + } + }], + range: [10, 39], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 39 } + } + }, + range: [0, 39], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 39 } + } + }, + "class Foo {set fooProp(value:number):void{}}": { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [{ + type: "MethodDefinition", + key: { + type: "Identifier", + name: "fooProp", + range: [15, 22], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 22 } + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [{ + type: "Identifier", + name: "value", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [29, 35], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 35 } + } + }, + range: [28, 35], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 35 } + } + }, + range: [23, 35], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 35 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [41, 43], + loc: { + start: { line: 1, column: 41 }, + end: { line: 1, column: 43 } + } + }, + rest: null, + generator: false, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "VoidTypeAnnotation", + range: [37, 41], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 41 } + } + }, + range: [36, 41], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 41 } + } + }, + //range: [41, 43], + //loc: { + // start: { line: 1, column: 41 }, + // end: { line: 1, column: 43 } + //} + }, + kind: "set", + "static": false, + computed: false, + range: [11, 43], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 43 } + } + }], + range: [10, 44], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 44 } + } + }, + range: [0, 44], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 44 } + } + }, + "class Foo {get fooProp():number{}}": { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [{ + type: "MethodDefinition", + key: { + type: "Identifier", + name: "fooProp", + range: [15, 22], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 22 } + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [31, 33], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 33 } + } + }, + rest: null, + generator: false, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [25, 31], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 31 } + } + }, + range: [24, 31], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 31 } + } + }, + //range: [31, 33], + //loc: { + // start: { line: 1, column: 31 }, + // end: { line: 1, column: 33 } + //} + }, + kind: "get", + "static": false, + computed: false, + range: [11, 33], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 33 } + } + }], + range: [10, 34], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 34 } + } + }, + range: [0, 34], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 34 } + } + }, + "var numVal:number;": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "numVal", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [11, 17], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 17 } + } + }, + range: [10, 17], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 17 } + } + }, + range: [4, 17], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 17 } + } + }, + init: null, + range: [4, 17], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 17 } + } + }], + kind: "var", + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + }, + "var numVal:number = otherNumVal;": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "numVal", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [11, 17], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 17 } + } + }, + range: [10, 17], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 17 } + } + }, + range: [4, 17], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 17 } + } + }, + init: { + type: "Identifier", + name: "otherNumVal", + range: [20, 31], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 31 } + } + }, + range: [4, 31], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 31 } + } + }], + kind: "var", + range: [0, 32], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 32 } + } + }, + "var a: {numVal: number};": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "numVal", + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: "NumberTypeAnnotation", + range: [16, 22], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 22 } + } + }, + optional: false, + range: [8, 22], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 22 } + } + }], + indexers: [], + callProperties: [], + range: [7, 23], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 23 } + } + }, + range: [5, 23], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 23 } + } + }, + range: [4, 23], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 23 } + } + }, + init: null, + range: [4, 23], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 23 } + } + }], + kind: "var", + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + }, + "var a: {numVal: number;};": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "numVal", + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: "NumberTypeAnnotation", + range: [16, 22], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 22 } + } + }, + optional: false, + range: [8, 22], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 22 } + } + }], + indexers: [], + callProperties: [], + range: [7, 24], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 24 } + } + }, + range: [5, 24], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 24 } + } + }, + range: [4, 24], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 24 } + } + }, + init: null, + range: [4, 24], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 24 } + } + }], + kind: "var", + range: [0, 25], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 25 } + } + }, + "var a: {numVal: number; [indexer: string]: number};": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "numVal", + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: "NumberTypeAnnotation", + range: [16, 22], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 22 } + } + }, + optional: false, + range: [8, 22], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 22 } + } + }], + indexers: [{ + type: "ObjectTypeIndexer", + id: { + type: "Identifier", + name: "indexer", + range: [25, 32], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 32 } + } + }, + key: { + type: "StringTypeAnnotation", + range: [34, 40], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 40 } + } + }, + value: { + type: "NumberTypeAnnotation", + range: [43, 49], + loc: { + start: { line: 1, column: 43 }, + end: { line: 1, column: 49 } + } + }, + range: [24, 49], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 49 } + } + }], + callProperties: [], + range: [7, 50], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 50 } + } + }, + range: [5, 50], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 50 } + } + }, + range: [4, 50], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 50 } + } + }, + init: null, + range: [4, 50], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 50 } + } + }], + kind: "var", + range: [0, 51], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 51 } + } + }, + "var a: ?{numVal: number};": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NullableTypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "numVal", + range: [9, 15], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 15 } + } + }, + value: { + type: "NumberTypeAnnotation", + range: [17, 23], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 23 } + } + }, + optional: false, + range: [9, 23], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 23 } + } + }], + indexers: [], + callProperties: [], + range: [8, 24], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 24 } + } + }, + range: [7, 24], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 24 } + } + }, + range: [5, 24], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 24 } + } + }, + range: [4, 24], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 24 } + } + }, + init: null, + range: [4, 24], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 24 } + } + }], + kind: "var", + range: [0, 25], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 25 } + } + }, + "var a: {numVal: number; strVal: string}": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "numVal", + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: "NumberTypeAnnotation", + range: [16, 22], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 22 } + } + }, + optional: false, + range: [8, 22], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 22 } + } + }, { + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "strVal", + range: [24, 30], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 30 } + } + }, + value: { + type: "StringTypeAnnotation", + range: [32, 38], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 38 } + } + }, + optional: false, + range: [24, 38], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 38 } + } + }], + indexers: [], + callProperties: [], + range: [7, 39], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 39 } + } + }, + range: [5, 39], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 39 } + } + }, + range: [4, 39], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 39 } + } + }, + init: null, + range: [4, 39], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 39 } + } + }], + kind: "var", + range: [0, 39], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 39 } + } + }, + "var a: {subObj: {strVal: string}}": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "subObj", + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "strVal", + range: [17, 23], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 23 } + } + }, + value: { + type: "StringTypeAnnotation", + range: [25, 31], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 31 } + } + }, + optional: false, + range: [17, 31], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 31 } + } + }], + indexers: [], + callProperties: [], + range: [16, 32], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 32 } + } + }, + optional: false, + range: [8, 32], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 32 } + } + }], + indexers: [], + callProperties: [], + range: [7, 33], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 33 } + } + }, + range: [5, 33], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 33 } + } + }, + range: [4, 33], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 33 } + } + }, + init: null, + range: [4, 33], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 33 } + } + }], + kind: "var", + range: [0, 33], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 33 } + } + }, + "var a: {subObj: ?{strVal: string}}": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "subObj", + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: "NullableTypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "strVal", + range: [18, 24], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 24 } + } + }, + value: { + type: "StringTypeAnnotation", + range: [26, 32], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 32 } + } + }, + optional: false, + range: [18, 32], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 32 } + } + }], + indexers: [], + callProperties: [], + range: [17, 33], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 33 } + } + }, + range: [16, 33], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 33 } + } + }, + optional: false, + range: [8, 33], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 33 } + } + }], + indexers: [], + callProperties: [], + range: [7, 34], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 34 } + } + }, + range: [5, 34], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 34 } + } + }, + range: [4, 34], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 34 } + } + }, + init: null, + range: [4, 34], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 34 } + } + }], + kind: "var", + range: [0, 34], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 34 } + } + }, + "var a: {param1: number; param2: string}": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "param1", + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: "NumberTypeAnnotation", + range: [16, 22], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 22 } + } + }, + optional: false, + range: [8, 22], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 22 } + } + }, { + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "param2", + range: [24, 30], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 30 } + } + }, + value: { + type: "StringTypeAnnotation", + range: [32, 38], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 38 } + } + }, + optional: false, + range: [24, 38], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 38 } + } + }], + indexers: [], + callProperties: [], + range: [7, 39], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 39 } + } + }, + range: [5, 39], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 39 } + } + }, + range: [4, 39], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 39 } + } + }, + init: null, + range: [4, 39], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 39 } + } + }], + kind: "var", + range: [0, 39], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 39 } + } + }, + "var a: {param1: number; param2?: string}": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "param1", + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + value: { + type: "NumberTypeAnnotation", + range: [16, 22], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 22 } + } + }, + optional: false, + range: [8, 22], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 22 } + } + }, { + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "param2", + range: [24, 30], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 30 } + } + }, + value: { + type: "StringTypeAnnotation", + range: [33, 39], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 39 } + } + }, + optional: true, + range: [24, 39], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 39 } + } + }], + indexers: [], + callProperties: [], + range: [7, 40], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 40 } + } + }, + range: [5, 40], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 40 } + } + }, + range: [4, 40], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 40 } + } + }, + init: null, + range: [4, 40], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 40 } + } + }], + kind: "var", + range: [0, 40], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 40 } + } + }, + "var a: {add(x:number, ...y:Array): void}": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "add", + range: [8, 11], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 11 } + } + }, + value: { + type: "FunctionTypeAnnotation", + params: [{ + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "x", + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [14, 20], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 20 } + } + }, + optional: false, + range: [12, 20], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 20 } + } + }], + returnType: { + type: "VoidTypeAnnotation", + range: [43, 47], + loc: { + start: { line: 1, column: 43 }, + end: { line: 1, column: 47 } + } + }, + rest: { + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "y", + range: [25, 26], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 26 } + } + }, + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Array", + range: [27, 32], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 32 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "StringTypeAnnotation", + range: [33, 39], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 39 } + } + }], + range: [32, 40], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 40 } + } + }, + range: [27, 40], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 40 } + } + }, + optional: false, + range: [25, 40], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 40 } + } + }, + typeParameters: null, + range: [8, 47], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 47 } + } + }, + optional: false, + range: [8, 47], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 47 } + } + }], + indexers: [], + callProperties: [], + range: [7, 48], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 48 } + } + }, + range: [5, 48], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 48 } + } + }, + range: [4, 48], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 48 } + } + }, + init: null, + range: [4, 48], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 48 } + } + }], + kind: "var", + range: [0, 48], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 48 } + } + }, + "var a: { id(x: T): T; }": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "id", + range: [9, 11], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 11 } + } + }, + value: { + type: "FunctionTypeAnnotation", + params: [{ + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "x", + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }, + typeParameters: null, + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }, + optional: false, + range: [15, 19], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 19 } + } + }], + returnType: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [22, 23], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 23 } + } + }, + typeParameters: null, + range: [22, 23], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 23 } + } + }, + rest: null, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }], + range: [11, 14], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 14 } + } + }, + range: [9, 23], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 23 } + } + }, + optional: false, + range: [9, 23], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 23 } + } + }], + indexers: [], + callProperties: [], + range: [7, 26], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 26 } + } + }, + range: [5, 26], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 26 } + } + }, + range: [4, 26], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 26 } + } + }, + init: null, + range: [4, 26], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 26 } + } + }], + kind: "var", + range: [0, 26], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 26 } + } + }, + "var a:Array = [1, 2, 3]": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Array", + range: [6, 11], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 11 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "NumberTypeAnnotation", + range: [12, 18], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 18 } + } + }], + range: [11, 19], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 19 } + } + }, + range: [6, 19], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 19 } + } + }, + range: [5, 19], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 19 } + } + }, + range: [4, 19], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 19 } + } + }, + init: { + type: "ArrayExpression", + elements: [{ + type: "Literal", + value: 1, + raw: "1", + range: [23, 24], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 24 } + } + }, { + type: "Literal", + value: 2, + raw: "2", + range: [26, 27], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 27 } + } + }, { + type: "Literal", + value: 3, + raw: "3", + range: [29, 30], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 30 } + } + }], + range: [22, 31], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 31 } + } + }, + range: [4, 31], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 31 } + } + }], + kind: "var", + range: [0, 31], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 31 } + } + }, + "a = class Foo { }": { + type: "ExpressionStatement", + expression: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "Identifier", + name: "a", + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: "ClassExpression", + id: { + type: "Identifier", + name: "Foo", + range: [10, 13], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 13 } + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [], + range: [17, 20], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 20 } + } + }, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }], + range: [13, 16], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 16 } + } + }, + range: [4, 20], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 20 } + } + }, + range: [0, 20], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + range: [0, 20], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + "a = class Foo extends Bar { }": { + type: "ExpressionStatement", + expression: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "Identifier", + name: "a", + range: [0, 1], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: "ClassExpression", + id: { + type: "Identifier", + name: "Foo", + range: [10, 13], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 13 } + } + }, + superClass: { + type: "Identifier", + name: "Bar", + range: [25, 28], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 28 } + } + }, + body: { + type: "ClassBody", + body: [], + range: [32, 35], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 35 } + } + }, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }], + range: [13, 16], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 16 } + } + }, + superTypeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [29, 30], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 30 } + } + }, + typeParameters: null, + range: [29, 30], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 30 } + } + }], + range: [28, 31], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 31 } + } + }, + range: [4, 35], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 35 } + } + }, + range: [0, 35], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 35 } + } + }, + range: [0, 35], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 35 } + } + }, + "class Foo {}": { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [], + range: [13, 15], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 15 } + } + }, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }], + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + "class Foo extends Bar { }": { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + superClass: { + type: "Identifier", + name: "Bar", + range: [21, 24], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 24 } + } + }, + body: { + type: "ClassBody", + body: [], + range: [28, 31], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 31 } + } + }, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }], + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + superTypeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [25, 26], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 26 } + } + }, + typeParameters: null, + range: [25, 26], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 26 } + } + }], + range: [24, 27], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 27 } + } + }, + range: [0, 31], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 31 } + } + }, + "class Foo extends mixin(Bar) { }": { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + superClass: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "mixin", + range: [21, 26], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 26 } + } + }, + "arguments": [{ + type: "Identifier", + name: "Bar", + range: [27, 30], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 30 } + } + }], + range: [21, 31], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 31 } + } + }, + body: { + type: "ClassBody", + body: [], + range: [32, 35], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 35 } + } + }, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }], + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 35], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 35 } + } + }, + "class Foo { bar():number { return 42; }}": { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [{ + type: "MethodDefinition", + key: { + type: "Identifier", + name: "bar", + range: [15, 18], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 18 } + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [{ + type: "ReturnStatement", + argument: { + type: "Literal", + value: 42, + raw: "42", + range: [40, 42], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 42 } + } + }, + range: [33, 43], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 43 } + } + }], + range: [31, 45], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 45 } + } + }, + rest: null, + generator: false, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [24, 30], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 30 } + } + }, + range: [23, 30], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 30 } + } + }, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "U", + range: [19, 20], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 20 } + } + }], + range: [18, 21], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 21 } + } + }, + //range: [31, 45], + //loc: { + // start: { line: 1, column: 31 }, + // end: { line: 1, column: 45 } + //} + }, + kind: "", + "static": false, + computed: false, + range: [15, 45], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 45 } + } + }], + range: [13, 46], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 46 } + } + }, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }], + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + range: [0, 46], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 46 } + } + }, + 'class Foo { "bar"() { } }': { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [{ + type: "MethodDefinition", + key: { + type: "Literal", + value: "bar", + raw: '"bar"', + range: [12, 17], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 17 } + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [23, 26], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 26 } + } + }, + rest: null, + generator: false, + expression: false, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }], + range: [17, 20], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 20 } + } + }, + //range: [23, 26], + //loc: { + // start: { line: 1, column: 23 }, + // end: { line: 1, column: 26 } + //} + }, + kind: "", + "static": false, + computed: false, + range: [12, 26], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 26 } + } + }], + range: [10, 28], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 28 } + } + }, + range: [0, 28], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 28 } + } + }, + "function foo(requiredParam, optParam?) {}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [{ + type: "Identifier", + name: "requiredParam", + range: [13, 26], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 26 } + } + }, { + type: "Identifier", + name: "optParam", + optional: true, + range: [28, 37], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 37 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [39, 41], + loc: { + start: { line: 1, column: 39 }, + end: { line: 1, column: 41 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 41], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 41 } + } + }, + "class Foo { prop1:string; prop2:number; }": { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [{ + type: "ClassProperty", + key: { + type: "Identifier", + name: "prop1", + range: [12, 17], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 17 } + } + }, + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "StringTypeAnnotation", + range: [18, 24], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 24 } + } + }, + range: [17, 24], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 24 } + } + }, + computed: false, + "static": false, + range: [12, 25], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 25 } + } + }, { + type: "ClassProperty", + key: { + type: "Identifier", + name: "prop2", + range: [26, 31], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 31 } + } + }, + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [32, 38], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 38 } + } + }, + range: [31, 38], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 38 } + } + }, + computed: false, + "static": false, + range: [26, 39], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 39 } + } + }], + range: [10, 41], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 41 } + } + }, + range: [0, 41], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 41 } + } + }, + "class Foo { static prop1:string; prop2:number; }": { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [{ + type: "ClassProperty", + key: { + type: "Identifier", + name: "prop1", + range: [19, 24], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 24 } + } + }, + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "StringTypeAnnotation", + range: [25, 31], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 31 } + } + }, + range: [24, 31], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 31 } + } + }, + computed: false, + "static": true, + range: [12, 32], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 32 } + } + }, { + type: "ClassProperty", + key: { + type: "Identifier", + name: "prop2", + range: [33, 38], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 38 } + } + }, + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [39, 45], + loc: { + start: { line: 1, column: 39 }, + end: { line: 1, column: 45 } + } + }, + range: [38, 45], + loc: { + start: { line: 1, column: 38 }, + end: { line: 1, column: 45 } + } + }, + computed: false, + "static": false, + range: [33, 46], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 46 } + } + }], + range: [10, 48], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 48 } + } + }, + range: [0, 48], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 48 } + } + }, + "var x : number | string = 4;": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "x", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "UnionTypeAnnotation", + types: [{ + type: "NumberTypeAnnotation", + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, { + type: "StringTypeAnnotation", + range: [17, 23], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 23 } + } + }], + range: [8, 23], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 23 } + } + }, + range: [6, 23], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 23 } + } + }, + range: [4, 23], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 23 } + } + }, + init: { + type: "Literal", + value: 4, + raw: "4", + range: [26, 27], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 27 } + } + }, + range: [4, 27], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 27 } + } + }], + kind: "var", + range: [0, 28], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 28 } + } + }, + "class Array { concat(items:number | string) {}; }": { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Array", + range: [6, 11], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 11 } + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [{ + type: "MethodDefinition", + key: { + type: "Identifier", + name: "concat", + range: [14, 20], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 20 } + } + }, + value: { + type: "FunctionExpression", + id: null, + params: [{ + type: "Identifier", + name: "items", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "UnionTypeAnnotation", + types: [{ + type: "NumberTypeAnnotation", + range: [27, 33], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 33 } + } + }, { + type: "StringTypeAnnotation", + range: [36, 42], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 42 } + } + }], + range: [27, 42], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 42 } + } + }, + range: [26, 42], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 42 } + } + }, + range: [21, 42], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 42 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [44, 46], + loc: { + start: { line: 1, column: 44 }, + end: { line: 1, column: 46 } + } + }, + rest: null, + generator: false, + expression: false, + //range: [44, 46], + //loc: { + // start: { line: 1, column: 44 }, + // end: { line: 1, column: 46 } + //} + }, + kind: "", + "static": false, + computed: false, + range: [14, 46], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 46 } + } + }], + range: [12, 49], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 49 } + } + }, + range: [0, 49], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 49 } + } + }, + "var x : () => number | () => string = fn;": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "x", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "UnionTypeAnnotation", + types: [{ + type: "NumberTypeAnnotation", + range: [14, 20], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 20 } + } + }, { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "StringTypeAnnotation", + range: [29, 35], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 35 } + } + }, + rest: null, + typeParameters: null, + range: [23, 35], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 35 } + } + }], + range: [14, 35], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 35 } + } + }, + rest: null, + typeParameters: null, + range: [8, 35], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 35 } + } + }, + range: [6, 35], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 35 } + } + }, + range: [4, 35], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 35 } + } + }, + init: { + type: "Identifier", + name: "fn", + range: [38, 40], + loc: { + start: { line: 1, column: 38 }, + end: { line: 1, column: 40 } + } + }, + range: [4, 40], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 40 } + } + }], + kind: "var", + range: [0, 41], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 41 } + } + }, + "var x: typeof Y = Y;": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "x", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "TypeofTypeAnnotation", + argument: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Y", + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + typeParameters: null, + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + range: [7, 15], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 15 } + } + }, + range: [5, 15], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 15 } + } + }, + range: [4, 15], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 15 } + } + }, + init: { + type: "Identifier", + name: "Y", + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }, + range: [4, 19], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 19 } + } + }], + kind: "var", + range: [0, 20], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + "var x: typeof Y | number = Y;": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "x", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "UnionTypeAnnotation", + types: [{ + type: "TypeofTypeAnnotation", + argument: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Y", + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + typeParameters: null, + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + range: [7, 15], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 15 } + } + }, { + type: "NumberTypeAnnotation", + range: [18, 24], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 24 } + } + }], + range: [7, 24], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 24 } + } + }, + range: [5, 24], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 24 } + } + }, + range: [4, 24], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 24 } + } + }, + init: { + type: "Identifier", + name: "Y", + range: [27, 28], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 28 } + } + }, + range: [4, 28], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 28 } + } + }], + kind: "var", + range: [0, 29], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 29 } + } + }, + 'var {x}: {x: string; } = { x: "hello" };': { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "ObjectPattern", + properties: [{ + type: "Property", + key: { + type: "Identifier", + name: "x", + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + value: { + type: "Identifier", + name: "x", + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + kind: "init", + method: false, + shorthand: true, + computed: false, + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }], + range: [4, 22], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 22 } + }, + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "x", + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + value: { + type: "StringTypeAnnotation", + range: [13, 19], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 19 } + } + }, + optional: false, + range: [10, 19], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 19 } + } + }], + indexers: [], + callProperties: [], + range: [9, 22], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 22 } + } + }, + range: [7, 22], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 22 } + } + } + }, + init: { + type: "ObjectExpression", + properties: [{ + type: "Property", + key: { + type: "Identifier", + name: "x", + range: [27, 28], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 28 } + } + }, + value: { + type: "Literal", + value: "hello", + raw: '"hello"', + range: [30, 37], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 37 } + } + }, + kind: "init", + method: false, + shorthand: false, + computed: false, + range: [27, 37], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 37 } + } + }], + range: [25, 39], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 39 } + } + }, + range: [4, 39], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 39 } + } + }], + kind: "var", + range: [0, 40], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 40 } + } + }, + 'var {x}: {x: string } = { x: "hello" };': { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "ObjectPattern", + properties: [{ + type: "Property", + key: { + type: "Identifier", + name: "x", + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + value: { + type: "Identifier", + name: "x", + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + kind: "init", + method: false, + shorthand: true, + computed: false, + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }], + range: [4, 21], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 21 } + }, + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "x", + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + value: { + type: "StringTypeAnnotation", + range: [13, 19], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 19 } + } + }, + optional: false, + range: [10, 19], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 19 } + } + }], + indexers: [], + callProperties: [], + range: [9, 21], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 21 } + } + }, + range: [7, 21], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 21 } + } + } + }, + init: { + type: "ObjectExpression", + properties: [{ + type: "Property", + key: { + type: "Identifier", + name: "x", + range: [26, 27], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 27 } + } + }, + value: { + type: "Literal", + value: "hello", + raw: '"hello"', + range: [29, 36], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 36 } + } + }, + kind: "init", + method: false, + shorthand: false, + computed: false, + range: [26, 36], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 36 } + } + }], + range: [24, 38], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 38 } + } + }, + range: [4, 38], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 38 } + } + }], + kind: "var", + range: [0, 39], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 39 } + } + }, + 'var [x]: Array = [ "hello" ];': { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "ArrayPattern", + elements: [{ + type: "Identifier", + name: "x", + range: [5, 6], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }], + range: [4, 22], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 22 } + }, + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Array", + range: [9, 14], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 14 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "StringTypeAnnotation", + range: [15, 21], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 21 } + } + }], + range: [14, 22], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 22 } + } + }, + range: [9, 22], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 22 } + } + }, + range: [7, 22], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 22 } + } + } + }, + init: { + type: "ArrayExpression", + elements: [{ + type: "Literal", + value: "hello", + raw: '"hello"', + range: [27, 34], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 34 } + } + }], + range: [25, 36], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 36 } + } + }, + range: [4, 36], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 36 } + } + }], + kind: "var", + range: [0, 37], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 37 } + } + }, + "function foo({x}: { x: string; }) {}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [{ + type: "ObjectPattern", + properties: [{ + type: "Property", + key: { + type: "Identifier", + name: "x", + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + value: { + type: "Identifier", + name: "x", + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + kind: "init", + method: false, + shorthand: true, + computed: false, + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }], + range: [13, 32], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 32 } + }, + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "x", + range: [20, 21], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 21 } + } + }, + value: { + type: "StringTypeAnnotation", + range: [23, 29], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 29 } + } + }, + optional: false, + range: [20, 29], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 29 } + } + }], + indexers: [], + callProperties: [], + range: [18, 32], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 32 } + } + }, + range: [16, 32], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 32 } + } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [34, 36], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 36 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + "function foo([x]: Array) {}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [{ + type: "ArrayPattern", + elements: [{ + type: "Identifier", + name: "x", + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }], + range: [13, 31], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 31 } + }, + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Array", + range: [18, 23], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 23 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "StringTypeAnnotation", + range: [24, 30], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 30 } + } + }], + range: [23, 31], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 31 } + } + }, + range: [18, 31], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 31 } + } + }, + range: [16, 31], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 31 } + } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [33, 35], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 35 } + } + }, + rest: null, + generator: false, + expression: false, + range: [0, 35], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 35 } + } + }, + "function foo(...rest: Array) {}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [37, 39], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 39 } + } + }, + rest: { + type: "Identifier", + name: "rest", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Array", + range: [22, 27], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 27 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "NumberTypeAnnotation", + range: [28, 34], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 34 } + } + }], + range: [27, 35], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 35 } + } + }, + range: [22, 35], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 35 } + } + }, + range: [20, 35], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 35 } + } + }, + range: [16, 35], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 35 } + } + }, + generator: false, + expression: false, + range: [0, 39], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 39 } + } + }, + "(function (...rest: Array) {})": { + type: "ExpressionStatement", + expression: { + type: "FunctionExpression", + id: null, + params: [], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [35, 37], + loc: { + start: { line: 1, column: 35 }, + end: { line: 1, column: 37 } + } + }, + rest: { + type: "Identifier", + name: "rest", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Array", + range: [20, 25], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 25 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "NumberTypeAnnotation", + range: [26, 32], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 32 } + } + }], + range: [25, 33], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 33 } + } + }, + range: [20, 33], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 33 } + } + }, + range: [18, 33], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 33 } + } + }, + range: [14, 33], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 33 } + } + }, + generator: false, + expression: false, + range: [1, 37], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 37 } + } + }, + range: [0, 38], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + } + }, + "((...rest: Array) => rest)": { + type: "ExpressionStatement", + expression: { + type: "ArrowFunctionExpression", + id: null, + params: [], + defaults: [], + body: { + type: "Identifier", + name: "rest", + range: [29, 33], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 33 } + } + }, + rest: { + type: "Identifier", + name: "rest", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Array", + range: [11, 16], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 16 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "NumberTypeAnnotation", + range: [17, 23], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 23 } + } + }], + range: [16, 24], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 24 } + } + }, + range: [11, 24], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 24 } + } + }, + range: [9, 24], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 24 } + } + }, + range: [5, 24], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 24 } + } + }, + generator: false, + expression: true, + range: [1, 33], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 33 } + } + }, + range: [0, 34], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 34 } + } + }, + "var a: Map >": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Map", + range: [7, 10], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 10 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "StringTypeAnnotation", + range: [11, 17], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 17 } + } + }, { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Array", + range: [19, 24], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 24 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "StringTypeAnnotation", + range: [25, 31], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 31 } + } + }], + range: [24, 32], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 32 } + } + }, + range: [19, 32], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 32 } + } + }], + range: [10, 34], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 34 } + } + }, + range: [7, 34], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 34 } + } + }, + range: [5, 34], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 34 } + } + }, + range: [4, 34], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 34 } + } + }, + init: null, + range: [4, 34], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 34 } + } + }], + kind: "var", + range: [0, 34], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 34 } + } + }, + "var a: Map>": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Map", + range: [7, 10], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 10 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "StringTypeAnnotation", + range: [11, 17], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 17 } + } + }, { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Array", + range: [19, 24], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 24 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "StringTypeAnnotation", + range: [25, 31], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 31 } + } + }], + range: [24, 32], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 32 } + } + }, + range: [19, 32], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 32 } + } + }], + range: [10, 33], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 33 } + } + }, + range: [7, 33], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 33 } + } + }, + range: [5, 33], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 33 } + } + }, + range: [4, 33], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 33 } + } + }, + init: null, + range: [4, 33], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 33 } + } + }], + kind: "var", + range: [0, 33], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 33 } + } + }, + "var a: number[]": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ArrayTypeAnnotation", + elementType: { + type: "NumberTypeAnnotation", + range: [7, 13], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 13 } + } + }, + range: [7, 15], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 15 } + } + }, + range: [5, 15], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 15 } + } + }, + range: [4, 15], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 15 } + } + }, + init: null, + range: [4, 15], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 15 } + } + }], + kind: "var", + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + "var a: ?string[]": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NullableTypeAnnotation", + typeAnnotation: { + type: "ArrayTypeAnnotation", + elementType: { + type: "StringTypeAnnotation", + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + range: [8, 16], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 16 } + } + }, + range: [7, 16], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 16 } + } + }, + range: [5, 16], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 16 } + } + }, + range: [4, 16], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 16 } + } + }, + init: null, + range: [4, 16], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 16 } + } + }], + kind: "var", + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + "var a: Promise[]": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ArrayTypeAnnotation", + elementType: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Promise", + range: [7, 14], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 14 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "BooleanTypeAnnotation", + range: [15, 19], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 19 } + } + }], + range: [14, 20], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 20 } + } + }, + range: [7, 20], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 20 } + } + }, + range: [7, 22], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 22 } + } + }, + range: [5, 22], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 22 } + } + }, + range: [4, 22], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 22 } + } + }, + init: null, + range: [4, 22], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 22 } + } + }], + kind: "var", + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + "var a:(...rest:Array) => number": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "NumberTypeAnnotation", + range: [33, 39], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 39 } + } + }, + rest: { + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "rest", + range: [10, 14], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 14 } + } + }, + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Array", + range: [15, 20], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 20 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "NumberTypeAnnotation", + range: [21, 27], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 27 } + } + }], + range: [20, 28], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 28 } + } + }, + range: [15, 28], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 28 } + } + }, + optional: false, + range: [10, 28], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 28 } + } + }, + typeParameters: null, + range: [6, 39], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 39 } + } + }, + range: [5, 39], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 39 } + } + }, + range: [4, 39], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 39 } + } + }, + init: null, + range: [4, 39], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 39 } + } + }], + kind: "var", + range: [0, 39], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 39 } + } + }, + "var identity: (x: T) => T": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "identity", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [{ + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "x", + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }, + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [21, 22], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 22 } + } + }, + typeParameters: null, + range: [21, 22], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 22 } + } + }, + optional: false, + range: [18, 22], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 22 } + } + }], + returnType: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [27, 28], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 28 } + } + }, + typeParameters: null, + range: [27, 28], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 28 } + } + }, + rest: null, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }], + range: [14, 17], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 17 } + } + }, + range: [14, 28], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 28 } + } + }, + range: [12, 28], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 28 } + } + }, + range: [4, 28], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 28 } + } + }, + init: null, + range: [4, 28], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 28 } + } + }], + kind: "var", + range: [0, 28], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 28 } + } + }, + "var identity: (x: T, ...y:T[]) => T": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "identity", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [{ + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "x", + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }, + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [21, 22], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 22 } + } + }, + typeParameters: null, + range: [21, 22], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 22 } + } + }, + optional: false, + range: [18, 22], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 22 } + } + }], + returnType: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [37, 38], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 38 } + } + }, + typeParameters: null, + range: [37, 38], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 38 } + } + }, + rest: { + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "y", + range: [27, 28], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 28 } + } + }, + typeAnnotation: { + type: "ArrayTypeAnnotation", + elementType: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [29, 30], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 30 } + } + }, + typeParameters: null, + range: [29, 30], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 30 } + } + }, + range: [29, 32], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 32 } + } + }, + optional: false, + range: [27, 32], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 32 } + } + }, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }], + range: [14, 17], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 17 } + } + }, + range: [14, 38], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 38 } + } + }, + range: [12, 38], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 38 } + } + }, + range: [4, 38], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 38 } + } + }, + init: null, + range: [4, 38], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 38 } + } + }], + kind: "var", + range: [0, 38], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + } + }, + }, + "Array Types": { + "var a: number[]": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ArrayTypeAnnotation", + elementType: { + type: "NumberTypeAnnotation", + range: [7, 13], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 13 } + } + }, + range: [7, 15], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 15 } + } + }, + range: [5, 15], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 15 } + } + }, + range: [4, 15], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 15 } + } + }, + init: null, + range: [4, 15], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 15 } + } + }], + kind: "var", + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + "var a: ?number[]": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NullableTypeAnnotation", + typeAnnotation: { + type: "ArrayTypeAnnotation", + elementType: { + type: "NumberTypeAnnotation", + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + range: [8, 16], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 16 } + } + }, + range: [7, 16], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 16 } + } + }, + range: [5, 16], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 16 } + } + }, + range: [4, 16], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 16 } + } + }, + init: null, + range: [4, 16], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 16 } + } + }], + kind: "var", + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + "var a: (?number)[]": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ArrayTypeAnnotation", + elementType: { + type: "NullableTypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [9, 15], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 15 } + } + }, + range: [8, 15], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 15 } + } + }, + range: [7, 18], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 18 } + } + }, + range: [5, 18], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 18 } + } + }, + range: [4, 18], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 18 } + } + }, + init: null, + range: [4, 18], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 18 } + } + }], + kind: "var", + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + }, + "var a: () => number[]": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "ArrayTypeAnnotation", + elementType: { + type: "NumberTypeAnnotation", + range: [13, 19], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 19 } + } + }, + range: [13, 21], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 21 } + } + }, + rest: null, + typeParameters: null, + range: [7, 21], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 21 } + } + }, + range: [5, 21], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 21 } + } + }, + range: [4, 21], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 21 } + } + }, + init: null, + range: [4, 21], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 21 } + } + }], + kind: "var", + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + "var a: (() => number)[]": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ArrayTypeAnnotation", + elementType: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "NumberTypeAnnotation", + range: [14, 20], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 20 } + } + }, + rest: null, + typeParameters: null, + range: [8, 20], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 20 } + } + }, + range: [7, 23], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 23 } + } + }, + range: [5, 23], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 23 } + } + }, + range: [4, 23], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 23 } + } + }, + init: null, + range: [4, 23], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 23 } + } + }], + kind: "var", + range: [0, 23], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + } + }, + "var a: typeof A[]": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ArrayTypeAnnotation", + elementType: { + type: "TypeofTypeAnnotation", + argument: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "A", + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + typeParameters: null, + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + range: [7, 15], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 15 } + } + }, + range: [7, 17], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 17 } + } + }, + range: [5, 17], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 17 } + } + }, + range: [4, 17], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 17 } + } + }, + init: null, + range: [4, 17], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 17 } + } + }], + kind: "var", + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }, + }, + "Tuples": { + "var a : [] = [];": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "TupleTypeAnnotation", + types: [], + range: [8, 10], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 10 } + } + }, + range: [6, 10], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 10 } + } + }, + range: [4, 10], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 10 } + } + }, + init: { + type: "ArrayExpression", + elements: [], + range: [13, 15], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 15 } + } + }, + range: [4, 15], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 15 } + } + }], + kind: "var", + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + "var a : [Foo] = [foo];": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "TupleTypeAnnotation", + types: [{ + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Foo", + range: [9, 12], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 12 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }, + typeParameters: null, + range: [13, 14], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }], + range: [12, 15], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 15 } + } + }, + range: [9, 15], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 15 } + } + }], + range: [8, 16], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 16 } + } + }, + range: [6, 16], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 16 } + } + }, + range: [4, 16], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 16 } + } + }, + init: { + type: "ArrayExpression", + elements: [{ + type: "Identifier", + name: "foo", + range: [20, 23], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 23 } + } + }], + range: [19, 24], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 24 } + } + }, + range: [4, 24], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 24 } + } + }], + kind: "var", + range: [0, 25], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 25 } + } + }, + "var a : [number,] = [123,];": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "TupleTypeAnnotation", + types: [{ + type: "NumberTypeAnnotation", + range: [9, 15], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 15 } + } + }], + range: [8, 17], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 17 } + } + }, + range: [6, 17], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 17 } + } + }, + range: [4, 17], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 17 } + } + }, + init: { + type: "ArrayExpression", + elements: [{ + type: "Literal", + value: 123, + raw: "123", + range: [21, 24], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 24 } + } + }], + range: [20, 26], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 26 } + } + }, + range: [4, 26], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 26 } + } + }], + kind: "var", + range: [0, 27], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + }, + 'var a : [number, string] = [123, "duck"];': { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "TupleTypeAnnotation", + types: [{ + type: "NumberTypeAnnotation", + range: [9, 15], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 15 } + } + }, { + type: "StringTypeAnnotation", + range: [17, 23], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 23 } + } + }], + range: [8, 24], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 24 } + } + }, + range: [6, 24], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 24 } + } + }, + range: [4, 24], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 24 } + } + }, + init: { + type: "ArrayExpression", + elements: [{ + type: "Literal", + value: 123, + raw: "123", + range: [28, 31], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 31 } + } + }, { + type: "Literal", + value: "duck", + raw: '"duck"', + range: [33, 39], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 39 } + } + }], + range: [27, 40], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 40 } + } + }, + range: [4, 40], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 40 } + } + }], + kind: "var", + range: [0, 41], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 41 } + } + }, + }, + "Type Alias": { + "type FBID = number;": { + type: "TypeAlias", + id: { + type: "Identifier", + name: "FBID", + range: [5, 9], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 9 } + } + }, + typeParameters: null, + right: { + type: "NumberTypeAnnotation", + range: [12, 18], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 18 } + } + }, + range: [0, 19], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 19 } + } + }, + "type Foo = Bar": { + type: "TypeAlias", + id: { + type: "Identifier", + name: "Foo", + range: [5, 8], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 8 } + } + }, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [9, 10], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }], + range: [8, 11], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 11 } + } + }, + right: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "Bar", + range: [14, 17], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 17 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }, + typeParameters: null, + range: [18, 19], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + }], + range: [17, 20], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 20 } + } + }, + range: [14, 20], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 20 } + } + }, + range: [0, 20], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + }, + "Interfaces": { + "interface A {}": { + type: "InterfaceDeclaration", + id: { + type: "Identifier", + name: "A", + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + typeParameters: null, + body: { + type: "ObjectTypeAnnotation", + properties: [], + indexers: [], + callProperties: [], + range: [12, 14], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 14 } + } + }, + "extends": [], + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + "interface A extends B {}": { + type: "InterfaceDeclaration", + id: { + type: "Identifier", + name: "A", + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + typeParameters: null, + body: { + type: "ObjectTypeAnnotation", + properties: [], + indexers: [], + callProperties: [], + range: [22, 24], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 24 } + } + }, + "extends": [{ + type: "InterfaceExtends", + id: { + type: "Identifier", + name: "B", + range: [20, 21], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 21 } + } + }, + typeParameters: null, + range: [20, 21], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 21 } + } + }], + range: [0, 24], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + }, + "interface A extends B, C {}": { + type: "InterfaceDeclaration", + id: { + type: "Identifier", + name: "A", + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }], + range: [11, 14], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 14 } + } + }, + body: { + type: "ObjectTypeAnnotation", + properties: [], + indexers: [], + callProperties: [], + range: [34, 36], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 36 } + } + }, + "extends": [{ + type: "InterfaceExtends", + id: { + type: "Identifier", + name: "B", + range: [23, 24], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 24 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [25, 26], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 26 } + } + }, + typeParameters: null, + range: [25, 26], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 26 } + } + }], + range: [24, 27], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 27 } + } + }, + range: [23, 27], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 27 } + } + }, { + type: "InterfaceExtends", + id: { + type: "Identifier", + name: "C", + range: [29, 30], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 30 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [31, 32], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 32 } + } + }, + typeParameters: null, + range: [31, 32], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 32 } + } + }], + range: [30, 33], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 33 } + } + }, + range: [29, 33], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 33 } + } + }], + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + "interface A { foo: () => number; }": { + type: "InterfaceDeclaration", + id: { + type: "Identifier", + name: "A", + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + typeParameters: null, + body: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "foo", + range: [14, 17], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 17 } + } + }, + value: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "NumberTypeAnnotation", + range: [25, 31], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 31 } + } + }, + rest: null, + typeParameters: null, + range: [19, 31], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 31 } + } + }, + optional: false, + range: [14, 31], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 31 } + } + }], + indexers: [], + callProperties: [], + range: [12, 34], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 34 } + } + }, + "extends": [], + range: [0, 34], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 34 } + } + }, + "interface Dictionary { [index: string]: string; length: number; }": { + type: "InterfaceDeclaration", + id: { + type: "Identifier", + name: "Dictionary", + range: [10, 20], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 20 } + } + }, + typeParameters: null, + body: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "length", + range: [48, 54], + loc: { + start: { line: 1, column: 48 }, + end: { line: 1, column: 54 } + } + }, + value: { + type: "NumberTypeAnnotation", + range: [56, 62], + loc: { + start: { line: 1, column: 56 }, + end: { line: 1, column: 62 } + } + }, + optional: false, + range: [48, 62], + loc: { + start: { line: 1, column: 48 }, + end: { line: 1, column: 62 } + } + }], + indexers: [{ + type: "ObjectTypeIndexer", + id: { + type: "Identifier", + name: "index", + range: [24, 29], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 29 } + } + }, + key: { + type: "StringTypeAnnotation", + range: [31, 37], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 37 } + } + }, + value: { + type: "StringTypeAnnotation", + range: [40, 46], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 46 } + } + }, + range: [23, 46], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 46 } + } + }], + callProperties: [], + range: [21, 65], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 65 } + } + }, + "extends": [], + range: [0, 65], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 65 } + } + }, + "class Foo implements Bar {}": { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [], + range: [25, 27], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 27 } + } + }, + "implements": [{ + type: "ClassImplements", + id: { + type: "Identifier", + name: "Bar", + range: [21, 24], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 24 } + } + }, + typeParameters: null, + range: [21, 24], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 24 } + } + }], + range: [0, 27], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + }, + "class Foo extends Bar implements Bat, Man {}": { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + superClass: { + type: "Identifier", + name: "Bar", + range: [18, 21], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 21 } + } + }, + body: { + type: "ClassBody", + body: [], + range: [50, 52], + loc: { + start: { line: 1, column: 50 }, + end: { line: 1, column: 52 } + } + }, + "implements": [{ + type: "ClassImplements", + id: { + type: "Identifier", + name: "Bat", + range: [33, 36], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 36 } + } + }, + typeParameters: null, + range: [33, 36], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 36 } + } + }, { + type: "ClassImplements", + id: { + type: "Identifier", + name: "Man", + range: [38, 41], + loc: { + start: { line: 1, column: 38 }, + end: { line: 1, column: 41 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "NumberTypeAnnotation", + range: [42, 48], + loc: { + start: { line: 1, column: 42 }, + end: { line: 1, column: 48 } + } + }], + range: [41, 49], + loc: { + start: { line: 1, column: 41 }, + end: { line: 1, column: 49 } + } + }, + range: [38, 49], + loc: { + start: { line: 1, column: 38 }, + end: { line: 1, column: 49 } + } + }], + range: [0, 52], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 52 } + } + }, + "class Foo extends class Bar implements Bat {} {}": { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + superClass: { + type: "ClassExpression", + id: { + type: "Identifier", + name: "Bar", + range: [24, 27], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 27 } + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [], + range: [43, 45], + loc: { + start: { line: 1, column: 43 }, + end: { line: 1, column: 45 } + } + }, + "implements": [{ + type: "ClassImplements", + id: { + type: "Identifier", + name: "Bat", + range: [39, 42], + loc: { + start: { line: 1, column: 39 }, + end: { line: 1, column: 42 } + } + }, + typeParameters: null, + range: [39, 42], + loc: { + start: { line: 1, column: 39 }, + end: { line: 1, column: 42 } + } + }], + range: [18, 45], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 45 } + } + }, + body: { + type: "ClassBody", + body: [], + range: [46, 48], + loc: { + start: { line: 1, column: 46 }, + end: { line: 1, column: 48 } + } + }, + range: [0, 48], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 48 } + } + }, + "class Foo extends class Bar implements Bat {} implements Man {}": { + type: "ClassDeclaration", + id: { + type: "Identifier", + name: "Foo", + range: [6, 9], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + superClass: { + type: "ClassExpression", + id: { + type: "Identifier", + name: "Bar", + range: [24, 27], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 27 } + } + }, + superClass: null, + body: { + type: "ClassBody", + body: [], + range: [43, 45], + loc: { + start: { line: 1, column: 43 }, + end: { line: 1, column: 45 } + } + }, + "implements": [{ + type: "ClassImplements", + id: { + type: "Identifier", + name: "Bat", + range: [39, 42], + loc: { + start: { line: 1, column: 39 }, + end: { line: 1, column: 42 } + } + }, + typeParameters: null, + range: [39, 42], + loc: { + start: { line: 1, column: 39 }, + end: { line: 1, column: 42 } + } + }], + range: [18, 45], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 45 } + } + }, + body: { + type: "ClassBody", + body: [], + range: [61, 63], + loc: { + start: { line: 1, column: 61 }, + end: { line: 1, column: 63 } + } + }, + "implements": [{ + type: "ClassImplements", + id: { + type: "Identifier", + name: "Man", + range: [57, 60], + loc: { + start: { line: 1, column: 57 }, + end: { line: 1, column: 60 } + } + }, + typeParameters: null, + range: [57, 60], + loc: { + start: { line: 1, column: 57 }, + end: { line: 1, column: 60 } + } + }], + range: [0, 63], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 63 } + } + }, + }, + "Type Grouping": { + "var a: (number)": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + range: [5, 15], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 15 } + } + }, + range: [4, 15], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 15 } + } + }, + init: null, + range: [4, 15], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 15 } + } + }], + kind: "var", + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + "var a: (() => number) | () => string": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "UnionTypeAnnotation", + types: [{ + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "NumberTypeAnnotation", + range: [14, 20], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 20 } + } + }, + rest: null, + typeParameters: null, + range: [8, 20], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 20 } + } + }, { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "StringTypeAnnotation", + range: [30, 36], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 36 } + } + }, + rest: null, + typeParameters: null, + range: [24, 36], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 36 } + } + }], + range: [7, 36], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 36 } + } + }, + range: [5, 36], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 36 } + } + }, + range: [4, 36], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 36 } + } + }, + init: null, + range: [4, 36], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 36 } + } + }], + kind: "var", + range: [0, 36], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 36 } + } + }, + "var a: number & (string | bool)": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "IntersectionTypeAnnotation", + types: [{ + type: "NumberTypeAnnotation", + range: [7, 13], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 13 } + } + }, { + type: "UnionTypeAnnotation", + types: [{ + type: "StringTypeAnnotation", + range: [17, 23], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 23 } + } + }, { + type: "BooleanTypeAnnotation", + range: [26, 30], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 30 } + } + }], + range: [17, 30], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 30 } + } + }], + range: [7, 31], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 31 } + } + }, + range: [5, 31], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 31 } + } + }, + range: [4, 31], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 31 } + } + }, + init: null, + range: [4, 31], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 31 } + } + }], + kind: "var", + range: [0, 31], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 31 } + } + }, + "var a: (typeof A)": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "TypeofTypeAnnotation", + argument: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "A", + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + typeParameters: null, + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + range: [8, 16], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 16 } + } + }, + range: [5, 17], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 17 } + } + }, + range: [4, 17], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 17 } + } + }, + init: null, + range: [4, 17], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 17 } + } + }], + kind: "var", + range: [0, 17], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 17 } + } + }, + }, + "Call Properties": { + "var a : { (): number }": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [], + indexers: [], + callProperties: [{ + type: "ObjectTypeCallProperty", + value: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "NumberTypeAnnotation", + range: [14, 20], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 20 } + } + }, + rest: null, + typeParameters: null, + range: [10, 20], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 20 } + } + }, + range: [10, 20], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 20 } + } + }], + range: [8, 22], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 22 } + } + }, + range: [6, 22], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 22 } + } + }, + range: [4, 22], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 22 } + } + }, + init: null, + range: [4, 22], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 22 } + } + }], + kind: "var", + range: [0, 22], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + }, + "var a : { (): number; }": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [], + indexers: [], + callProperties: [{ + type: "ObjectTypeCallProperty", + value: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "NumberTypeAnnotation", + range: [14, 20], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 20 } + } + }, + rest: null, + typeParameters: null, + range: [10, 20], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 20 } + } + }, + range: [10, 20], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 20 } + } + }], + range: [8, 23], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 23 } + } + }, + range: [6, 23], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 23 } + } + }, + range: [4, 23], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 23 } + } + }, + init: null, + range: [4, 23], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 23 } + } + }], + kind: "var", + range: [0, 23], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + } + }, + "var a : { (): number; y: string; (x: string): string }": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "y", + range: [22, 23], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 23 } + } + }, + value: { + type: "StringTypeAnnotation", + range: [25, 31], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 31 } + } + }, + optional: false, + range: [22, 31], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 31 } + } + }], + indexers: [], + callProperties: [{ + type: "ObjectTypeCallProperty", + value: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "NumberTypeAnnotation", + range: [14, 20], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 20 } + } + }, + rest: null, + typeParameters: null, + range: [10, 20], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 20 } + } + }, + range: [10, 20], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 20 } + } + }, { + type: "ObjectTypeCallProperty", + value: { + type: "FunctionTypeAnnotation", + params: [{ + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "x", + range: [34, 35], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 35 } + } + }, + typeAnnotation: { + type: "StringTypeAnnotation", + range: [37, 43], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 43 } + } + }, + optional: false, + range: [34, 43], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 43 } + } + }], + returnType: { + type: "StringTypeAnnotation", + range: [46, 52], + loc: { + start: { line: 1, column: 46 }, + end: { line: 1, column: 52 } + } + }, + rest: null, + typeParameters: null, + range: [33, 52], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 52 } + } + }, + range: [33, 52], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 52 } + } + }], + range: [8, 54], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 54 } + } + }, + range: [6, 54], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 54 } + } + }, + range: [4, 54], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 54 } + } + }, + init: null, + range: [4, 54], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 54 } + } + }], + kind: "var", + range: [0, 54], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 54 } + } + }, + "var a : { (x: T): number; }": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "ObjectTypeAnnotation", + properties: [], + indexers: [], + callProperties: [{ + type: "ObjectTypeCallProperty", + value: { + type: "FunctionTypeAnnotation", + params: [{ + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "x", + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [17, 18], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }, + typeParameters: null, + range: [17, 18], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }, + optional: false, + range: [14, 18], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 18 } + } + }], + returnType: { + type: "NumberTypeAnnotation", + range: [21, 27], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 27 } + } + }, + rest: null, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [11, 12], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }], + range: [10, 13], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 13 } + } + }, + range: [10, 27], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 27 } + } + }, + range: [10, 27], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 27 } + } + }], + range: [8, 30], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 30 } + } + }, + range: [6, 30], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 30 } + } + }, + range: [4, 30], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 30 } + } + }, + init: null, + range: [4, 30], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 30 } + } + }], + kind: "var", + range: [0, 30], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 30 } + } + }, + "interface A { (): number; }": { + type: "InterfaceDeclaration", + id: { + type: "Identifier", + name: "A", + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + typeParameters: null, + body: { + type: "ObjectTypeAnnotation", + properties: [], + indexers: [], + callProperties: [{ + type: "ObjectTypeCallProperty", + value: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "NumberTypeAnnotation", + range: [18, 24], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 24 } + } + }, + rest: null, + typeParameters: null, + range: [14, 24], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 24 } + } + }, + "static": false, + range: [14, 24], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 24 } + } + }], + range: [12, 27], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 27 } + } + }, + "extends": [], + range: [0, 27], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + }, + }, + "String Literal Types": { + 'function createElement(tagName: "div"): HTMLDivElement {}': { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "createElement", + range: [9, 22], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 22 } + } + }, + params: [{ + type: "Identifier", + name: "tagName", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "StringLiteralTypeAnnotation", + value: "div", + raw: '"div"', + range: [32, 37], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 37 } + } + }, + range: [30, 37], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 37 } + } + }, + range: [23, 37], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 37 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [55, 57], + loc: { + start: { line: 1, column: 55 }, + end: { line: 1, column: 57 } + } + }, + rest: null, + generator: false, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "HTMLDivElement", + range: [40, 54], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 54 } + } + }, + typeParameters: null, + range: [40, 54], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 54 } + } + }, + range: [38, 54], + loc: { + start: { line: 1, column: 38 }, + end: { line: 1, column: 54 } + } + }, + range: [0, 57], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 57 } + } + }, + "function createElement(tagName: \"div\"): HTMLDivElement {}": { + type: "FunctionDeclaration", + id: { + type: "Identifier", + name: "createElement", + range: [9, 22], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 22 } + } + }, + params: [{ + type: "Identifier", + name: "tagName", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "StringLiteralTypeAnnotation", + value: "div", + raw: "\"div\"", + range: [32, 37], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 37 } + } + }, + range: [30, 37], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 37 } + } + }, + range: [23, 37], + loc: { + start: { line: 1, column: 23 }, + end: { line: 1, column: 37 } + } + }], + defaults: [], + body: { + type: "BlockStatement", + body: [], + range: [55, 57], + loc: { + start: { line: 1, column: 55 }, + end: { line: 1, column: 57 } + } + }, + rest: null, + generator: false, + expression: false, + returnType: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "HTMLDivElement", + range: [40, 54], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 54 } + } + }, + typeParameters: null, + range: [40, 54], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 54 } + } + }, + range: [38, 54], + loc: { + start: { line: 1, column: 38 }, + end: { line: 1, column: 54 } + } + }, + range: [0, 57], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 57 } + } + }, + }, + "Qualified Generic Type": { + "var a : A.B": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "QualifiedTypeIdentifier", + qualification: { + type: "Identifier", + name: "A", + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + id: { + type: "Identifier", + name: "B", + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + range: [8, 11], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 11 } + } + }, + typeParameters: null, + range: [8, 11], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 11 } + } + }, + range: [6, 11], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 11 } + } + }, + range: [4, 11], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 11 } + } + }, + init: null, + range: [4, 11], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 11 } + } + }], + kind: "var", + range: [0, 11], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + "var a : A.B.C": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "QualifiedTypeIdentifier", + qualification: { + type: "QualifiedTypeIdentifier", + qualification: { + type: "Identifier", + name: "A", + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + id: { + type: "Identifier", + name: "B", + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + range: [8, 11], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 11 } + } + }, + id: { + type: "Identifier", + name: "C", + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + range: [8, 13], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 13 } + } + }, + typeParameters: null, + range: [8, 13], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 13 } + } + }, + range: [6, 13], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 13 } + } + }, + range: [4, 13], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 13 } + } + }, + init: null, + range: [4, 13], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 13 } + } + }], + kind: "var", + range: [0, 13], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + "var a : A.B": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "GenericTypeAnnotation", + id: { + type: "QualifiedTypeIdentifier", + qualification: { + type: "Identifier", + name: "A", + range: [8, 9], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + id: { + type: "Identifier", + name: "B", + range: [10, 11], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + range: [8, 11], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 11 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + typeParameters: null, + range: [12, 13], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }], + range: [11, 14], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 14 } + } + }, + range: [8, 14], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + }, + range: [6, 14], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 14 } + } + }, + range: [4, 14], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 14 } + } + }, + init: null, + range: [4, 14], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 14 } + } + }], + kind: "var", + range: [0, 14], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + }, + "var a : typeof A.B": { + type: "VariableDeclaration", + declarations: [{ + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "a", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "TypeofTypeAnnotation", + argument: { + type: "GenericTypeAnnotation", + id: { + type: "QualifiedTypeIdentifier", + qualification: { + type: "Identifier", + name: "A", + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + id: { + type: "Identifier", + name: "B", + range: [17, 18], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }, + range: [15, 18], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 18 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [19, 20], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 20 } + } + }, + typeParameters: null, + range: [19, 20], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 20 } + } + }], + range: [18, 21], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 21 } + } + }, + range: [15, 21], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 21 } + } + }, + range: [8, 21], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 21 } + } + }, + range: [6, 21], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 21 } + } + }, + range: [4, 21], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 21 } + } + }, + init: null, + range: [4, 21], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 21 } + } + }], + kind: "var", + range: [0, 21], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + }, + }, + "Declare Statements": { + "declare var foo": { + type: "DeclareVariable", + id: { + type: "Identifier", + name: "foo", + range: [12, 15], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 15 } + } + }, + range: [0, 15], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + }, + "declare var foo;": { + type: "DeclareVariable", + id: { + type: "Identifier", + name: "foo", + range: [12, 15], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 15 } + } + }, + range: [0, 16], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + }, + "declare function foo(): void": { + type: "DeclareFunction", + id: { + type: "Identifier", + name: "foo", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "VoidTypeAnnotation", + range: [24, 28], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 28 } + } + }, + rest: null, + typeParameters: null, + range: [20, 28], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 28 } + } + }, + range: [20, 28], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 28 } + } + }, + range: [17, 28], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 28 } + } + }, + range: [0, 28], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 28 } + } + }, + "declare function foo(): void;": { + type: "DeclareFunction", + id: { + type: "Identifier", + name: "foo", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "VoidTypeAnnotation", + range: [24, 28], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 28 } + } + }, + rest: null, + typeParameters: null, + range: [20, 28], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 28 } + } + }, + range: [20, 28], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 28 } + } + }, + range: [17, 28], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 28 } + } + }, + range: [0, 29], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 29 } + } + }, + "declare function foo(): void;": { + type: "DeclareFunction", + id: { + type: "Identifier", + name: "foo", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "VoidTypeAnnotation", + range: [27, 31], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 31 } + } + }, + rest: null, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [21, 22], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 22 } + } + }], + range: [20, 23], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 23 } + } + }, + range: [20, 31], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 31 } + } + }, + range: [20, 31], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 31 } + } + }, + range: [17, 31], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 31 } + } + }, + range: [0, 32], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 32 } + } + }, + "declare function foo(x: number, y: string): void;": { + type: "DeclareFunction", + id: { + type: "Identifier", + name: "foo", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [{ + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "x", + range: [21, 22], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 22 } + } + }, + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [24, 30], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 30 } + } + }, + optional: false, + range: [21, 30], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 30 } + } + }, { + type: "FunctionTypeParam", + name: { + type: "Identifier", + name: "y", + range: [32, 33], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 33 } + } + }, + typeAnnotation: { + type: "StringTypeAnnotation", + range: [35, 41], + loc: { + start: { line: 1, column: 35 }, + end: { line: 1, column: 41 } + } + }, + optional: false, + range: [32, 41], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 41 } + } + }], + returnType: { + type: "VoidTypeAnnotation", + range: [44, 48], + loc: { + start: { line: 1, column: 44 }, + end: { line: 1, column: 48 } + } + }, + rest: null, + typeParameters: null, + range: [20, 48], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 48 } + } + }, + range: [20, 48], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 48 } + } + }, + range: [17, 48], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 48 } + } + }, + range: [0, 49], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 49 } + } + }, + "declare class A {}": { + type: "DeclareClass", + id: { + type: "Identifier", + name: "A", + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + typeParameters: null, + body: { + type: "ObjectTypeAnnotation", + properties: [], + indexers: [], + callProperties: [], + range: [16, 18], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 18 } + } + }, + "extends": [], + range: [0, 18], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + }, + "declare class A extends B { x: number }": { + type: "DeclareClass", + id: { + type: "Identifier", + name: "A", + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + typeParameters: { + type: "TypeParameterDeclaration", + params: [{ + type: "Identifier", + name: "T", + range: [16, 17], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + }], + range: [15, 18], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 18 } + } + }, + body: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "x", + range: [34, 35], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 35 } + } + }, + value: { + type: "NumberTypeAnnotation", + range: [37, 43], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 43 } + } + }, + optional: false, + range: [34, 43], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 43 } + } + }], + indexers: [], + callProperties: [], + range: [32, 45], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 45 } + } + }, + "extends": [{ + type: "InterfaceExtends", + id: { + type: "Identifier", + name: "B", + range: [27, 28], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 28 } + } + }, + typeParameters: { + type: "TypeParameterInstantiation", + params: [{ + type: "GenericTypeAnnotation", + id: { + type: "Identifier", + name: "T", + range: [29, 30], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 30 } + } + }, + typeParameters: null, + range: [29, 30], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 30 } + } + }], + range: [28, 31], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 31 } + } + }, + range: [27, 31], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 31 } + } + }], + range: [0, 45], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 45 } + } + }, + "declare class A { static foo(): number; static x : string }": { + type: "DeclareClass", + id: { + type: "Identifier", + name: "A", + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + typeParameters: null, + body: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "foo", + range: [25, 28], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 28 } + } + }, + value: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "NumberTypeAnnotation", + range: [32, 38], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 38 } + } + }, + rest: null, + typeParameters: null, + range: [18, 38], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 38 } + } + }, + optional: false, + "static": true, + range: [18, 38], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 38 } + } + }, { + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "x", + range: [47, 48], + loc: { + start: { line: 1, column: 47 }, + end: { line: 1, column: 48 } + } + }, + value: { + type: "StringTypeAnnotation", + range: [51, 57], + loc: { + start: { line: 1, column: 51 }, + end: { line: 1, column: 57 } + } + }, + optional: false, + "static": true, + range: [40, 57], + loc: { + start: { line: 1, column: 40 }, + end: { line: 1, column: 57 } + } + }], + indexers: [], + callProperties: [], + range: [16, 59], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 59 } + } + }, + "extends": [], + range: [0, 59], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 59 } } }, - '
    {
    }
    ': { type: 'ExpressionStatement', start: 0, @@ -3335,7 +11775,6 @@ var fbTestFixture = { }] } }, - '
    { {a} }
    ': { type: "ExpressionStatement", start: 0, @@ -3400,6 +11839,399 @@ var fbTestFixture = { } }] } + }, + "declare class A { static [ indexer: number]: string }": { + type: "DeclareClass", + id: { + type: "Identifier", + name: "A", + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + typeParameters: null, + body: { + type: "ObjectTypeAnnotation", + properties: [], + indexers: [{ + type: "ObjectTypeIndexer", + id: { + type: "Identifier", + name: "indexer", + range: [27, 34], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 34 } + } + }, + key: { + type: "NumberTypeAnnotation", + range: [36, 42], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 42 } + } + }, + value: { + type: "StringTypeAnnotation", + range: [45, 51], + loc: { + start: { line: 1, column: 45 }, + end: { line: 1, column: 51 } + } + }, + "static": true, + range: [18, 51], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 51 } + } + }], + callProperties: [], + range: [16, 53], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 53 } + } + }, + "extends": [], + range: [0, 53], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 53 } + } + }, + "declare class A { static () : number }": { + type: "DeclareClass", + id: { + type: "Identifier", + name: "A", + range: [14, 15], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + typeParameters: null, + body: { + type: "ObjectTypeAnnotation", + properties: [], + indexers: [], + callProperties: [{ + type: "ObjectTypeCallProperty", + value: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "NumberTypeAnnotation", + range: [30, 36], + loc: { + start: { line: 1, column: 30 }, + end: { line: 1, column: 36 } + } + }, + rest: null, + typeParameters: null, + range: [25, 36], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 36 } + } + }, + "static": true, + range: [18, 36], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 36 } + } + }], + range: [16, 38], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 38 } + } + }, + "extends": [], + range: [0, 38], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + } + }, + }, + "Declare Module": { + "declare module A {}": { + type: "DeclareModule", + id: { + type: "Identifier", + name: "A", + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + body: { + type: "BlockStatement", + body: [], + range: [17, 19], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 19 } + } + }, + range: [0, 19], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 19 } + } + }, + 'declare module "./a/b.js" {}': { + type: "DeclareModule", + id: { + type: "Literal", + value: "./a/b.js", + raw: '"./a/b.js"', + range: [15, 25], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 25 } + } + }, + body: { + type: "BlockStatement", + body: [], + range: [26, 28], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 28 } + } + }, + range: [0, 28], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 28 } + } + }, + "declare module A { declare var x: number; }": { + type: "DeclareModule", + id: { + type: "Identifier", + name: "A", + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + body: { + type: "BlockStatement", + body: [{ + type: "DeclareVariable", + id: { + type: "Identifier", + name: "x", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "NumberTypeAnnotation", + range: [34, 40], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 40 } + } + }, + range: [32, 40], + loc: { + start: { line: 1, column: 32 }, + end: { line: 1, column: 40 } + } + }, + range: [31, 40], + loc: { + start: { line: 1, column: 31 }, + end: { line: 1, column: 40 } + } + }, + range: [19, 41], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 41 } + } + }], + range: [17, 43], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 43 } + } + }, + range: [0, 43], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 43 } + } + }, + "declare module A { declare function foo(): number; }": { + type: "DeclareModule", + id: { + type: "Identifier", + name: "A", + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + body: { + type: "BlockStatement", + body: [{ + type: "DeclareFunction", + id: { + type: "Identifier", + name: "foo", + typeAnnotation: { + type: "TypeAnnotation", + typeAnnotation: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "NumberTypeAnnotation", + range: [43, 49], + loc: { + start: { line: 1, column: 43 }, + end: { line: 1, column: 49 } + } + }, + rest: null, + typeParameters: null, + range: [39, 49], + loc: { + start: { line: 1, column: 39 }, + end: { line: 1, column: 49 } + } + }, + range: [39, 49], + loc: { + start: { line: 1, column: 39 }, + end: { line: 1, column: 49 } + } + }, + range: [36, 49], + loc: { + start: { line: 1, column: 36 }, + end: { line: 1, column: 49 } + } + }, + range: [19, 50], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 50 } + } + }], + range: [17, 52], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 52 } + } + }, + range: [0, 52], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 52 } + } + }, + "declare module A { declare class B { foo(): number; } }": { + type: "DeclareModule", + id: { + type: "Identifier", + name: "A", + range: [15, 16], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + body: { + type: "BlockStatement", + body: [{ + type: "DeclareClass", + id: { + type: "Identifier", + name: "B", + range: [33, 34], + loc: { + start: { line: 1, column: 33 }, + end: { line: 1, column: 34 } + } + }, + typeParameters: null, + body: { + type: "ObjectTypeAnnotation", + properties: [{ + type: "ObjectTypeProperty", + key: { + type: "Identifier", + name: "foo", + range: [37, 40], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 40 } + } + }, + value: { + type: "FunctionTypeAnnotation", + params: [], + returnType: { + type: "NumberTypeAnnotation", + range: [44, 50], + loc: { + start: { line: 1, column: 44 }, + end: { line: 1, column: 50 } + } + }, + rest: null, + typeParameters: null, + range: [37, 50], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 50 } + } + }, + optional: false, + range: [37, 50], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 50 } + } + }], + indexers: [], + callProperties: [], + range: [35, 53], + loc: { + start: { line: 1, column: 35 }, + end: { line: 1, column: 53 } + } + }, + "extends": [], + range: [19, 53], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 53 } + } + }], + range: [17, 55], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 55 } + } + }, + range: [0, 55], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 55 } + } } } }; @@ -3412,7 +12244,7 @@ for (var ns in fbTestFixture) { ns = fbTestFixture[ns]; for (var code in ns) { test(code, { - type: 'Program', + type: "Program", body: [ns[code]] }, { ecmaVersion: 6, From 3a59b5a15147d68916f7edc0529340cf35c8e836 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 13 Dec 2014 12:06:42 +1100 Subject: [PATCH 086/198] better async contextual identifiers --- acorn.js | 50 +++++++------- test/tests-6to5.js | 168 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 194 insertions(+), 24 deletions(-) diff --git a/acorn.js b/acorn.js index 9da6054829..3eae0e4afe 100644 --- a/acorn.js +++ b/acorn.js @@ -2079,15 +2079,6 @@ next(); return parseFunction(node, true, false); } - - function eatAsync() { - if (tokType === _name && tokVal === "async") { - next(); - return true; - } else { - return false; - } - } function parseIfStatement(node) { next(); @@ -2727,23 +2718,28 @@ } else first = false; var prop = startNode(), isGenerator, isAsync; - if (options.ecmaVersion >= 7) { - isAsync = eatAsync(); - if (isAsync && tokType === _star) unexpected(); + if (options.ecmaVersion >= 7 && tokType === _ellipsis) { + prop = parseMaybeUnary(); + prop.type = "SpreadProperty"; + node.properties.push(prop); + continue; } if (options.ecmaVersion >= 6) { prop.method = false; prop.shorthand = false; isGenerator = eat(_star); } - if (options.ecmaVersion >= 7 && tokType === _ellipsis) { - if (isAsync || isGenerator) unexpected(); - prop = parseMaybeUnary(); - prop.type = "SpreadProperty"; - node.properties.push(prop); - continue; + if (options.ecmaVersion >= 7 && !isGenerator && tokType === _name && tokVal === "async") { + var asyncId = parseIdent(); + if (tokType === _colon || tokType === _parenL) { + prop.key = asyncId; + } else { + isAsync = true; + parsePropertyName(prop); + } + } else { + parsePropertyName(prop); } - parsePropertyName(prop); if (eat(_colon)) { prop.value = parseExpression(true); prop.kind = "init"; @@ -2953,12 +2949,18 @@ method['static'] = false; } var isAsync = false; - if (options.ecmaVersion >= 7) { - isAsync = eatAsync(); - if (isAsync && tokType === _star) unexpected(); - } var isGenerator = eat(_star); - parsePropertyName(method); + if (options.ecmaVersion >= 7 && !isGenerator && tokType === _name && tokVal === "async") { + var asyncId = parseIdent(); + if (tokType === _colon || tokType === _parenL) { + method.key = asyncId; + } else { + isAsync = true; + parsePropertyName(method); + } + } else { + parsePropertyName(method); + } if (tokType !== _parenL && !method.computed && method.key.type === "Identifier" && (method.key.name === "get" || method.key.name === "set" || (options.playground && method.key.name === "memo"))) { if (isGenerator || isAsync) unexpected(); diff --git a/test/tests-6to5.js b/test/tests-6to5.js index 757e67762d..87416eca36 100644 --- a/test/tests-6to5.js +++ b/test/tests-6to5.js @@ -1733,6 +1733,174 @@ test('(function() { var async; async = 10 })', { ranges: true }); +test('class Test { async() {} }', { + type: "Program", + start: 0, + end: 25, + body: [{ + type: "ClassDeclaration", + start: 0, + end: 25, + id: { + type: "Identifier", + start: 6, + end: 10, + name: "Test" + }, + superClass: null, + body: { + type: "ClassBody", + start: 11, + end: 25, + body: [{ + type: "MethodDefinition", + start: 13, + end: 23, + static: false, + key: { + type: "Identifier", + start: 13, + end: 18, + name: "async" + }, + kind: "", + value: { + type: "FunctionExpression", + start: 18, + end: 23, + id: null, + params: [], + defaults: [], + rest: null, + generator: false, + async: false, + body: { + type: "BlockStatement", + start: 21, + end: 23, + body: [] + }, + expression: false + } + }] + } + }] +}, { + ecmaVersion: 7 +}); + +test('var obj = { async: "test" };', { + type: "Program", + start: 0, + end: 28, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 28, + declarations: [{ + type: "VariableDeclarator", + start: 4, + end: 27, + id: { + type: "Identifier", + start: 4, + end: 7, + name: "obj" + }, + init: { + type: "ObjectExpression", + start: 10, + end: 27, + properties: [{ + type: "Property", + start: 12, + end: 25, + method: false, + shorthand: false, + key: { + type: "Identifier", + start: 12, + end: 17, + name: "async" + }, + value: { + type: "Literal", + start: 19, + end: 25, + value: "test", + raw: "\"test\"" + }, + kind: "init" + }] + } + }], + kind: "var" + }] +}, { + ecmaVersion: 7 +}); + +test('var obj = { async() {} };', { + type: "Program", + start: 0, + end: 25, + body: [{ + type: "VariableDeclaration", + start: 0, + end: 25, + declarations: [{ + type: "VariableDeclarator", + start: 4, + end: 24, + id: { + type: "Identifier", + start: 4, + end: 7, + name: "obj" + }, + init: { + type: "ObjectExpression", + start: 10, + end: 24, + properties: [{ + type: "Property", + start: 12, + end: 22, + method: true, + shorthand: false, + key: { + type: "Identifier", + start: 12, + end: 17, + name: "async" + }, + kind: "init", + value: { + type: "FunctionExpression", + start: 17, + end: 22, + id: null, + params: [], + defaults: [], + rest: null, + generator: false, + body: { + type: "BlockStatement", + start: 20, + end: 22, + body: [] + }, + expression: false + } + }] + } + }], + kind: "var" + }] +}, { + ecmaVersion: 7 +}); + // ES7: Abstract references test('foo::bar;', { From 46977807b7a11f708ceecf9ed81c5ff8f973cc2d Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 13 Dec 2014 12:33:07 +1100 Subject: [PATCH 087/198] fix isX variables not being reset on parseObj --- acorn.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index 3eae0e4afe..bb514d48c5 100644 --- a/acorn.js +++ b/acorn.js @@ -2717,7 +2717,7 @@ if (options.allowTrailingCommas && eat(_braceR)) break; } else first = false; - var prop = startNode(), isGenerator, isAsync; + var prop = startNode(), isGenerator = false, isAsync = false; if (options.ecmaVersion >= 7 && tokType === _ellipsis) { prop = parseMaybeUnary(); prop.type = "SpreadProperty"; From e0b630264948cd3071c1447cdfaad062d83862a6 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 14 Dec 2014 13:19:22 +1100 Subject: [PATCH 088/198] add support for private declarations --- acorn.js | 24 +++++++-- test/tests-6to5.js | 128 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 4 deletions(-) diff --git a/acorn.js b/acorn.js index 4557bc7efe..56cc6cfc0c 100644 --- a/acorn.js +++ b/acorn.js @@ -2008,7 +2008,9 @@ return parseLabeledStatement(node, maybeName, expr); } - if (expr.name === "declare") { + if (options.ecmaVersion >= 7 && expr.name === "private" && tokType === _name) { + return parsePrivate(node); + } else if (expr.name === "declare") { if (tokType === _class || tokType === _name || tokType === _function || tokType === _var) { return parseDeclare(node); } @@ -2988,6 +2990,15 @@ } } + function parsePrivate(node) { + node.declarations = []; + do { + node.declarations.push(parseIdent()); + } while (eat(_comma)); + semicolon(); + return finishNode(node, "PrivateDeclaration"); + } + // Parse a class declaration or literal (depending on the // `isStatement` parameter). @@ -3010,15 +3021,20 @@ expect(_braceL); while (!eat(_braceR)) { var method = startNode(); + if (options.ecmaVersion >= 7 && tokType === _name && tokVal === "private") { + next(); + classBody.body.push(parsePrivate(method)); + continue; + } if (tokType === _name && tokVal === "static") { next(); method['static'] = true; - } else { + } else { method['static'] = false; - } + } var isAsync = false; var isGenerator = eat(_star); - if (options.ecmaVersion >= 7 && !isGenerator && tokType === _name && tokVal === "async") { + if (options.ecmaVersion >= 7 && !isGenerator && tokType === _name && tokVal === "async") { var asyncId = parseIdent(); if (tokType === _colon || tokType === _parenL) { method.key = asyncId; diff --git a/test/tests-6to5.js b/test/tests-6to5.js index 87416eca36..a0a24fe647 100644 --- a/test/tests-6to5.js +++ b/test/tests-6to5.js @@ -2088,3 +2088,131 @@ test('delete foo::bar;', { }, { ecmaVersion: 7 }); + +test("private A;", { + type: "Program", + start: 0, + end: 10, + body: [{ + type: "PrivateDeclaration", + start: 0, + end: 10, + declarations: [{ + type: "Identifier", + start: 8, + end: 9, + name: "A" + }] + }] +}, { + ecmaVersion: 7 +}); + +test("private A, B;", { + type: "Program", + start: 0, + end: 13, + body: [{ + type: "PrivateDeclaration", + start: 0, + end: 13, + declarations: [ + { + type: "Identifier", + start: 8, + end: 9, + name: "A" + }, + { + type: "Identifier", + start: 11, + end: 12, + name: "B" + } + ] + }] +}, { + ecmaVersion: 7 +}); + +test("class A { private A; }", { + type: "Program", + start: 0, + end: 22, + body: [{ + type: "ClassDeclaration", + start: 0, + end: 22, + id: { + type: "Identifier", + start: 6, + end: 7, + name: "A" + }, + superClass: null, + body: { + type: "ClassBody", + start: 8, + end: 22, + body: [{ + type: "PrivateDeclaration", + start: 10, + end: 20, + declarations: [ + { + type: "Identifier", + start: 18, + end: 19, + name: "A" + } + ] + }] + } + }] +}, { + ecmaVersion: 7 +}); + +test("class A { private A, B; }", { + type: "Program", + start: 0, + end: 25, + body: [{ + type: "ClassDeclaration", + start: 0, + end: 25, + id: { + type: "Identifier", + start: 6, + end: 7, + name: "A" + }, + superClass: null, + body: { + type: "ClassBody", + start: 8, + end: 25, + body: [{ + type: "PrivateDeclaration", + start: 10, + end: 23, + declarations: [ + { + type: "Identifier", + start: 18, + end: 19, + name: "A" + }, + { + type: "Identifier", + start: 21, + end: 22, + name: "B" + } + ] + }] + } + }] +}, { + ecmaVersion: 7 +}); From e3b63530b18dd23c1a7d5a0bb77f0ed91db2d560 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 14 Dec 2014 14:52:25 +1100 Subject: [PATCH 089/198] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2010451e4f..59f509ecbf 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.9.1-13", + "version": "0.9.1-14", "maintainers": [ { "name": "Marijn Haverbeke", From 16b7d59ae5d93b4778941c1811eee722492d34b8 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Mon, 15 Dec 2014 09:39:24 +1100 Subject: [PATCH 090/198] allow async generator functions - closes #10 - thanks @fkling --- acorn.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/acorn.js b/acorn.js index 56cc6cfc0c..3aa7f661c7 100644 --- a/acorn.js +++ b/acorn.js @@ -2763,7 +2763,7 @@ prop.shorthand = false; isGenerator = eat(_star); } - if (options.ecmaVersion >= 7 && !isGenerator && tokType === _name && tokVal === "async") { + if (options.ecmaVersion >= 7 && tokType === _name && tokVal === "async") { var asyncId = parseIdent(); if (tokType === _colon || tokType === _parenL) { prop.key = asyncId; @@ -2840,7 +2840,6 @@ function parseFunction(node, isStatement, isAsync, allowExpressionBody) { initFunction(node, isAsync); if (options.ecmaVersion >= 6) { - if (isAsync && tokType === _star) unexpected(); node.generator = eat(_star); } if (isStatement || tokType === _name) { From 59c9f473ae71b68d24bb1d959c69c3795d83ae72 Mon Sep 17 00:00:00 2001 From: Felix Kling Date: Mon, 15 Dec 2014 22:33:47 -0800 Subject: [PATCH 091/198] Support async functions in export declarations 6to5 is able to transpile `export async function foo(){}` but acorn-6to5 is unable to parse it. --- acorn.js | 2 +- bin/acorn | 1 + test/tests-6to5.js | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index 3aa7f661c7..570ec31b9b 100644 --- a/acorn.js +++ b/acorn.js @@ -3139,7 +3139,7 @@ function parseExport(node) { next(); // export var|const|let|function|class ...; - if (tokType === _var || tokType === _const || tokType === _let || tokType === _function || tokType === _class) { + if (tokType === _var || tokType === _const || tokType === _let || tokType === _function || tokType === _class || tokType === _name && tokVal === 'async') { node.declaration = parseStatement(); node['default'] = false; node.specifiers = null; diff --git a/bin/acorn b/bin/acorn index 2a226da063..dd5baea012 100755 --- a/bin/acorn +++ b/bin/acorn @@ -20,6 +20,7 @@ for (var i = 2; i < process.argv.length; ++i) { else if (arg == "--ecma3") options.ecmaVersion = 3; else if (arg == "--ecma5") options.ecmaVersion = 5; else if (arg == "--ecma6") options.ecmaVersion = 6; + else if (arg == "--ecma7") options.ecmaVersion = 7; else if (arg == "--strictSemicolons") options.strictSemicolons = true; else if (arg == "--locations") options.locations = true; else if (arg == "--silent") silent = true; diff --git a/test/tests-6to5.js b/test/tests-6to5.js index a0a24fe647..708937b9cd 100644 --- a/test/tests-6to5.js +++ b/test/tests-6to5.js @@ -1901,6 +1901,45 @@ test('var obj = { async() {} };', { ecmaVersion: 7 }); +test('export async function foo(){}', { + "type": "Program", + "start": 0, + "end": 29, + "body": [{ + "type": "ExportDeclaration", + "start": 0, + "end": 29, + "declaration": { + "type": "FunctionDeclaration", + "start": 7, + "end": 29, + "id": { + "type": "Identifier", + "start": 22, + "end": 25, + "name": "foo" + }, + "params": [], + "defaults": [], + "rest": null, + "generator": false, + "async": true, + "body": { + "type": "BlockStatement", + "start": 27, + "end": 29, + "body": [] + }, + "expression": false + }, + "default": false, + "specifiers": null, + "source": null + }] +}, { + ecmaVersion: 7 +}); + // ES7: Abstract references test('foo::bar;', { From 0bea7c9d51d64ed71f5816d8569329ff81f49ba0 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 27 Dec 2014 19:54:23 +1100 Subject: [PATCH 092/198] Fix export default functions and classes being parsed as expressions instead of declarations --- acorn.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index 401b9421c8..de24f8571c 100644 --- a/acorn.js +++ b/acorn.js @@ -2476,7 +2476,11 @@ } else // export default ...; if (eat(_default)) { - node.declaration = parseExpression(true); + if (tokType === _function || tokType === _class) { + node.declaration = parseStatement(); + } else { + node.declaration = parseExpression(true); + } node['default'] = true; node.specifiers = null; node.source = null; From d727f9749792e15658c0af6c786d26d3fe902e42 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 27 Dec 2014 20:07:59 +1100 Subject: [PATCH 093/198] fix export default declarations --- acorn.js | 11 +++++++---- package.json | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/acorn.js b/acorn.js index a783a530fc..f5656d254e 100644 --- a/acorn.js +++ b/acorn.js @@ -3183,10 +3183,13 @@ } else // export default ...; if (eat(_default)) { - if (tokType === _function || tokType === _class) { - node.declaration = parseStatement(); - } else { - node.declaration = parseExpression(true); + var declar = node.declaration = parseExpression(true); + if (declar.id) { + if (declar.type === "FunctionExpression") { + declar.type = "FunctionDeclaration"; + } else if (declar.type === "ClassExpression") { + declar.type = "ClassDeclaration"; + } } node['default'] = true; node.specifiers = null; diff --git a/package.json b/package.json index 8f916d26c3..7003a8f05d 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.9.1-15", + "version": "0.9.1-16", "maintainers": [ { "name": "Marijn Haverbeke", From 9e6e19eca8bf7107842cc0e6cdc340a181da1d1a Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 31 Dec 2014 11:48:25 +1100 Subject: [PATCH 094/198] parse this shorthand as an ident with subscripts instead of a regular expression --- acorn.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index f5656d254e..319d4b1fe4 100644 --- a/acorn.js +++ b/acorn.js @@ -2563,10 +2563,11 @@ return finishNode(node, "ThisExpression"); case _at: + var start = storeCurrentPos(); var node = startNode(); next(); node.object = { type: "ThisExpression" } - node.property = parseExprSubscripts(); + node.property = parseSubscripts(parseIdent(), start); node.computed = false; return finishNode(node, "MemberExpression"); From b5c8ee2120e568adcfcc386d80aeda11a4655f98 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 31 Dec 2014 11:50:54 +1100 Subject: [PATCH 095/198] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7003a8f05d..e48fd1d010 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.9.1-16", + "version": "0.11.1-1", "maintainers": [ { "name": "Marijn Haverbeke", From 56bc618d33b22480ec2ed4f0a186e83024602a50 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Fri, 2 Jan 2015 04:21:56 +1100 Subject: [PATCH 096/198] actually parse async functions as statements --- acorn.js | 49 +++++++++++++++++++++++++++---------------------- package.json | 2 +- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/acorn.js b/acorn.js index f1c6cf4077..df16c19886 100644 --- a/acorn.js +++ b/acorn.js @@ -2008,7 +2008,7 @@ if (tokType === _slash || tokType === _assign && tokVal == "/=") readToken(true); - var starttype = tokType, node = startNode(); + var starttype = tokType, node = startNode(), start = storeCurrentPos(); // Most types of statements are recognized by the keyword they // start with. Many are trivial to parse, some require a bit of @@ -2043,28 +2043,33 @@ // next token is a colon and the expression was a simple // Identifier node, we switch to interpreting it as a label. default: - var maybeName = tokVal, expr = parseExpression(); - if (starttype === _name) { - if (expr.type === "FunctionExpression" && expr.async) { - expr.type = "FunctionDeclaration"; - return expr; - } else if (expr.type === "Identifier") { - if (eat(_colon)) { - return parseLabeledStatement(node, maybeName, expr); - } + if (tokType === _name && tokVal === "async") { + var id = parseIdent(); + if (tokType === _function) { + next(); + return parseFunction(node, true, true); + } else { + return parseSubscripts(id, start); + } + } - if (options.ecmaVersion >= 7 && expr.name === "private" && tokType === _name) { - return parsePrivate(node); - } else if (expr.name === "declare") { - if (tokType === _class || tokType === _name || tokType === _function || tokType === _var) { - return parseDeclare(node); - } - } else if (tokType === _name) { - if (expr.name === "interface") { - return parseInterface(node); - } else if (expr.name === "type") { - return parseTypeAlias(node); - } + var maybeName = tokVal, expr = parseExpression(); + if (starttype === _name && expr.type === "Identifier") { + if (eat(_colon)) { + return parseLabeledStatement(node, maybeName, expr); + } + + if (options.ecmaVersion >= 7 && expr.name === "private" && tokType === _name) { + return parsePrivate(node); + } else if (expr.name === "declare") { + if (tokType === _class || tokType === _name || tokType === _function || tokType === _var) { + return parseDeclare(node); + } + } else if (tokType === _name) { + if (expr.name === "interface") { + return parseInterface(node); + } else if (expr.name === "type") { + return parseTypeAlias(node); } } } diff --git a/package.json b/package.json index e48fd1d010..f7e89739c3 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.11.1-1", + "version": "0.11.1-2", "maintainers": [ { "name": "Marijn Haverbeke", From c8fc778ffb2211a972e2e35fb8f9507e8fbc1e9f Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Fri, 2 Jan 2015 05:02:59 +1100 Subject: [PATCH 097/198] add ecmaVersion check to async function statements --- acorn.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/acorn.js b/acorn.js index df16c19886..3476392618 100644 --- a/acorn.js +++ b/acorn.js @@ -2043,7 +2043,7 @@ // next token is a colon and the expression was a simple // Identifier node, we switch to interpreting it as a label. default: - if (tokType === _name && tokVal === "async") { + if (options.ecmaVersion >= 7 && tokType === _name && tokVal === "async") { var id = parseIdent(); if (tokType === _function) { next(); diff --git a/package.json b/package.json index f7e89739c3..bded093ed5 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.11.1-2", + "version": "0.11.1-3", "maintainers": [ { "name": "Marijn Haverbeke", From 017d76c720e21fce468daef886887ec88bd61e36 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sat, 3 Jan 2015 06:09:37 +1100 Subject: [PATCH 098/198] set location info on ThisExpression node in this shorthand - fixes 6to5/6to5#367 --- acorn.js | 3 ++- package.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/acorn.js b/acorn.js index 3476392618..536605abc5 100644 --- a/acorn.js +++ b/acorn.js @@ -2570,8 +2570,9 @@ case _at: var start = storeCurrentPos(); var node = startNode(); + var thisNode = startNode(); next(); - node.object = { type: "ThisExpression" } + node.object = finishNode(thisNode, "ThisExpression"); node.property = parseSubscripts(parseIdent(), start); node.computed = false; return finishNode(node, "MemberExpression"); diff --git a/package.json b/package.json index bded093ed5..9df29bd4da 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.11.1-3", + "version": "0.11.1-4", "maintainers": [ { "name": "Marijn Haverbeke", From 9c3c569ac608694dce069f043d12f3975ca2455c Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 4 Jan 2015 08:12:23 +1100 Subject: [PATCH 099/198] remove checkLVal from class heritage --- acorn.js | 1 - package.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/acorn.js b/acorn.js index 536605abc5..0be40874b3 100644 --- a/acorn.js +++ b/acorn.js @@ -3052,7 +3052,6 @@ node.typeParameters = parseTypeParameterDeclaration(); } node.superClass = eat(_extends) ? parseMaybeAssign(false, true) : null; - if (node.superClass) checkLVal(node.superClass); if (node.superClass && tokType === _lt) { node.superTypeParameters = parseTypeParameterInstantiation(); } diff --git a/package.json b/package.json index 9df29bd4da..61f63257f9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.11.1-4", + "version": "0.11.1-5", "maintainers": [ { "name": "Marijn Haverbeke", From 55b3e96d955dcb18ad1c9fb36f883917ab1a00e8 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 4 Jan 2015 18:20:08 +1100 Subject: [PATCH 100/198] add support for semicolons as class elements --- acorn.js | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index 0be40874b3..9a7f13f19c 100644 --- a/acorn.js +++ b/acorn.js @@ -3063,6 +3063,10 @@ classBody.body = []; expect(_braceL); while (!eat(_braceR)) { + if (eat(_semi)) { + continue; + } + var method = startNode(); if (options.ecmaVersion >= 7 && tokType === _name && tokVal === "private") { next(); diff --git a/package.json b/package.json index 61f63257f9..bbbbb2e551 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.11.1-5", + "version": "0.11.1-6", "maintainers": [ { "name": "Marijn Haverbeke", From cec7b1ba3f9d3dcf22513894dcf50d336ad8cf61 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 4 Jan 2015 19:37:38 +1100 Subject: [PATCH 101/198] better acorn async statement parsing --- acorn.js | 41 +++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/acorn.js b/acorn.js index 9a7f13f19c..c95a6636e8 100644 --- a/acorn.js +++ b/acorn.js @@ -2043,17 +2043,9 @@ // next token is a colon and the expression was a simple // Identifier node, we switch to interpreting it as a label. default: - if (options.ecmaVersion >= 7 && tokType === _name && tokVal === "async") { - var id = parseIdent(); - if (tokType === _function) { - next(); - return parseFunction(node, true, true); - } else { - return parseSubscripts(id, start); - } - } + var maybeName = tokVal, expr = parseExpression(false, false, true); + if (expr.type === "FunctionDeclaration") return expr; - var maybeName = tokVal, expr = parseExpression(); if (starttype === _name && expr.type === "Identifier") { if (eat(_colon)) { return parseLabeledStatement(node, maybeName, expr); @@ -2387,9 +2379,9 @@ // sequences (in argument lists, array literals, or object literals) // or the `in` operator (in for loops initalization expressions). - function parseExpression(noComma, noIn) { + function parseExpression(noComma, noIn, isStatement) { var start = storeCurrentPos(); - var expr = parseMaybeAssign(noIn); + var expr = parseMaybeAssign(noIn, false, isStatement); if (!noComma && tokType === _comma) { var node = startNodeAt(start); node.expressions = [expr]; @@ -2402,9 +2394,9 @@ // Parse an assignment expression. This includes applications of // operators like `+=`. - function parseMaybeAssign(noIn, noLess) { + function parseMaybeAssign(noIn, noLess, isStatement) { var start = storeCurrentPos(); - var left = parseMaybeConditional(noIn, noLess); + var left = parseMaybeConditional(noIn, noLess, isStatement); if (tokType.isAssign) { var node = startNodeAt(start); node.operator = tokVal; @@ -2419,9 +2411,9 @@ // Parse a ternary conditional (`?:`) operator. - function parseMaybeConditional(noIn, noLess) { + function parseMaybeConditional(noIn, noLess, isStatement) { var start = storeCurrentPos(); - var expr = parseExprOps(noIn, noLess); + var expr = parseExprOps(noIn, noLess, isStatement); if (eat(_question)) { var node = startNodeAt(start); if (eat(_eq)) { @@ -2442,9 +2434,9 @@ // Start the precedence parser. - function parseExprOps(noIn, noLess) { + function parseExprOps(noIn, noLess, isStatement) { var start = storeCurrentPos(); - return parseExprOp(parseMaybeUnary(), start, -1, noIn, noLess); + return parseExprOp(parseMaybeUnary(isStatement), start, -1, noIn, noLess); } // Parse binary operators with the operator precedence parsing @@ -2473,7 +2465,7 @@ // Parse unary operators, both prefix and postfix. - function parseMaybeUnary() { + function parseMaybeUnary(isStatement) { if (tokType.prefix) { var node = startNode(), update = tokType.isUpdate, nodeType; if (tokType === _ellipsis) { @@ -2493,7 +2485,7 @@ return finishNode(node, nodeType); } var start = storeCurrentPos(); - var expr = parseExprSubscripts(); + var expr = parseExprSubscripts(isStatement); while (tokType.postfix && !canInsertSemicolon()) { var node = startNodeAt(start); node.operator = tokVal; @@ -2508,9 +2500,9 @@ // Parse call, dot, and `[]`-subscript expressions. - function parseExprSubscripts() { + function parseExprSubscripts(isStatement) { var start = storeCurrentPos(); - return parseSubscripts(parseExprAtom(), start); + return parseSubscripts(parseExprAtom(isStatement), start); } function parseSubscripts(base, start, noCalls) { @@ -2560,7 +2552,7 @@ // `new`, or an expression wrapped in punctuation like `()`, `[]`, // or `{}`. - function parseExprAtom() { + function parseExprAtom(isStatement) { switch (tokType) { case _this: var node = startNode(); @@ -2618,7 +2610,8 @@ // normal functions if (tokType === _function) { next(); - return parseFunction(node, false, true); + console.trace(); + return parseFunction(node, isStatement, true); } } else if (id.name === "await") { if (inAsync) return parseAwait(node); diff --git a/package.json b/package.json index bbbbb2e551..e83a382ba5 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.11.1-6", + "version": "0.11.1-7", "maintainers": [ { "name": "Marijn Haverbeke", From 8dad17b6757a9e0399168d8d9613f6abefd26d21 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 4 Jan 2015 19:49:10 +1100 Subject: [PATCH 102/198] remove console.trace --- acorn.js | 1 - package.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/acorn.js b/acorn.js index c95a6636e8..2738f6bbd7 100644 --- a/acorn.js +++ b/acorn.js @@ -2610,7 +2610,6 @@ // normal functions if (tokType === _function) { next(); - console.trace(); return parseFunction(node, isStatement, true); } } else if (id.name === "await") { diff --git a/package.json b/package.json index e83a382ba5..6997fe3d42 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.11.1-7", + "version": "0.11.1-8", "maintainers": [ { "name": "Marijn Haverbeke", From 1eeb505bf4b35eb358601a111c098922418d2904 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 4 Jan 2015 20:35:51 +1100 Subject: [PATCH 103/198] no line terminator after contextual async keyword --- acorn.js | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index 2738f6bbd7..234b3e9b07 100644 --- a/acorn.js +++ b/acorn.js @@ -2609,6 +2609,13 @@ // normal functions if (tokType === _function) { + if (isStatement) { + // no line terminator after `async` contextual keyword + if (tokType === _semi || canInsertSemicolon()) { + return id; + } + } + next(); return parseFunction(node, isStatement, true); } diff --git a/package.json b/package.json index 6997fe3d42..29c3f6ce5f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.11.1-8", + "version": "0.11.1-9", "maintainers": [ { "name": "Marijn Haverbeke", From f2c78674af3c42126a26804cd65b0f563a138675 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Sun, 4 Jan 2015 21:14:18 +1100 Subject: [PATCH 104/198] better class element semicolons --- acorn.js | 7 ++----- package.json | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/acorn.js b/acorn.js index 234b3e9b07..f529e39b5f 100644 --- a/acorn.js +++ b/acorn.js @@ -3062,10 +3062,8 @@ classBody.body = []; expect(_braceL); while (!eat(_braceR)) { - if (eat(_semi)) { - continue; - } - + while (eat(_semi)); + if (tokType === _braceR) continue; var method = startNode(); if (options.ecmaVersion >= 7 && tokType === _name && tokVal === "private") { next(); @@ -3112,7 +3110,6 @@ method.value = parseMethod(isGenerator, isAsync); method.value.typeParameters = typeParameters; classBody.body.push(finishNode(method, "MethodDefinition")); - eat(_semi); } } node.body = finishNode(classBody, "ClassBody"); diff --git a/package.json b/package.json index 29c3f6ce5f..cd22d22b71 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.11.1-9", + "version": "0.11.1-10", "maintainers": [ { "name": "Marijn Haverbeke", From 8c25cb0d80f63b931a53a9f3b607922bf587ae29 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Tue, 6 Jan 2015 10:42:57 +1100 Subject: [PATCH 105/198] add higher priority to exponent operator, better async contextual functions --- acorn.js | 10 +++------- package.json | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/acorn.js b/acorn.js index f93cb72511..225b588c3f 100644 --- a/acorn.js +++ b/acorn.js @@ -469,7 +469,7 @@ // '*' may be multiply or have special meaning in ES6 var _star = {binop: 10, beforeExpr: true}; - var _exponent = {binop: 10, beforeExpr: true}; + var _exponent = {binop: 11, beforeExpr: true}; // '<', '>' may be relational or have special meaning in JSX var _lt = {binop: 7, beforeExpr: true}, _gt = {binop: 7, beforeExpr: true}; @@ -2618,12 +2618,8 @@ // normal functions if (tokType === _function) { - if (isStatement) { - // no line terminator after `async` contextual keyword - if (tokType === _semi || canInsertSemicolon()) { - return id; - } - } + // no line terminator after `async` contextual keyword + if (canInsertSemicolon()) return id; next(); return parseFunction(node, isStatement, true); diff --git a/package.json b/package.json index cd22d22b71..2309ef12b9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.11.1-10", + "version": "0.11.1-11", "maintainers": [ { "name": "Marijn Haverbeke", From 5c0d9a0e6194f2ce0fac37449616dae897461957 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Fri, 9 Jan 2015 05:54:16 +1100 Subject: [PATCH 106/198] Parse assignment patterns in-place in certain contexts. * Parsing assignables without extra transform step when possible (speed-up). * Added support for shorthand defaults in such certain contexts (issue #181). Conflicts: acorn.js acorn_loose.js --- acorn.js | 75 +++++++++++++++++++++++---- acorn_loose.js | 4 ++ test/tests-harmony.js | 117 +++++++++++++++++++++++++++++++++++------- 3 files changed, 166 insertions(+), 30 deletions(-) diff --git a/acorn.js b/acorn.js index 225b588c3f..47767ddc94 100644 --- a/acorn.js +++ b/acorn.js @@ -1828,7 +1828,8 @@ function has(obj, propName) { return Object.prototype.hasOwnProperty.call(obj, propName); } -// Convert existing expression atom to assignable pattern + + // Convert existing expression atom to assignable pattern // if possible. function toAssignable(node, allowSpread, checkType) { @@ -1878,6 +1879,53 @@ return node; } + // Parses lvalue (assignable) atom. + + function parseAssignableAtom() { + if (options.ecmaVersion < 6) return parseIdent(); + switch (tokType) { + case _name: + return parseIdent(); + + case _bracketL: + var node = startNode(); + next(); + var elts = node.elements = [], first = true; + while (!eat(_bracketR)) { + first ? first = false : expect(_comma); + if (tokType === _ellipsis) { + var spread = startNode(); + next(); + spread.argument = parseAssignableAtom(); + checkSpreadAssign(spread.argument); + elts.push(finishNode(spread, "SpreadElement")); + expect(_bracketR); + break; + } + elts.push(tokType === _comma ? null : parseMaybeDefault()); + } + return finishNode(node, "ArrayPattern"); + + case _braceL: + return parseObj(true); + + default: + unexpected(); + } + } + + // Parses assignment pattern around given atom if possible. + + function parseMaybeDefault(startPos, left) { + left = left || parseAssignableAtom(); + if (!eat(_eq)) return left; + var node = startPos ? startNodeAt(startPos) : startNode(); + node.operator = "="; + node.left = left; + node.right = parseMaybeAssign(); + return finishNode(node, "AssignmentPattern"); + } + // Checks if node can be assignable spread argument. function checkSpreadAssign(node) { @@ -2361,7 +2409,7 @@ node.kind = kind; for (;;) { var decl = startNode(); - decl.id = options.ecmaVersion >= 6 ? toAssignable(parseExprAtom()) : parseIdent(); + decl.id = parseAssignableAtom(); checkLVal(decl.id, true); if (tokType === _colon) { @@ -2788,7 +2836,7 @@ // Parse an object literal. - function parseObj() { + function parseObj(isPattern) { var node = startNode(), first = true, propHash = {}; node.properties = []; next(); @@ -2798,7 +2846,7 @@ if (options.allowTrailingCommas && eat(_braceR)) break; } else first = false; - var prop = startNode(), isGenerator = false, isAsync = false; + var prop = startNode(), start, isGenerator = false, isAsync = false; if (options.ecmaVersion >= 7 && tokType === _ellipsis) { prop = parseMaybeUnary(); prop.type = "SpreadProperty"; @@ -2808,7 +2856,11 @@ if (options.ecmaVersion >= 6) { prop.method = false; prop.shorthand = false; - isGenerator = eat(_star); + if (isPattern) { + start = storeCurrentPos(); + } else { + isGenerator = eat(_star); + } } if (options.ecmaVersion >= 7 && tokType === _name && tokVal === "async") { var asyncId = parseIdent(); @@ -2827,22 +2879,23 @@ if (tokType !== _parenL) unexpected(); } if (eat(_colon)) { - prop.value = parseExpression(true); + prop.value = isPattern ? parseMaybeDefault(start) : parseMaybeAssign(); prop.kind = "init"; } else if (options.ecmaVersion >= 6 && tokType === _parenL) { + if (isPattern) unexpected(); prop.kind = "init"; prop.method = true; prop.value = parseMethod(isGenerator, isAsync); } else if (options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set"|| (options.playground && prop.key.name === "memo")) && (tokType != _comma && tokType != _braceR)) { - if (isGenerator || isAsync) unexpected(); + if (isGenerator || isAsync || isPattern) unexpected(); prop.kind = prop.key.name; parsePropertyName(prop); prop.value = parseMethod(false, false); } else if (options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { prop.kind = "init"; - prop.value = prop.key; + prop.value = isPattern ? parseMaybeDefault(start, prop.key) : prop.key; prop.shorthand = true; } else unexpected(); @@ -2850,7 +2903,7 @@ checkPropClash(prop, propHash); node.properties.push(finishNode(prop, "Property")); } - return finishNode(node, "ObjectExpression"); + return finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression"); } function parsePropertyName(prop) { @@ -2960,7 +3013,7 @@ if (eat(_parenR)) { break; } else if (options.ecmaVersion >= 6 && eat(_ellipsis)) { - node.rest = toAssignable(parseExprAtom(), false, true); + node.rest = parseAssignableAtom(); checkSpreadAssign(node.rest); parseFunctionParam(node.rest); expect(_parenR); @@ -3358,7 +3411,7 @@ var block = startNode(); next(); expect(_parenL); - block.left = toAssignable(parseExprAtom()); + block.left = parseAssignableAtom(); checkLVal(block.left, true); if (tokType !== _name || tokVal !== "of") unexpected(); next(); diff --git a/acorn_loose.js b/acorn_loose.js index 867e21fa19..2f41edd588 100644 --- a/acorn_loose.js +++ b/acorn_loose.js @@ -983,6 +983,10 @@ case "SpreadElement": node.argument = toAssignable(node.argument); break; + + case "AssignmentExpression": + node.type = "AssignmentPattern"; + break; } } return checkLVal(node); diff --git a/test/tests-harmony.js b/test/tests-harmony.js index 72153b0a43..fa19a011b6 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -14393,30 +14393,39 @@ test('var {get} = obj;', { test("var {propName: localVar = defaultValue} = obj", { type: "Program", + range: [0, 45], body: [{ type: "VariableDeclaration", + range: [0, 45], declarations: [{ type: "VariableDeclarator", + range: [4, 45], id: { type: "ObjectPattern", + range: [4, 39], properties: [{ type: "Property", + range: [5, 38], method: false, shorthand: false, computed: false, key: { type: "Identifier", + range: [5, 13], name: "propName" }, value: { type: "AssignmentPattern", + range: [5, 38], operator: "=", left: { type: "Identifier", + range: [15, 23], name: "localVar" }, right: { type: "Identifier", + range: [26, 38], name: "defaultValue" } }, @@ -14425,44 +14434,114 @@ test("var {propName: localVar = defaultValue} = obj", { }, init: { type: "Identifier", + range: [42, 45], name: "obj" } }], kind: "var" }] -}, {ecmaVersion: 6}); +}, { + ecmaVersion: 6, + ranges: true, + locations: true, + loose: false +}); -test("var [a = 1, b = 2] = arr", { +test("var {propName = defaultValue} = obj", { type: "Program", + range: [0, 35], body: [{ type: "VariableDeclaration", + range: [0, 35], declarations: [{ type: "VariableDeclarator", + range: [4, 35], id: { - type: "ArrayPattern", - elements: [ - { - type: "AssignmentPattern", - operator: "=", - left: {type: "Identifier", name: "a"}, - right: { - type: "Literal", - value: 1 - } + type: "ObjectPattern", + range: [4, 29], + properties: [{ + type: "Property", + range: [5, 28], + method: false, + shorthand: true, + computed: false, + key: { + type: "Identifier", + range: [5, 13], + name: "propName" }, - { + kind: "init", + value: { type: "AssignmentPattern", + range: [5, 28], operator: "=", - left: {type: "Identifier", name: "b"}, + left: { + type: "Identifier", + range: [5, 13], + name: "propName" + }, right: { - type: "Literal", - value: 2 + type: "Identifier", + range: [16, 28], + name: "defaultValue" } } - ] + }] }, - init: {type: "Identifier", name: "arr"} + init: { + type: "Identifier", + range: [32, 35], + name: "obj" + } }], kind: "var" }] -}, {ecmaVersion: 6}); +}, { + ecmaVersion: 6, + ranges: true, + locations: true, + loose: false +}); + +test("var [localVar = defaultValue] = obj", { + type: "Program", + range: [0, 35], + body: [{ + type: "VariableDeclaration", + range: [0, 35], + declarations: [{ + type: "VariableDeclarator", + range: [4, 35], + id: { + type: "ArrayPattern", + range: [4, 29], + elements: [{ + type: "AssignmentPattern", + range: [16, 28], + operator: "=", + left: { + type: "Identifier", + range: [5, 13], + name: "localVar" + }, + right: { + type: "Identifier", + range: [16, 28], + name: "defaultValue" + } + }] + }, + init: { + type: "Identifier", + range: [32, 35], + name: "obj" + } + }], + kind: "var" + }] +}, { + ecmaVersion: 6, + ranges: true, + locations: true, + loose: false +}); From 9d4ab350f5ac488afb01cd7150c0d3e6e914dffd Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Fri, 9 Jan 2015 05:54:50 +1100 Subject: [PATCH 107/198] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2309ef12b9..8c6db8c256 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.11.1-11", + "version": "0.11.1-12", "maintainers": [ { "name": "Marijn Haverbeke", From 8ca1be061ea3fe0abb9e057aba525332b59e3d96 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Fri, 9 Jan 2015 05:58:57 +1100 Subject: [PATCH 108/198] fix destructering defaults in params --- acorn.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acorn.js b/acorn.js index 47767ddc94..331ee43169 100644 --- a/acorn.js +++ b/acorn.js @@ -3020,7 +3020,7 @@ defaults.push(null); break; } else { - var param = options.ecmaVersion >= 6 ? toAssignable(parseExprAtom(), false, true) : parseIdent(); + var param = parseAssignableAtom(); parseFunctionParam(param); node.params.push(param); From eb37a57fb0b8d6a02aa6648924838d493e1410e4 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sun, 11 Jan 2015 23:36:41 +0200 Subject: [PATCH 109/198] Fix for '/text
    ': { + type: "ExpressionStatement", + start: 0, + end: 16, + expression: { + type: "XJSElement", + start: 0, + end: 16, + openingElement: { + type: "XJSOpeningElement", + start: 0, + end: 5, + attributes: [], + name: { + type: "XJSIdentifier", + start: 1, + end: 4, + name: "div" + }, + selfClosing: false + }, + closingElement: { + type: "XJSClosingElement", + start: 10, + end: 16, + name: { + type: "XJSIdentifier", + start: 12, + end: 15, + name: "div" + } + }, + children: [{ + type: "Literal", + start: 5, + end: 10, + value: "/text", + raw: "/text" + }] + } } } }; From 735c7614ed37b390154facdc747ec7708947439a Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Mon, 12 Jan 2015 11:44:56 +1100 Subject: [PATCH 110/198] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8c6db8c256..139576750d 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "acorn-6to5", "description": "Acorn fork used by 6to5", "main": "acorn.js", - "version": "0.11.1-12", + "version": "0.11.1-13", "maintainers": [ { "name": "Marijn Haverbeke", From 482b94563e7bbefff681b316469428075eae7484 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Tue, 13 Jan 2015 22:39:00 +1100 Subject: [PATCH 111/198] add csp version as default - fixes #13 --- Makefile | 10 + acorn_csp.js | 4323 ++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 3 files changed, 4334 insertions(+), 1 deletion(-) create mode 100644 Makefile create mode 100644 acorn_csp.js diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..d420111a2a --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +.PHONY: publish + +publish: + read -p "Version: " version; \ + npm version $$version --message "v%s" + + bin/without_eval >acorn_csp.js + npm publish + + git push --follow-tags diff --git a/acorn_csp.js b/acorn_csp.js new file mode 100644 index 0000000000..d566cab7cf --- /dev/null +++ b/acorn_csp.js @@ -0,0 +1,4323 @@ +// Acorn is a tiny, fast JavaScript parser written in JavaScript. +// +// 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](http://esprima.org) by +// Ariya Hidayat. +// +// Git repositories for Acorn are available at +// +// http://marijnhaverbeke.nl/git/acorn +// https://github.com/marijnh/acorn.git +// +// Please use the [github bug tracker][ghbt] to report issues. +// +// [ghbt]: https://github.com/marijnh/acorn/issues +// +// This file defines the main parser interface. The library also comes +// with a [error-tolerant parser][dammit] and an +// [abstract syntax tree walker][walk], defined in other files. +// +// [dammit]: acorn_loose.js +// [walk]: util/walk.js + +(function(root, mod) { + if (typeof exports == "object" && typeof module == "object") return mod(exports); // CommonJS + if (typeof define == "function" && define.amd) return define(["exports"], mod); // AMD + mod(root.acorn || (root.acorn = {})); // Plain browser env +})(this, function(exports) { + "use strict"; + + exports.version = "0.11.1"; + + // The main exported interface (under `self.acorn` when in the + // browser) is a `parse` function that takes a code string and + // returns an abstract syntax tree as specified by [Mozilla parser + // API][api], with the caveat that inline XML is not recognized. + // + // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API + + var options, input, inputLen, sourceFile; + + exports.parse = function(inpt, opts) { + input = String(inpt); inputLen = input.length; + setOptions(opts); + initTokenState(); + var startPos = options.locations ? [tokPos, curPosition()] : tokPos; + initParserState(); + return parseTopLevel(options.program || startNodeAt(startPos)); + }; + + // A second optional argument can be given to further configure + // the parser process. These options are recognized: + + var defaultOptions = exports.defaultOptions = { + playground: false, + // `ecmaVersion` indicates the ECMAScript version to parse. Must + // be either 3, or 5, or 6. This influences support for strict + // mode, the set of reserved words, support for getters and + // setters and other features. + ecmaVersion: 5, + // Turn on `strictSemicolons` to prevent the parser from doing + // automatic semicolon insertion. + strictSemicolons: false, + // When `allowTrailingCommas` is false, the parser will not allow + // trailing commas in array and object literals. + allowTrailingCommas: true, + // By default, reserved words are not enforced. Enable + // `forbidReserved` to enforce them. When this option has the + // value "everywhere", reserved words and keywords can also not be + // used as property names. + forbidReserved: false, + // When enabled, a return at the top level is not considered an + // error. + allowReturnOutsideFunction: false, + // When enabled, import/export statements are not constrained to + // appearing at the top of the program. + allowImportExportEverywhere: false, + // When enabled, hashbang directive in the beginning of file + // is allowed and treated as a line comment. + allowHashBang: false, + // When `locations` is on, `loc` properties holding objects with + // `start` and `end` properties in `{line, column}` form (with + // line being 1-based and column 0-based) will be attached to the + // nodes. + locations: false, + // 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 + // boolean indicating whether this is a block (`/* */`) comment, + // `text` is the content of the comment, and `start` and `end` are + // character offsets that denote the start and end of the comment. + // When the `locations` option is on, two more parameters are + // passed, the full `{line, column}` locations of the start and + // end of the comments. Note that you are not allowed to call the + // parser from the callback—that will corrupt its internal state. + onComment: null, + // Nodes have their start and end characters offsets recorded in + // `start` and `end` properties (directly on the node, rather than + // the `loc` object, which holds line/column data. To also add a + // [semi-standardized][range] `range` property holding a `[start, + // end]` array with the same numbers, set the `ranges` option to + // `true`. + // + // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 + ranges: false, + // It is possible to parse multiple files into a single AST by + // passing the tree produced by parsing the first file as + // `program` option in subsequent parses. This will add the + // toplevel forms of the parsed file to the `Program` (top) node + // of an existing parse tree. + program: null, + // When `locations` is on, you can pass this to record the source + // file in every node's `loc` object. + sourceFile: null, + // This value, if given, is stored in every node, whether + // `locations` is on or off. + directSourceFile: null, + // When enabled, parenthesized expressions are represented by + // (non-standard) ParenthesizedExpression nodes + preserveParens: false + }; + + // This function tries to parse a single expression at a given + // offset in a string. Useful for parsing mixed-language formats + // that embed JavaScript expressions. + + exports.parseExpressionAt = function(inpt, pos, opts) { + input = String(inpt); inputLen = input.length; + setOptions(opts); + initTokenState(pos); + initParserState(); + return parseExpression(); + }; + + var isArray = function (obj) { + return Object.prototype.toString.call(obj) === "[object Array]"; + }; + + function setOptions(opts) { + options = {}; + for (var opt in defaultOptions) + options[opt] = opts && has(opts, opt) ? opts[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); + }; + } + if (options.strictMode) { + strict = true; + } + if (options.ecmaVersion >= 6) { + isKeyword = isEcma6Keyword; + } else { + isKeyword = isEcma5AndLessKeyword; + } + } + + // The `getLineInfo` function is mostly useful when the + // `locations` option is off (for performance reasons) and you + // want to find the line/column position for a given character + // offset. `input` should be the code string that the offset refers + // into. + + var getLineInfo = exports.getLineInfo = function(input, offset) { + for (var line = 1, cur = 0;;) { + lineBreak.lastIndex = cur; + var match = lineBreak.exec(input); + if (match && match.index < offset) { + ++line; + cur = match.index + match[0].length; + } 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. + // Because the tokenizer is optimized for being efficiently used by + // the Acorn parser itself, this interface is somewhat crude and not + // very modular. Performing another parse or call to `tokenize` will + // reset the internal state, and invalidate existing tokenizers. + + exports.tokenize = function(inpt, opts) { + input = String(inpt); inputLen = input.length; + setOptions(opts); + initTokenState(); + skipSpace(); + + function getToken(forceRegexp) { + lastEnd = tokEnd; + readToken(forceRegexp); + return new Token(); + } + getToken.jumpTo = function(pos, reAllowed) { + tokPos = pos; + if (options.locations) { + tokCurLine = 1; + tokLineStart = lineBreak.lastIndex = 0; + var match; + while ((match = lineBreak.exec(input)) && match.index < pos) { + ++tokCurLine; + tokLineStart = match.index + match[0].length; + } + } + tokRegexpAllowed = reAllowed; + skipSpace(); + }; + getToken.noRegexp = function() { + tokRegexpAllowed = false; + }; + getToken.options = options; + return getToken; + }; + + // State is kept in (closure-)global variables. We already saw the + // `options`, `input`, and `inputLen` variables above. + + // The current position of the tokenizer in the input. + + var tokPos; + + // The start and end offsets of the current token. + + var tokStart, tokEnd; + + // When `options.locations` is true, these hold objects + // containing the tokens start and end line/column pairs. + + var tokStartLoc, tokEndLoc; + + // The type and value of the current token. Token types are objects, + // named by variables against which they can be compared, and + // holding properties that describe them (indicating, for example, + // the precedence of an infix operator, and the original name of a + // keyword token). The kind of value that's held in `tokVal` depends + // on the type of the token. For literals, it is the literal value, + // for operators, the operator name, and so on. + + var tokType, tokVal; + + // Internal state for the tokenizer. To distinguish between division + // operators and regular expressions, it remembers whether the last + // token was one that is allowed to be followed by an expression. + // (If it is, a slash is probably a regexp, if it isn't it's a + // division operator. See the `parseStatement` function for a + // caveat.) + + var tokRegexpAllowed; + + // When `options.locations` is true, these are used to keep + // track of the current line, and know when a new line has been + // entered. + + var tokCurLine, tokLineStart; + + // These store the position of the previous token, which is useful + // when finishing a node and assigning its `end` position. + + var lastStart, lastEnd, lastEndLoc; + + // This is the parser's state. `inFunction` is used to reject + // `return` statements outside of functions, `inGenerator` to + // reject `yield`s outside of generators, `labels` to verify + // that `break` and `continue` have somewhere to jump to, and + // `strict` indicates whether strict mode is on. + + var inFunction, inGenerator, inAsync, labels, strict, + inXJSChild, inXJSTag, inType; + + // This counter is used for checking that arrow expressions did + // not contain nested parentheses in argument list. + + var metParenL; + + // This is used by the tokenizer to track the template strings it is + // inside, and count the amount of open braces seen inside them, to + // be able to switch back to a template token when the } to match ${ + // is encountered. It will hold an array of integers. + + var templates; + + function initParserState() { + lastStart = lastEnd = tokPos; + if (options.locations) lastEndLoc = new Position; + inFunction = inGenerator = inAsync = strict = false; + labels = []; + skipSpace(); + readToken(); + } + + // This function is used to raise exceptions on parse errors. It + // takes an offset integer (into the current `input`) to indicate + // the location of the error, attaches the position to the end + // of the error message, and then raises a `SyntaxError` with that + // message. + + function raise(pos, message) { + var loc = getLineInfo(input, pos); + message += " (" + loc.line + ":" + loc.column + ")"; + var err = new SyntaxError(message); + err.pos = pos; err.loc = loc; err.raisedAt = tokPos; + throw err; + } + + // Reused empty array added for node fields that are always empty. + + var empty = []; + + // ## 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. + + // These are the general types. The `type` property is only used to + // make them recognizeable when debugging. + + var _num = {type: "num"}, _regexp = {type: "regexp"}, _string = {type: "string"}; + var _name = {type: "name"}, _eof = {type: "eof"}; + + // These are JSX-specific token types + + var _xjsName = {type: "xjsName"}, _xjsText = {type: "xjsText"}; + + // Keyword tokens. The `keyword` property (also used in keyword-like + // operators) indicates that the token originated from an + // identifier-like word, which is used when parsing property names. + // + // The `beforeExpr` property is used to disambiguate between regular + // expressions and divisions. It is set on all token types that can + // be followed by an expression (thus, a slash after them would be a + // regular expression). + // + // `isLoop` marks a keyword as starting a loop, which is important + // to know when parsing a label, in order to allow or disallow + // continue jumps to that label. + + var _break = {keyword: "break"}, _case = {keyword: "case", beforeExpr: true}, _catch = {keyword: "catch"}; + var _continue = {keyword: "continue"}, _debugger = {keyword: "debugger"}, _default = {keyword: "default"}; + var _do = {keyword: "do", isLoop: true}, _else = {keyword: "else", beforeExpr: true}; + var _finally = {keyword: "finally"}, _for = {keyword: "for", isLoop: true}, _function = {keyword: "function"}; + var _if = {keyword: "if"}, _return = {keyword: "return", beforeExpr: true}, _switch = {keyword: "switch"}; + var _throw = {keyword: "throw", beforeExpr: true}, _try = {keyword: "try"}, _var = {keyword: "var"}; + var _let = {keyword: "let"}, _const = {keyword: "const"}; + var _while = {keyword: "while", isLoop: true}, _with = {keyword: "with"}, _new = {keyword: "new", beforeExpr: true}; + var _this = {keyword: "this"}; + var _class = {keyword: "class"}, _extends = {keyword: "extends", beforeExpr: true}; + var _export = {keyword: "export"}, _import = {keyword: "import"}; + var _yield = {keyword: "yield", beforeExpr: true}; + + // The keywords that denote values. + + var _null = {keyword: "null", atomValue: null}, _true = {keyword: "true", atomValue: true}; + var _false = {keyword: "false", atomValue: false}; + + // Some keywords are treated as regular operators. `in` sometimes + // (when parsing `for`) needs to be tested against specifically, so + // we assign a variable name to it for quick comparing. + + var _in = {keyword: "in", binop: 7, beforeExpr: true}; + + // Map keyword names to token types. + + var keywordTypes = {"break": _break, "case": _case, "catch": _catch, + "continue": _continue, "debugger": _debugger, "default": _default, + "do": _do, "else": _else, "finally": _finally, "for": _for, + "function": _function, "if": _if, "return": _return, "switch": _switch, + "throw": _throw, "try": _try, "var": _var, "let": _let, "const": _const, + "while": _while, "with": _with, + "null": _null, "true": _true, "false": _false, "new": _new, "in": _in, + "instanceof": {keyword: "instanceof", binop: 7, beforeExpr: true}, "this": _this, + "typeof": {keyword: "typeof", prefix: true, beforeExpr: true}, + "void": {keyword: "void", prefix: true, beforeExpr: true}, + "delete": {keyword: "delete", prefix: true, beforeExpr: true}, + "class": _class, "extends": _extends, + "export": _export, "import": _import, "yield": _yield}; + + // Punctuation token types. Again, the `type` property is purely for debugging. + + var _bracketL = {type: "[", beforeExpr: true}, _bracketR = {type: "]"}, _braceL = {type: "{", beforeExpr: true}; + var _braceR = {type: "}"}, _parenL = {type: "(", beforeExpr: true}, _parenR = {type: ")"}; + var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true}; + var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _question = {type: "?", beforeExpr: true}; + var _arrow = {type: "=>", beforeExpr: true}, _bquote = {type: "`"}, _dollarBraceL = {type: "${", beforeExpr: true}; + var _ltSlash = {type: "", beforeExpr: true}, _template = {type: "template"}, _templateContinued = {type: "templateContinued"}; + var _ellipsis = {type: "...", prefix: true, beforeExpr: true}; + var _paamayimNekudotayim = { type: "::", beforeExpr: true }; + var _at = { type: '@' }; + var _hash = { type: '#' }; + + // Operators. These carry several kinds of properties to help the + // parser use them properly (the presence of these properties is + // what categorizes them as operators). + // + // `binop`, when present, specifies that this operator is a binary + // operator, and will refer to its precedence. + // + // `prefix` and `postfix` mark the operator as a prefix or postfix + // unary operator. `isUpdate` specifies that the node produced by + // the operator should be of type UpdateExpression rather than + // simply UnaryExpression (`++` and `--`). + // + // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as + // binary operators with a very low precedence, that should result + // in AssignmentExpression nodes. + + var _slash = {binop: 10, beforeExpr: true}, _eq = {isAssign: true, beforeExpr: true}; + var _assign = {isAssign: true, beforeExpr: true}; + var _incDec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true}; + var _logicalOR = {binop: 1, beforeExpr: true}; + var _logicalAND = {binop: 2, beforeExpr: true}; + var _bitwiseOR = {binop: 3, beforeExpr: true}; + var _bitwiseXOR = {binop: 4, beforeExpr: true}; + var _bitwiseAND = {binop: 5, beforeExpr: true}; + var _equality = {binop: 6, beforeExpr: true}; + var _relational = {binop: 7, beforeExpr: true}; + var _bitShift = {binop: 8, beforeExpr: true}; + var _plusMin = {binop: 9, prefix: true, beforeExpr: true}; + var _modulo = {binop: 10, beforeExpr: true}; + + // '*' may be multiply or have special meaning in ES6 + var _star = {binop: 10, beforeExpr: true}; + var _exponent = {binop: 11, beforeExpr: true}; + + // '<', '>' may be relational or have special meaning in JSX + var _lt = {binop: 7, beforeExpr: true}, _gt = {binop: 7, beforeExpr: true}; + + // Provide access to the token types for external users of the + // tokenizer. + + exports.tokTypes = {bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR, + parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon, + dot: _dot, ellipsis: _ellipsis, question: _question, slash: _slash, eq: _eq, + name: _name, eof: _eof, num: _num, regexp: _regexp, string: _string, + arrow: _arrow, bquote: _bquote, dollarBraceL: _dollarBraceL, star: _star, + assign: _assign, xjsName: _xjsName, xjsText: _xjsText, + paamayimNekudotayim: _paamayimNekudotayim, exponent: _exponent, at: _at, hash: _hash, + template: _template, templateContinued: _templateContinued}; + for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw]; + + // 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 + // predicate containing a big ugly `switch` statement is faster than + // a regular expression, and on Chrome the two are about on par. + // This function uses `eval` (non-lexical) to produce such a + // predicate from a space-separated string of words. + // + // It starts by sorting the words by length. + + // Removed to create an eval-free library + + // The ECMAScript 3 reserved word list. + + var isReservedWord3 = function anonymous(str) { +switch(str.length){case 6:switch(str){case "double":case "export":case "import":case "native":case "public":case "static":case "throws":return true}return false;case 4:switch(str){case "byte":case "char":case "enum":case "goto":case "long":return true}return false;case 5:switch(str){case "class":case "final":case "float":case "short":case "super":return true}return false;case 7:switch(str){case "boolean":case "extends":case "package":case "private":return true}return false;case 9:switch(str){case "interface":case "protected":case "transient":return true}return false;case 8:switch(str){case "abstract":case "volatile":return true}return false;case 10:return str === "implements";case 3:return str === "int";case 12:return str === "synchronized";} +}; + + // ECMAScript 5 reserved words. + + var isReservedWord5 = function anonymous(str) { +switch(str.length){case 5:switch(str){case "class":case "super":case "const":return true}return false;case 6:switch(str){case "export":case "import":return true}return false;case 4:return str === "enum";case 7:return str === "extends";} +}; + + // The additional reserved words in strict mode. + + var isStrictReservedWord = function anonymous(str) { +switch(str.length){case 9:switch(str){case "interface":case "protected":return true}return false;case 7:switch(str){case "package":case "private":return true}return false;case 6:switch(str){case "public":case "static":return true}return false;case 10:return str === "implements";case 3:return str === "let";case 5:return str === "yield";} +}; + + // The forbidden variable names in strict mode. + + var isStrictBadIdWord = function anonymous(str) { +switch(str){case "eval":case "arguments":return true}return false; +}; + + // And the keywords. + + var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; + + var isEcma5AndLessKeyword = function anonymous(str) { +switch(str.length){case 4:switch(str){case "case":case "else":case "with":case "null":case "true":case "void":case "this":return true}return false;case 5:switch(str){case "break":case "catch":case "throw":case "while":case "false":return true}return false;case 3:switch(str){case "for":case "try":case "var":case "new":return true}return false;case 6:switch(str){case "return":case "switch":case "typeof":case "delete":return true}return false;case 8:switch(str){case "continue":case "debugger":case "function":return true}return false;case 2:switch(str){case "do":case "if":case "in":return true}return false;case 7:switch(str){case "default":case "finally":return true}return false;case 10:return str === "instanceof";} +}; + + var ecma6AndLessKeywords = ecma5AndLessKeywords + " let const class extends export import yield"; + + var isEcma6Keyword = function anonymous(str) { +switch(str.length){case 5:switch(str){case "break":case "catch":case "throw":case "while":case "false":case "const":case "class":case "yield":return true}return false;case 4:switch(str){case "case":case "else":case "with":case "null":case "true":case "void":case "this":return true}return false;case 6:switch(str){case "return":case "switch":case "typeof":case "delete":case "export":case "import":return true}return false;case 3:switch(str){case "for":case "try":case "var":case "new":case "let":return true}return false;case 8:switch(str){case "continue":case "debugger":case "function":return true}return false;case 7:switch(str){case "default":case "finally":case "extends":return true}return false;case 2:switch(str){case "do":case "if":case "in":return true}return false;case 10:return str === "instanceof";} +}; + + var isKeyword = isEcma5AndLessKeyword; + + // ## Character categories + + // Big ugly regular expressions that match characters in the + // whitespace, identifier, and identifier-start categories. These + // are only applied when a character is found to actually have a + // code point above 128. + // Generated by `tools/generate-identifier-regex.js`. + + var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; + var nonASCIIidentifierStartChars = "\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC"; + var nonASCIIidentifierChars = "\u0300-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u0669\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u06F0-\u06F9\u0711\u0730-\u074A\u07A6-\u07B0\u07C0-\u07C9\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E4-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0966-\u096F\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09E6-\u09EF\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A66-\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B66-\u0B6F\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0CE6-\u0CEF\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D66-\u0D6F\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0E50-\u0E59\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0ED0-\u0ED9\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1040-\u1049\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u18A9\u1920-\u192B\u1930-\u193B\u1946-\u194F\u19B0-\u19C0\u19C8\u19C9\u19D0-\u19D9\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AB0-\u1ABD\u1B00-\u1B04\u1B34-\u1B44\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BF3\u1C24-\u1C37\u1C40-\u1C49\u1C50-\u1C59\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u200C\u200D\u203F\u2040\u2054\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA620-\uA629\uA66F\uA674-\uA67D\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F1\uA900-\uA909\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9D0-\uA9D9\uA9E5\uA9F0-\uA9F9\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA50-\uAA59\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uABF0-\uABF9\uFB1E\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFF10-\uFF19\uFF3F"; + var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); + var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); + + var decimalNumber = /^\d+$/; + var hexNumber = /^[\da-fA-F]+$/; + + // Whether a single character denotes a newline. + + var newline = /[\n\r\u2028\u2029]/; + + function isNewLine(code) { + return code === 10 || code === 13 || code === 0x2028 || code == 0x2029; + } + + // Matches a whole line break (where CRLF is considered a single + // line break). Used to count lines. + + var lineBreak = /\r\n|[\n\r\u2028\u2029]/g; + + // Test whether a given character code starts an identifier. + + var isIdentifierStart = exports.isIdentifierStart = function(code) { + if (code < 65) return code === 36; + if (code < 91) return true; + if (code < 97) return code === 95; + if (code < 123)return true; + return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); + }; + + // Test whether a given character is part of an identifier. + + var isIdentifierChar = exports.isIdentifierChar = function(code) { + if (code < 48) return code === 36; + if (code < 58) return true; + if (code < 65) return false; + if (code < 91) return true; + if (code < 97) return code === 95; + if (code < 123)return true; + return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); + }; + + // ## Tokenizer + + // These are used when `options.locations` is on, for the + // `tokStartLoc` and `tokEndLoc` properties. + + function Position(line, col) { + this.line = line; + this.column = col; + } + + Position.prototype.offset = function(n) { + return new Position(this.line, this.column + n); + } + + function curPosition() { + return new Position(tokCurLine, tokPos - tokLineStart); + } + + // Reset the token state. Used at the start of a parse. + + function initTokenState(pos) { + if (pos) { + tokPos = pos; + tokLineStart = Math.max(0, input.lastIndexOf("\n", pos)); + tokCurLine = input.slice(0, tokLineStart).split(newline).length; + } else { + tokCurLine = 1; + tokPos = tokLineStart = 0; + } + tokRegexpAllowed = true; + metParenL = 0; + inType = inXJSChild = inXJSTag = false; + templates = []; + if (tokPos === 0 && options.allowHashBang && input.slice(0, 2) === '#!') { + skipLineComment(2); + } + } + + // Called at the end of every token. Sets `tokEnd`, `tokVal`, and + // `tokRegexpAllowed`, and skips the space after the token, so that + // the next one's `tokStart` will point at the right position. + + function finishToken(type, val, shouldSkipSpace) { + tokEnd = tokPos; + if (options.locations) tokEndLoc = curPosition(); + tokType = type; + if (shouldSkipSpace !== false) skipSpace(); + tokVal = val; + tokRegexpAllowed = type.beforeExpr; + if (options.onToken) { + options.onToken(new Token()); + } + } + + function skipBlockComment() { + var startLoc = options.onComment && options.locations && curPosition(); + var start = tokPos, end = input.indexOf("*/", tokPos += 2); + if (end === -1) raise(tokPos - 2, "Unterminated comment"); + tokPos = end + 2; + if (options.locations) { + lineBreak.lastIndex = start; + var match; + while ((match = lineBreak.exec(input)) && match.index < tokPos) { + ++tokCurLine; + tokLineStart = match.index + match[0].length; + } + } + if (options.onComment) + options.onComment(true, input.slice(start + 2, end), start, tokPos, + startLoc, options.locations && curPosition()); + } + + function skipLineComment(startSkip) { + var start = tokPos; + var startLoc = options.onComment && options.locations && curPosition(); + 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 + startSkip, tokPos), start, tokPos, + startLoc, options.locations && curPosition()); + } + + // Called at the start of the parse and after every token. Skips + // whitespace and comments, and. + + function skipSpace() { + while (tokPos < inputLen) { + var ch = input.charCodeAt(tokPos); + if (ch === 32) { // ' ' + ++tokPos; + } else if (ch === 13) { + ++tokPos; + var next = input.charCodeAt(tokPos); + if (next === 10) { + ++tokPos; + } + if (options.locations) { + ++tokCurLine; + tokLineStart = tokPos; + } + } else if (ch === 10 || ch === 8232 || ch === 8233) { + ++tokPos; + if (options.locations) { + ++tokCurLine; + tokLineStart = tokPos; + } + } else if (ch > 8 && ch < 14) { + ++tokPos; + } else if (ch === 47) { // '/' + var next = input.charCodeAt(tokPos + 1); + if (next === 42) { // '*' + skipBlockComment(); + } else if (next === 47) { // '/' + skipLineComment(2); + } else break; + } else if (ch === 160) { // '\xa0' + ++tokPos; + } else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { + ++tokPos; + } else { + break; + } + } + } + + // ### Token reading + + // This is the function that is called to fetch the next token. It + // is somewhat obscure, because it works in character codes rather + // than characters, and because operator parsing has been inlined + // into it. + // + // All in the name of speed. + // + // The `forceRegexp` parameter is used in the one case where the + // `tokRegexpAllowed` trick does not work. See `parseStatement`. + + function readToken_dot() { + var next = input.charCodeAt(tokPos + 1); + if (next >= 48 && next <= 57) return readNumber(true); + var next2 = input.charCodeAt(tokPos + 2); + if (options.playground && next === 63) { // 63 + tokPos += 2; + return finishToken(_dotQuestion); + } else if (options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' + tokPos += 3; + return finishToken(_ellipsis); + } else { + ++tokPos; + return finishToken(_dot); + } + } + + function readToken_slash() { // '/' + var next = input.charCodeAt(tokPos + 1); + if (tokRegexpAllowed) {++tokPos; return readRegexp();} + if (next === 61) return finishOp(_assign, 2); + return finishOp(_slash, 1); + } + + function readToken_modulo() { // '%' + var next = input.charCodeAt(tokPos + 1); + if (next === 61) return finishOp(_assign, 2); + return finishOp(_modulo, 1); + } + + function readToken_mult() { // '*' + var type = _star; + var width = 1; + var next = input.charCodeAt(tokPos + 1); + + if (options.ecmaVersion >= 7 && next === 42) { // '*' + width++; + next = input.charCodeAt(tokPos + 2); + type = _exponent; + } + + if (next === 61) { // '=' + width++; + type = _assign; + } + + return finishOp(type, width); + } + + function readToken_pipe_amp(code) { // '|&' + var next = input.charCodeAt(tokPos + 1); + if (next === code) return finishOp(code === 124 ? _logicalOR : _logicalAND, 2); + if (next === 61) return finishOp(_assign, 2); + return finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1); + } + + function readToken_caret() { // '^' + var next = input.charCodeAt(tokPos + 1); + if (next === 61) return finishOp(_assign, 2); + return finishOp(_bitwiseXOR, 1); + } + + function readToken_plus_min(code) { // '+-' + var next = input.charCodeAt(tokPos + 1); + if (next === code) { + if (next == 45 && input.charCodeAt(tokPos + 2) == 62 && + newline.test(input.slice(lastEnd, tokPos))) { + // A `-->` line comment + skipLineComment(3); + skipSpace(); + return readToken(); + } + return finishOp(_incDec, 2); + } + if (next === 61) return finishOp(_assign, 2); + return finishOp(_plusMin, 1); + } + + function readToken_lt_gt(code) { // '<>' + var next = input.charCodeAt(tokPos + 1); + var size = 1; + if (!inType && next === code) { + size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2; + if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1); + return finishOp(_bitShift, size); + } + if (next == 33 && code == 60 && input.charCodeAt(tokPos + 2) == 45 && + input.charCodeAt(tokPos + 3) == 45) { + // `` line comment - skipLineComment(3); - skipSpace(); - return readToken(); - } - return finishOp(_incDec, 2); - } - if (next === 61) return finishOp(_assign, 2); - return finishOp(_plusMin, 1); - } - - function readToken_lt_gt(code) { // '<>' - var next = input.charCodeAt(tokPos + 1); - var size = 1; - if (!inType && next === code) { - size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2; - if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1); - return finishOp(_bitShift, size); - } - if (next == 33 && code == 60 && input.charCodeAt(tokPos + 2) == 45 && - input.charCodeAt(tokPos + 3) == 45) { - // `