Merge branch 'upstream' into jsx2
Conflicts: acorn.js
This commit is contained in:
commit
c445d073e2
427
acorn.js
427
acorn.js
@ -200,9 +200,6 @@
|
||||
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];
|
||||
@ -318,7 +315,7 @@
|
||||
function initParserState() {
|
||||
lastStart = lastEnd = tokPos;
|
||||
if (options.locations) lastEndLoc = curPosition();
|
||||
inFunction = inGenerator = strict = false;
|
||||
inFunction = inGenerator = false;
|
||||
labels = [];
|
||||
skipSpace();
|
||||
readToken();
|
||||
@ -625,8 +622,9 @@
|
||||
tokPos = tokLineStart = 0;
|
||||
}
|
||||
tokType = _eof;
|
||||
tokContext = [];
|
||||
tokContext = [b_stat];
|
||||
tokExprAllowed = true;
|
||||
strict = false;
|
||||
if (tokPos === 0 && options.allowHashBang && input.slice(0, 2) === '#!') {
|
||||
skipLineComment(2);
|
||||
}
|
||||
@ -638,7 +636,7 @@
|
||||
|
||||
var b_stat = {token: "{", isExpr: false}, b_expr = {token: "{", isExpr: true}, b_tmpl = {token: "${", isExpr: true};
|
||||
var p_stat = {token: "(", isExpr: false}, p_expr = {token: "(", isExpr: true};
|
||||
var q_tmpl = {token: "`", isExpr: true};
|
||||
var q_tmpl = {token: "`", isExpr: true}, f_expr = {token: "function", isExpr: true};
|
||||
var j_oTag = {token: "<tag", isExpr: false}, j_cTag = {token: "</tag", isExpr: false}, j_expr = {token: "<tag>...</tag>", isExpr: true};
|
||||
|
||||
function curTokContext() {
|
||||
@ -677,8 +675,16 @@
|
||||
// Update context info
|
||||
if (type === _parenR || type === _braceR) {
|
||||
var out = tokContext.pop();
|
||||
tokExprAllowed = !(out && out.isExpr);
|
||||
preserveSpace = out === b_tmpl || curTokContext() === j_expr;
|
||||
if (out === b_tmpl) {
|
||||
preserveSpace = true;
|
||||
} else if (curTokContext() === j_expr) {
|
||||
preserveSpace = tokExprAllowed = true;
|
||||
} else if (out === b_stat && curTokContext() === f_expr) {
|
||||
tokContext.pop();
|
||||
tokExprAllowed = false;
|
||||
} else {
|
||||
tokExprAllowed = !(out && out.isExpr);
|
||||
}
|
||||
} else if (type === _braceL) {
|
||||
tokContext.push(braceIsBlock(prevType) ? b_stat : b_expr);
|
||||
tokExprAllowed = true;
|
||||
@ -693,7 +699,10 @@
|
||||
// tokExprAllowed stays unchanged
|
||||
} else if (type.keyword && prevType == _dot) {
|
||||
tokExprAllowed = false;
|
||||
} else if (tokExprAllowed && type == _function) {
|
||||
} else if (type == _function) {
|
||||
if (curTokContext() !== b_stat) {
|
||||
tokContext.push(f_expr);
|
||||
}
|
||||
tokExprAllowed = false;
|
||||
} else if (type === _backQuote) {
|
||||
if (curTokContext() === q_tmpl) {
|
||||
@ -1168,38 +1177,37 @@
|
||||
|
||||
function readString(quote) {
|
||||
var isJSX = curTokContext() === j_oTag;
|
||||
++tokPos;
|
||||
var out = "";
|
||||
var out = "", chunkStart = ++tokPos;
|
||||
for (;;) {
|
||||
if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant");
|
||||
var ch = input.charCodeAt(tokPos);
|
||||
if (ch === quote) {
|
||||
++tokPos;
|
||||
return finishToken(_string, out);
|
||||
}
|
||||
if (ch === quote) break;
|
||||
if (ch === 92 && !isJSX) { // '\'
|
||||
out += input.slice(chunkStart, tokPos);
|
||||
out += readEscapedChar();
|
||||
chunkStart = tokPos;
|
||||
} else if (ch === 38 && isJSX) { // '&'
|
||||
out += input.slice(chunkStart, tokPos);
|
||||
out += readJSXEntity();
|
||||
chunkStart = tokPos;
|
||||
} else {
|
||||
if (isNewLine(ch)) raise(tokStart, "Unterminated string constant");
|
||||
++tokPos;
|
||||
if (isNewLine(ch)) {
|
||||
raise(tokStart, "Unterminated string constant");
|
||||
}
|
||||
out += String.fromCharCode(ch); // '\'
|
||||
}
|
||||
}
|
||||
out += input.slice(chunkStart, tokPos++);
|
||||
return finishToken(_string, out);
|
||||
}
|
||||
|
||||
// Reads template string tokens.
|
||||
|
||||
function readTmplToken() {
|
||||
var out = "", start = tokPos;
|
||||
var out = "", chunkStart = tokPos;
|
||||
for (;;) {
|
||||
if (tokPos >= inputLen) raise(tokStart, "Unterminated template");
|
||||
var ch = input.charCodeAt(tokPos);
|
||||
if (ch === 96 || ch === 36 && input.charCodeAt(tokPos + 1) === 123) { // '`', '${'
|
||||
if (tokPos === start && tokType === _template) {
|
||||
if (tokPos === tokStart && tokType === _template) {
|
||||
if (ch === 36) {
|
||||
tokPos += 2;
|
||||
return finishToken(_dollarBraceL);
|
||||
@ -1208,23 +1216,29 @@
|
||||
return finishToken(_backQuote);
|
||||
}
|
||||
}
|
||||
out += input.slice(chunkStart, tokPos);
|
||||
return finishToken(_template, out);
|
||||
}
|
||||
if (ch === 92) { // '\'
|
||||
out += input.slice(chunkStart, tokPos);
|
||||
out += readEscapedChar();
|
||||
chunkStart = tokPos;
|
||||
} else if (isNewLine(ch)) {
|
||||
out += input.slice(chunkStart, tokPos);
|
||||
++tokPos;
|
||||
if (ch === 13 && input.charCodeAt(tokPos) === 10) {
|
||||
++tokPos;
|
||||
out += "\n";
|
||||
} else {
|
||||
out += String.fromCharCode(ch);
|
||||
}
|
||||
if (options.locations) {
|
||||
++tokCurLine;
|
||||
tokLineStart = tokPos;
|
||||
}
|
||||
chunkStart = tokPos;
|
||||
} else {
|
||||
++tokPos;
|
||||
if (isNewLine(ch)) {
|
||||
if (ch === 13 && input.charCodeAt(tokPos) === 10) {
|
||||
++tokPos;
|
||||
ch = 10;
|
||||
}
|
||||
if (options.locations) {
|
||||
++tokCurLine;
|
||||
tokLineStart = tokPos;
|
||||
}
|
||||
}
|
||||
out += String.fromCharCode(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1605,20 +1619,19 @@
|
||||
// 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.
|
||||
// Incrementally adds only escaped chars, adding other chunks as-is
|
||||
// as a micro-optimization.
|
||||
|
||||
function readWord1() {
|
||||
containsEsc = false;
|
||||
var word, first = true, start = tokPos;
|
||||
var word = "", first = true, chunkStart = 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;
|
||||
word += input.slice(chunkStart, tokPos);
|
||||
if (input.charCodeAt(++tokPos) != 117) // "u"
|
||||
raise(tokPos, "Expecting Unicode escape sequence \\uXXXX");
|
||||
++tokPos;
|
||||
@ -1628,12 +1641,13 @@
|
||||
if (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc)))
|
||||
raise(tokPos - 4, "Invalid Unicode escape");
|
||||
word += escStr;
|
||||
chunkStart = tokPos;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
return containsEsc ? word : input.slice(start, tokPos);
|
||||
return word + input.slice(chunkStart, tokPos);
|
||||
}
|
||||
|
||||
// Read an identifier or keyword token. Will check for reserved
|
||||
@ -1806,6 +1820,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Tests whether parsed token is a contextual keyword.
|
||||
|
||||
function isContextual(name) {
|
||||
return tokType === _name && tokVal === name;
|
||||
}
|
||||
|
||||
// Consumes contextual keyword if possible.
|
||||
|
||||
function eatContextual(name) {
|
||||
return tokVal === name && eat(_name);
|
||||
}
|
||||
|
||||
// Asserts that following token is given contextual keyword.
|
||||
|
||||
function expectContextual(name) {
|
||||
if (!eatContextual(name)) unexpected();
|
||||
}
|
||||
|
||||
// Test whether a semicolon can be inserted at the current position.
|
||||
|
||||
function canInsertSemicolon() {
|
||||
@ -1842,7 +1874,7 @@
|
||||
// Convert existing expression atom to assignable pattern
|
||||
// if possible.
|
||||
|
||||
function toAssignable(node, allowSpread, checkType) {
|
||||
function toAssignable(node) {
|
||||
if (options.ecmaVersion >= 6 && node) {
|
||||
switch (node.type) {
|
||||
case "Identifier":
|
||||
@ -1856,55 +1888,70 @@
|
||||
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);
|
||||
if (prop.kind !== "init") raise(prop.key.start, "Object pattern can't contain getter or setter");
|
||||
toAssignable(prop.value);
|
||||
}
|
||||
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);
|
||||
}
|
||||
toAssignableList(node.elements);
|
||||
break;
|
||||
|
||||
case "AssignmentExpression":
|
||||
if (node.operator === "=") {
|
||||
node.type = "AssignmentPattern";
|
||||
} else {
|
||||
unexpected(node.left.end);
|
||||
raise(node.left.end, "Only '=' operator can be used for specifying default value.");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (checkType) unexpected(node.start);
|
||||
raise(node.start, "Assigning to rvalue");
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
// Convert list of expression atoms to binding list.
|
||||
|
||||
function toAssignableList(exprList) {
|
||||
if (exprList.length) {
|
||||
for (var i = 0; i < exprList.length - 1; i++) {
|
||||
toAssignable(exprList[i]);
|
||||
}
|
||||
var last = exprList[exprList.length - 1];
|
||||
switch (last.type) {
|
||||
case "RestElement":
|
||||
break;
|
||||
case "SpreadElement":
|
||||
last.type = "RestElement";
|
||||
var arg = last.argument;
|
||||
toAssignable(arg);
|
||||
if (arg.type !== "Identifier" && arg.type !== "ArrayPattern")
|
||||
unexpected(arg.start);
|
||||
break;
|
||||
default:
|
||||
toAssignable(last);
|
||||
}
|
||||
}
|
||||
return exprList;
|
||||
}
|
||||
|
||||
// Parses spread element.
|
||||
|
||||
function parseSpread(isBinding) {
|
||||
var spread = startNode();
|
||||
function parseSpread(refShorthandDefaultPos) {
|
||||
var node = startNode();
|
||||
next();
|
||||
if (isBinding) {
|
||||
var arg = parseAssignableAtom();
|
||||
checkSpreadAssign(arg);
|
||||
spread.argument = arg;
|
||||
} else {
|
||||
spread.argument = parseMaybeAssign();
|
||||
}
|
||||
return finishNode(spread, "SpreadElement");
|
||||
node.argument = parseMaybeAssign(refShorthandDefaultPos);
|
||||
return finishNode(node, "SpreadElement");
|
||||
}
|
||||
|
||||
function parseRest() {
|
||||
var node = startNode();
|
||||
next();
|
||||
node.argument = tokType === _name || tokType === _bracketL ? parseAssignableAtom() : unexpected();
|
||||
return finishNode(node, "RestElement");
|
||||
}
|
||||
|
||||
// Parses lvalue (assignable) atom.
|
||||
@ -1918,16 +1965,7 @@
|
||||
case _bracketL:
|
||||
var node = startNode();
|
||||
next();
|
||||
var elts = node.elements = [], first = true;
|
||||
while (!eat(_bracketR)) {
|
||||
first ? first = false : expect(_comma);
|
||||
if (tokType === _ellipsis) {
|
||||
elts.push(parseSpread(true));
|
||||
expect(_bracketR);
|
||||
break;
|
||||
}
|
||||
elts.push(tokType === _comma ? null : parseMaybeDefault());
|
||||
}
|
||||
node.elements = parseAssignableList(_bracketR, true);
|
||||
return finishNode(node, "ArrayPattern");
|
||||
|
||||
case _braceL:
|
||||
@ -1938,6 +1976,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
function parseAssignableList(close, allowEmpty) {
|
||||
var elts = [], first = true;
|
||||
while (!eat(close)) {
|
||||
first ? first = false : expect(_comma);
|
||||
if (tokType === _ellipsis) {
|
||||
elts.push(parseRest());
|
||||
expect(close);
|
||||
break;
|
||||
}
|
||||
elts.push(allowEmpty && tokType === _comma ? null : parseMaybeDefault());
|
||||
}
|
||||
return elts;
|
||||
}
|
||||
|
||||
// Parses assignment pattern around given atom if possible.
|
||||
|
||||
function parseMaybeDefault(startPos, left) {
|
||||
@ -1950,13 +2002,6 @@
|
||||
return finishNode(node, "AssignmentPattern");
|
||||
}
|
||||
|
||||
// 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`.
|
||||
|
||||
@ -1981,6 +2026,9 @@
|
||||
if (elem) checkFunctionParam(elem, nameHash);
|
||||
}
|
||||
break;
|
||||
|
||||
case "RestElement":
|
||||
return checkFunctionParam(param.argument, nameHash);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2040,7 +2088,11 @@
|
||||
break;
|
||||
|
||||
case "AssignmentPattern":
|
||||
case "SpreadElement":
|
||||
checkLVal(expr.left);
|
||||
break;
|
||||
|
||||
case "RestElement":
|
||||
checkLVal(expr.argument);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -2187,15 +2239,19 @@
|
||||
next();
|
||||
parseVar(init, true, varKind);
|
||||
finishNode(init, "VariableDeclaration");
|
||||
if ((tokType === _in || (options.ecmaVersion >= 6 && tokType === _name && tokVal === "of")) && init.declarations.length === 1 &&
|
||||
if ((tokType === _in || (options.ecmaVersion >= 6 && isContextual("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 || (options.ecmaVersion >= 6 && tokType === _name && tokVal === "of")) {
|
||||
var refShorthandDefaultPos = {start: 0};
|
||||
var init = parseExpression(true, refShorthandDefaultPos);
|
||||
if (tokType === _in || (options.ecmaVersion >= 6 && isContextual("of"))) {
|
||||
toAssignable(init);
|
||||
checkLVal(init);
|
||||
return parseForIn(node, init);
|
||||
} else if (refShorthandDefaultPos.start) {
|
||||
unexpected(refShorthandDefaultPos.start);
|
||||
}
|
||||
return parseFor(node, init);
|
||||
}
|
||||
@ -2409,7 +2465,7 @@
|
||||
var decl = startNode();
|
||||
decl.id = parseAssignableAtom();
|
||||
checkLVal(decl.id, true);
|
||||
decl.init = eat(_eq) ? parseExpression(true, noIn) : (kind === _const.keyword ? unexpected() : null);
|
||||
decl.init = eat(_eq) ? parseMaybeAssign(noIn) : (kind === _const.keyword ? unexpected() : null);
|
||||
node.declarations.push(finishNode(decl, "VariableDeclarator"));
|
||||
if (!eat(_comma)) break;
|
||||
}
|
||||
@ -2424,17 +2480,20 @@
|
||||
// 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).
|
||||
// Parse a full expression. The optional arguments are used to
|
||||
// forbid the `in` operator (in for loops initalization expressions)
|
||||
// and provide reference for storing '=' operator inside shorthand
|
||||
// property assignment in contexts where both object expression
|
||||
// and object pattern might appear (so it's possible to raise
|
||||
// delayed syntax error at correct position).
|
||||
|
||||
function parseExpression(noComma, noIn) {
|
||||
function parseExpression(noIn, refShorthandDefaultPos) {
|
||||
var start = storeCurrentPos();
|
||||
var expr = parseMaybeAssign(noIn);
|
||||
if (!noComma && tokType === _comma) {
|
||||
var expr = parseMaybeAssign(noIn, refShorthandDefaultPos);
|
||||
if (tokType === _comma) {
|
||||
var node = startNodeAt(start);
|
||||
node.expressions = [expr];
|
||||
while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn));
|
||||
while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn, refShorthandDefaultPos));
|
||||
return finishNode(node, "SequenceExpression");
|
||||
}
|
||||
return expr;
|
||||
@ -2443,32 +2502,43 @@
|
||||
// Parse an assignment expression. This includes applications of
|
||||
// operators like `+=`.
|
||||
|
||||
function parseMaybeAssign(noIn) {
|
||||
function parseMaybeAssign(noIn, refShorthandDefaultPos) {
|
||||
var failOnShorthandAssign;
|
||||
if (!refShorthandDefaultPos) {
|
||||
refShorthandDefaultPos = {start: 0};
|
||||
failOnShorthandAssign = true;
|
||||
} else {
|
||||
failOnShorthandAssign = false;
|
||||
}
|
||||
var start = storeCurrentPos();
|
||||
var left = parseMaybeConditional(noIn);
|
||||
var left = parseMaybeConditional(noIn, refShorthandDefaultPos);
|
||||
if (tokType.isAssign) {
|
||||
var node = startNodeAt(start);
|
||||
node.operator = tokVal;
|
||||
node.left = tokType === _eq ? toAssignable(left) : left;
|
||||
refShorthandDefaultPos.start = 0; // reset because shorthand default was used correctly
|
||||
checkLVal(left);
|
||||
next();
|
||||
node.right = parseMaybeAssign(noIn);
|
||||
return finishNode(node, "AssignmentExpression");
|
||||
} else if (failOnShorthandAssign && refShorthandDefaultPos.start) {
|
||||
unexpected(refShorthandDefaultPos.start);
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
// Parse a ternary conditional (`?:`) operator.
|
||||
|
||||
function parseMaybeConditional(noIn) {
|
||||
function parseMaybeConditional(noIn, refShorthandDefaultPos) {
|
||||
var start = storeCurrentPos();
|
||||
var expr = parseExprOps(noIn);
|
||||
var expr = parseExprOps(noIn, refShorthandDefaultPos);
|
||||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
|
||||
if (eat(_question)) {
|
||||
var node = startNodeAt(start);
|
||||
node.test = expr;
|
||||
node.consequent = parseExpression(true);
|
||||
node.consequent = parseMaybeAssign();
|
||||
expect(_colon);
|
||||
node.alternate = parseExpression(true, noIn);
|
||||
node.alternate = parseMaybeAssign(noIn);
|
||||
return finishNode(node, "ConditionalExpression");
|
||||
}
|
||||
return expr;
|
||||
@ -2476,9 +2546,11 @@
|
||||
|
||||
// Start the precedence parser.
|
||||
|
||||
function parseExprOps(noIn) {
|
||||
function parseExprOps(noIn, refShorthandDefaultPos) {
|
||||
var start = storeCurrentPos();
|
||||
return parseExprOp(parseMaybeUnary(), start, -1, noIn);
|
||||
var expr = parseMaybeUnary(refShorthandDefaultPos);
|
||||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
|
||||
return parseExprOp(expr, start, -1, noIn);
|
||||
}
|
||||
|
||||
// Parse binary operators with the operator precedence parsing
|
||||
@ -2507,13 +2579,14 @@
|
||||
|
||||
// Parse unary operators, both prefix and postfix.
|
||||
|
||||
function parseMaybeUnary() {
|
||||
function parseMaybeUnary(refShorthandDefaultPos) {
|
||||
if (tokType.prefix) {
|
||||
var node = startNode(), update = tokType.isUpdate;
|
||||
node.operator = tokVal;
|
||||
node.prefix = true;
|
||||
next();
|
||||
node.argument = parseMaybeUnary();
|
||||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) unexpected(refShorthandDefaultPos.start);
|
||||
if (update) checkLVal(node.argument);
|
||||
else if (strict && node.operator === "delete" &&
|
||||
node.argument.type === "Identifier")
|
||||
@ -2521,7 +2594,8 @@
|
||||
return finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
|
||||
}
|
||||
var start = storeCurrentPos();
|
||||
var expr = parseExprSubscripts();
|
||||
var expr = parseExprSubscripts(refShorthandDefaultPos);
|
||||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
|
||||
while (tokType.postfix && !canInsertSemicolon()) {
|
||||
var node = startNodeAt(start);
|
||||
node.operator = tokVal;
|
||||
@ -2536,9 +2610,11 @@
|
||||
|
||||
// Parse call, dot, and `[]`-subscript expressions.
|
||||
|
||||
function parseExprSubscripts() {
|
||||
function parseExprSubscripts(refShorthandDefaultPos) {
|
||||
var start = storeCurrentPos();
|
||||
return parseSubscripts(parseExprAtom(), start);
|
||||
var expr = parseExprAtom(refShorthandDefaultPos);
|
||||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr;
|
||||
return parseSubscripts(expr, start);
|
||||
}
|
||||
|
||||
function parseSubscripts(base, start, noCalls) {
|
||||
@ -2573,7 +2649,7 @@
|
||||
// `new`, or an expression wrapped in punctuation like `()`, `[]`,
|
||||
// or `{}`.
|
||||
|
||||
function parseExprAtom() {
|
||||
function parseExprAtom(refShorthandDefaultPos) {
|
||||
switch (tokType) {
|
||||
case _this:
|
||||
var node = startNode();
|
||||
@ -2623,11 +2699,11 @@
|
||||
if (options.ecmaVersion >= 7 && tokType === _for) {
|
||||
return parseComprehension(node, false);
|
||||
}
|
||||
node.elements = parseExprList(_bracketR, true, true);
|
||||
node.elements = parseExprList(_bracketR, true, true, refShorthandDefaultPos);
|
||||
return finishNode(node, "ArrayExpression");
|
||||
|
||||
case _braceL:
|
||||
return parseObj();
|
||||
return parseObj(false, refShorthandDefaultPos);
|
||||
|
||||
case _function:
|
||||
var node = startNode();
|
||||
@ -2660,18 +2736,19 @@
|
||||
return parseComprehension(startNodeAt(start), true);
|
||||
}
|
||||
|
||||
var innerStart = storeCurrentPos(), exprList = [], first = true, spreadStart, innerParenStart;
|
||||
var innerStart = storeCurrentPos(), exprList = [], first = true;
|
||||
var refShorthandDefaultPos = {start: 0}, spreadStart, innerParenStart;
|
||||
while (tokType !== _parenR) {
|
||||
first ? first = false : expect(_comma);
|
||||
if (tokType === _ellipsis) {
|
||||
spreadStart = tokStart;
|
||||
exprList.push(parseSpread(true));
|
||||
exprList.push(parseRest());
|
||||
break;
|
||||
} else {
|
||||
if (tokType === _parenL && !innerParenStart) {
|
||||
innerParenStart = tokStart;
|
||||
}
|
||||
exprList.push(parseMaybeAssign());
|
||||
exprList.push(parseMaybeAssign(false, refShorthandDefaultPos));
|
||||
}
|
||||
}
|
||||
var innerEnd = storeCurrentPos();
|
||||
@ -2684,6 +2761,7 @@
|
||||
|
||||
if (!exprList.length) unexpected(lastStart);
|
||||
if (spreadStart) unexpected(spreadStart);
|
||||
if (refShorthandDefaultPos.start) unexpected(refShorthandDefaultPos.start);
|
||||
|
||||
if (exprList.length > 1) {
|
||||
val = startNodeAt(innerStart);
|
||||
@ -2750,7 +2828,7 @@
|
||||
|
||||
// Parse an object literal or binding pattern.
|
||||
|
||||
function parseObj(isPattern) {
|
||||
function parseObj(isPattern, refShorthandDefaultPos) {
|
||||
var node = startNode(), first = true, propHash = {};
|
||||
node.properties = [];
|
||||
next();
|
||||
@ -2772,7 +2850,7 @@
|
||||
}
|
||||
parsePropertyName(prop);
|
||||
if (eat(_colon)) {
|
||||
prop.value = isPattern ? parseMaybeDefault(start) : parseMaybeAssign();
|
||||
prop.value = isPattern ? parseMaybeDefault(start) : parseMaybeAssign(false, refShorthandDefaultPos);
|
||||
prop.kind = "init";
|
||||
} else if (options.ecmaVersion >= 6 && tokType === _parenL) {
|
||||
if (isPattern) unexpected();
|
||||
@ -2788,7 +2866,15 @@
|
||||
prop.value = parseMethod(false);
|
||||
} else if (options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
|
||||
prop.kind = "init";
|
||||
prop.value = isPattern ? parseMaybeDefault(start, prop.key) : prop.key;
|
||||
if (isPattern) {
|
||||
prop.value = parseMaybeDefault(start, prop.key);
|
||||
} else if (tokType === _eq && refShorthandDefaultPos) {
|
||||
if (!refShorthandDefaultPos.start)
|
||||
refShorthandDefaultPos.start = tokStart;
|
||||
prop.value = parseMaybeDefault(start, prop.key);
|
||||
} else {
|
||||
prop.value = prop.key;
|
||||
}
|
||||
prop.shorthand = true;
|
||||
} else unexpected();
|
||||
|
||||
@ -2816,11 +2902,9 @@
|
||||
|
||||
function initFunction(node) {
|
||||
node.id = null;
|
||||
node.params = [];
|
||||
if (options.ecmaVersion >= 6) {
|
||||
node.defaults = [];
|
||||
node.rest = null;
|
||||
node.generator = false;
|
||||
node.expression = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2835,7 +2919,8 @@
|
||||
if (isStatement || tokType === _name) {
|
||||
node.id = parseIdent();
|
||||
}
|
||||
parseFunctionParams(node);
|
||||
expect(_parenL);
|
||||
node.params = parseAssignableList(_parenR, false);
|
||||
parseFunctionBody(node, allowExpressionBody);
|
||||
return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
|
||||
}
|
||||
@ -2845,7 +2930,8 @@
|
||||
function parseMethod(isGenerator) {
|
||||
var node = startNode();
|
||||
initFunction(node);
|
||||
parseFunctionParams(node);
|
||||
expect(_parenL);
|
||||
node.params = parseAssignableList(_parenR, false);
|
||||
var allowExpressionBody;
|
||||
if (options.ecmaVersion >= 6) {
|
||||
node.generator = isGenerator;
|
||||
@ -2861,76 +2947,18 @@
|
||||
|
||||
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 = [];
|
||||
|
||||
node.params = toAssignableList(params, true);
|
||||
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 (eat(_ellipsis)) {
|
||||
node.rest = parseAssignableAtom();
|
||||
checkSpreadAssign(node.rest);
|
||||
expect(_parenR);
|
||||
defaults.push(null);
|
||||
break;
|
||||
} else {
|
||||
node.params.push(parseAssignableAtom());
|
||||
if (options.ecmaVersion >= 6) {
|
||||
if (eat(_eq)) {
|
||||
hasDefaults = true;
|
||||
defaults.push(parseExpression(true));
|
||||
} else {
|
||||
defaults.push(null);
|
||||
}
|
||||
}
|
||||
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.body = parseMaybeAssign();
|
||||
node.expression = true;
|
||||
} else {
|
||||
// Start a new scope with regard to labels and the `inFunction`
|
||||
@ -2951,8 +2979,6 @@
|
||||
checkFunctionParam(node.id, {});
|
||||
for (var i = 0; i < node.params.length; i++)
|
||||
checkFunctionParam(node.params[i], nameHash);
|
||||
if (node.rest)
|
||||
checkFunctionParam(node.rest, nameHash);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3001,7 +3027,7 @@
|
||||
// nothing in between them to be parsed as `null` (which is needed
|
||||
// for array literals).
|
||||
|
||||
function parseExprList(close, allowTrailingComma, allowEmpty) {
|
||||
function parseExprList(close, allowTrailingComma, allowEmpty, refShorthandDefaultPos) {
|
||||
var elts = [], first = true;
|
||||
while (!eat(close)) {
|
||||
if (!first) {
|
||||
@ -3012,7 +3038,10 @@
|
||||
if (allowEmpty && tokType === _comma) {
|
||||
elts.push(null);
|
||||
} else {
|
||||
elts.push(tokType === _ellipsis ? parseSpread() : parseMaybeAssign());
|
||||
if (tokType === _ellipsis)
|
||||
elts.push(parseSpread(refShorthandDefaultPos));
|
||||
else
|
||||
elts.push(parseMaybeAssign(false, refShorthandDefaultPos));
|
||||
}
|
||||
}
|
||||
return elts;
|
||||
@ -3055,7 +3084,7 @@
|
||||
} else
|
||||
// export default ...;
|
||||
if (eat(_default)) {
|
||||
node.declaration = parseExpression(true);
|
||||
node.declaration = parseMaybeAssign();
|
||||
node['default'] = true;
|
||||
node.specifiers = null;
|
||||
node.source = null;
|
||||
@ -3067,8 +3096,7 @@
|
||||
node.declaration = null;
|
||||
node['default'] = false;
|
||||
node.specifiers = parseExportSpecifiers();
|
||||
if (tokType === _name && tokVal === "from") {
|
||||
next();
|
||||
if (eatContextual("from")) {
|
||||
node.source = tokType === _string ? parseExprAtom() : unexpected();
|
||||
} else {
|
||||
if (isBatch) unexpected();
|
||||
@ -3099,12 +3127,7 @@
|
||||
|
||||
var node = startNode();
|
||||
node.id = parseIdent(tokType === _default);
|
||||
if (tokType === _name && tokVal === "as") {
|
||||
next();
|
||||
node.name = parseIdent(true);
|
||||
} else {
|
||||
node.name = null;
|
||||
}
|
||||
node.name = eatContextual("as") ? parseIdent(true) : null;
|
||||
nodes.push(finishNode(node, "ExportSpecifier"));
|
||||
}
|
||||
}
|
||||
@ -3122,8 +3145,7 @@
|
||||
node.kind = "";
|
||||
} else {
|
||||
node.specifiers = parseImportSpecifiers();
|
||||
if (tokType !== _name || tokVal !== "from") unexpected();
|
||||
next();
|
||||
expectContextual("from");
|
||||
node.source = tokType === _string ? parseExprAtom() : unexpected();
|
||||
}
|
||||
semicolon();
|
||||
@ -3147,8 +3169,7 @@
|
||||
if (tokType === _star) {
|
||||
var node = startNode();
|
||||
next();
|
||||
if (tokType !== _name || tokVal !== "as") unexpected();
|
||||
next();
|
||||
expectContextual("as");
|
||||
node.name = parseIdent();
|
||||
checkLVal(node.name, true);
|
||||
nodes.push(finishNode(node, "ImportBatchSpecifier"));
|
||||
@ -3163,12 +3184,7 @@
|
||||
|
||||
var node = startNode();
|
||||
node.id = parseIdent(true);
|
||||
if (tokType === _name && tokVal === "as") {
|
||||
next();
|
||||
node.name = parseIdent();
|
||||
} else {
|
||||
node.name = null;
|
||||
}
|
||||
node.name = eatContextual("as") ? parseIdent() : null;
|
||||
checkLVal(node.name || node.id, true);
|
||||
node['default'] = false;
|
||||
nodes.push(finishNode(node, "ImportSpecifier"));
|
||||
@ -3186,7 +3202,7 @@
|
||||
node.argument = null;
|
||||
} else {
|
||||
node.delegate = eat(_star);
|
||||
node.argument = parseExpression(true);
|
||||
node.argument = parseMaybeAssign();
|
||||
}
|
||||
return finishNode(node, "YieldExpression");
|
||||
}
|
||||
@ -3201,8 +3217,7 @@
|
||||
expect(_parenL);
|
||||
block.left = parseAssignableAtom();
|
||||
checkLVal(block.left, true);
|
||||
if (tokType !== _name || tokVal !== "of") unexpected();
|
||||
next();
|
||||
expectContextual("of");
|
||||
block.right = parseExpression();
|
||||
expect(_parenR);
|
||||
node.blocks.push(finishNode(block, "ComprehensionBlock"));
|
||||
|
||||
147
acorn_loose.js
147
acorn_loose.js
@ -58,14 +58,12 @@
|
||||
var lastEnd, token = {start: 0, end: 0}, ahead = [];
|
||||
var curLineStart, nextLineStart, curIndent, lastEndLoc, sourceFile;
|
||||
|
||||
function next(forceRegexp) {
|
||||
function next() {
|
||||
lastEnd = token.end;
|
||||
if (options.locations)
|
||||
lastEndLoc = token.endLoc;
|
||||
if (forceRegexp)
|
||||
ahead.length = 0;
|
||||
lastEndLoc = token.loc && token.loc.end;
|
||||
|
||||
token = ahead.shift() || readToken(forceRegexp);
|
||||
token = ahead.shift() || readToken();
|
||||
if (options.onToken)
|
||||
options.onToken(token);
|
||||
|
||||
@ -78,10 +76,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
function readToken(forceRegexp) {
|
||||
function readToken() {
|
||||
for (;;) {
|
||||
try {
|
||||
var tok = fetchToken(forceRegexp);
|
||||
var tok = fetchToken();
|
||||
if (tok.type === tt.dot && input.substr(tok.end, 1) === '.') {
|
||||
tok = fetchToken();
|
||||
tok.start--;
|
||||
@ -129,8 +127,8 @@
|
||||
if (replace === true) replace = {start: pos, end: pos, type: tt.name, value: "✖"};
|
||||
if (replace) {
|
||||
if (options.locations) {
|
||||
replace.startLoc = acorn.getLineInfo(input, replace.start);
|
||||
replace.endLoc = acorn.getLineInfo(input, replace.end);
|
||||
replace.loc = new SourceLocation(acorn.getLineInfo(input, replace.start));
|
||||
replace.loc.end = acorn.getLineInfo(input, replace.end);
|
||||
}
|
||||
return replace;
|
||||
}
|
||||
@ -212,7 +210,7 @@
|
||||
Node.prototype = acorn.Node.prototype;
|
||||
|
||||
function SourceLocation(start) {
|
||||
this.start = start || token.startLoc || {line: 1, column: 0};
|
||||
this.start = start || token.loc.start || {line: 1, column: 0};
|
||||
this.end = null;
|
||||
if (sourceFile !== null) this.source = sourceFile;
|
||||
}
|
||||
@ -229,7 +227,7 @@
|
||||
}
|
||||
|
||||
function storeCurrentPos() {
|
||||
return options.locations ? [token.start, token.startLoc] : token.start;
|
||||
return options.locations ? [token.start, token.loc.start] : token.start;
|
||||
}
|
||||
|
||||
function startNodeAt(pos) {
|
||||
@ -273,9 +271,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
function isContextual(name) {
|
||||
return token.type === tt.name && token.value === name;
|
||||
}
|
||||
|
||||
function eatContextual(name) {
|
||||
return token.value === name && eat(tt.name);
|
||||
}
|
||||
|
||||
function canInsertSemicolon() {
|
||||
return (token.type === tt.eof || token.type === tt.braceR || newline.test(input.slice(lastEnd, token.start)));
|
||||
}
|
||||
|
||||
function semicolon() {
|
||||
return eat(tt.semi);
|
||||
}
|
||||
@ -299,7 +306,7 @@
|
||||
case "MemberExpression":
|
||||
case "ObjectPattern":
|
||||
case "ArrayPattern":
|
||||
case "SpreadElement":
|
||||
case "RestElement":
|
||||
case "AssignmentPattern":
|
||||
return expr;
|
||||
|
||||
@ -313,14 +320,11 @@
|
||||
node.body = [];
|
||||
while (token.type !== tt.eof) node.body.push(parseStatement());
|
||||
lastEnd = token.end;
|
||||
lastEndLoc = token.endLoc;
|
||||
lastEndLoc = token.loc && token.loc.end;
|
||||
return finishNode(node, "Program");
|
||||
}
|
||||
|
||||
function parseStatement() {
|
||||
if (token.type === tt.slash || token.type === tt.assign && token.value === "/=")
|
||||
next(true);
|
||||
|
||||
var starttype = token.type, node = startNode();
|
||||
|
||||
switch (starttype) {
|
||||
@ -354,13 +358,13 @@
|
||||
if (token.type === tt.semi) return parseFor(node, null);
|
||||
if (token.type === tt._var || token.type === tt._let) {
|
||||
var init = parseVar(true);
|
||||
if (init.declarations.length === 1 && (token.type === tt._in || token.type === tt.name && token.value === "of")) {
|
||||
if (init.declarations.length === 1 && (token.type === tt._in || isContextual("of"))) {
|
||||
return parseForIn(node, init);
|
||||
}
|
||||
return parseFor(node, init);
|
||||
}
|
||||
var init = parseExpression(false, true);
|
||||
if (token.type === tt._in || token.type === tt.name && token.value === "of") {
|
||||
var init = parseExpression(true);
|
||||
if (token.type === tt._in || isContextual("of")) {
|
||||
return parseForIn(node, checkLVal(init));
|
||||
}
|
||||
return parseFor(node, init);
|
||||
@ -532,7 +536,7 @@
|
||||
do {
|
||||
var decl = startNode();
|
||||
decl.id = options.ecmaVersion >= 6 ? toAssignable(parseExprAtom()) : parseIdent();
|
||||
decl.init = eat(tt.eq) ? parseExpression(true, noIn) : null;
|
||||
decl.init = eat(tt.eq) ? parseMaybeAssign(noIn) : null;
|
||||
node.declarations.push(finishNode(decl, "VariableDeclarator"));
|
||||
} while (eat(tt.comma));
|
||||
if (!node.declarations.length) {
|
||||
@ -544,10 +548,10 @@
|
||||
return finishNode(node, "VariableDeclaration");
|
||||
}
|
||||
|
||||
function parseExpression(noComma, noIn) {
|
||||
function parseExpression(noIn) {
|
||||
var start = storeCurrentPos();
|
||||
var expr = parseMaybeAssign(noIn);
|
||||
if (!noComma && token.type === tt.comma) {
|
||||
if (token.type === tt.comma) {
|
||||
var node = startNodeAt(start);
|
||||
node.expressions = [expr];
|
||||
while (eat(tt.comma)) node.expressions.push(parseMaybeAssign(noIn));
|
||||
@ -585,8 +589,8 @@
|
||||
if (eat(tt.question)) {
|
||||
var node = startNodeAt(start);
|
||||
node.test = expr;
|
||||
node.consequent = parseExpression(true);
|
||||
node.alternate = expect(tt.colon) ? parseExpression(true, noIn) : dummyIdent();
|
||||
node.consequent = parseMaybeAssign();
|
||||
node.alternate = expect(tt.colon) ? parseMaybeAssign(noIn) : dummyIdent();
|
||||
return finishNode(node, "ConditionalExpression");
|
||||
}
|
||||
return expr;
|
||||
@ -776,7 +780,7 @@
|
||||
node.argument = null;
|
||||
} else {
|
||||
node.delegate = eat(tt.star);
|
||||
node.argument = parseExpression(true);
|
||||
node.argument = parseMaybeAssign();
|
||||
}
|
||||
return finishNode(node, "YieldExpression");
|
||||
|
||||
@ -864,7 +868,7 @@
|
||||
isGenerator = eat(tt.star);
|
||||
}
|
||||
parsePropertyName(prop);
|
||||
if (isDummy(prop.key)) { if (isDummy(parseExpression(true))) next(); eat(tt.comma); continue; }
|
||||
if (isDummy(prop.key)) { if (isDummy(parseMaybeAssign())) next(); eat(tt.comma); continue; }
|
||||
if (isClass) {
|
||||
if (prop.key.type === "Identifier" && !prop.computed && prop.key.name === "static" &&
|
||||
(token.type != tt.parenL && token.type != tt.braceL)) {
|
||||
@ -877,7 +881,7 @@
|
||||
}
|
||||
if (!isClass && eat(tt.colon)) {
|
||||
prop.kind = "init";
|
||||
prop.value = parseExpression(true);
|
||||
prop.value = parseMaybeAssign();
|
||||
} else if (options.ecmaVersion >= 6 && (token.type === tt.parenL || token.type === tt.braceL)) {
|
||||
if (isClass) {
|
||||
prop.kind = "";
|
||||
@ -913,7 +917,7 @@
|
||||
// If there is no closing brace, make the node span to the start
|
||||
// of the next token (this is useful for Tern)
|
||||
lastEnd = token.start;
|
||||
if (options.locations) lastEndLoc = token.startLoc;
|
||||
if (options.locations) lastEndLoc = token.loc.start;
|
||||
}
|
||||
if (isClass) {
|
||||
semicolon();
|
||||
@ -954,8 +958,6 @@
|
||||
node.id = null;
|
||||
node.params = [];
|
||||
if (options.ecmaVersion >= 6) {
|
||||
node.defaults = [];
|
||||
node.rest = null;
|
||||
node.generator = false;
|
||||
node.expression = false;
|
||||
}
|
||||
@ -971,19 +973,17 @@
|
||||
node.type = "ObjectPattern";
|
||||
var props = node.properties;
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
props[i].value = toAssignable(props[i].value);
|
||||
toAssignable(props[i].value);
|
||||
}
|
||||
break;
|
||||
|
||||
case "ArrayExpression":
|
||||
node.type = "ArrayPattern";
|
||||
var elms = node.elements;
|
||||
for (var i = 0; i < elms.length; i++) {
|
||||
elms[i] = toAssignable(elms[i]);
|
||||
}
|
||||
toAssignableList(node.elements);
|
||||
break;
|
||||
|
||||
case "SpreadElement":
|
||||
node.type = "RestElement";
|
||||
node.argument = toAssignable(node.argument);
|
||||
break;
|
||||
|
||||
@ -995,33 +995,17 @@
|
||||
return checkLVal(node);
|
||||
}
|
||||
|
||||
function parseFunctionParams(node, params) {
|
||||
var defaults = [], hasDefaults = false;
|
||||
|
||||
if (!params) {
|
||||
pushCx();
|
||||
params = parseExprList(tt.parenR);
|
||||
}
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var param = params[i], defValue = null;
|
||||
if (param.type === "AssignmentExpression") {
|
||||
defValue = param.right;
|
||||
param = param.left;
|
||||
}
|
||||
param = toAssignable(param);
|
||||
if (param.type === "SpreadElement") {
|
||||
param = param.argument;
|
||||
if (i === params.length - 1) {
|
||||
node.rest = param;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
node.params.push(param);
|
||||
defaults.push(defValue);
|
||||
if (defValue) hasDefaults = true;
|
||||
function toAssignableList(exprList) {
|
||||
for (var i = 0; i < exprList.length; i++) {
|
||||
toAssignable(exprList[i]);
|
||||
}
|
||||
return exprList;
|
||||
}
|
||||
|
||||
if (hasDefaults) node.defaults = defaults;
|
||||
function parseFunctionParams(params) {
|
||||
pushCx();
|
||||
params = parseExprList(tt.parenR);
|
||||
return toAssignableList(params);
|
||||
}
|
||||
|
||||
function parseFunction(node, isStatement) {
|
||||
@ -1031,7 +1015,7 @@
|
||||
}
|
||||
if (token.type === tt.name) node.id = parseIdent();
|
||||
else if (isStatement) node.id = dummyIdent();
|
||||
parseFunctionParams(node);
|
||||
node.params = parseFunctionParams();
|
||||
node.body = parseBlock();
|
||||
return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
|
||||
}
|
||||
@ -1039,18 +1023,18 @@
|
||||
function parseMethod(isGenerator) {
|
||||
var node = startNode();
|
||||
initFunction(node);
|
||||
parseFunctionParams(node);
|
||||
node.params = parseFunctionParams();
|
||||
node.generator = isGenerator || false;
|
||||
node.expression = options.ecmaVersion >= 6 && token.type !== tt.braceL;
|
||||
node.body = node.expression ? parseExpression(true) : parseBlock();
|
||||
node.body = node.expression ? parseMaybeAssign() : parseBlock();
|
||||
return finishNode(node, "FunctionExpression");
|
||||
}
|
||||
|
||||
function parseArrowExpression(node, params) {
|
||||
initFunction(node);
|
||||
parseFunctionParams(node, params);
|
||||
node.params = toAssignableList(params);
|
||||
node.expression = token.type !== tt.braceL;
|
||||
node.body = node.expression ? parseExpression(true) : parseBlock();
|
||||
node.body = node.expression ? parseMaybeAssign() : parseBlock();
|
||||
return finishNode(node, "ArrowFunctionExpression");
|
||||
}
|
||||
|
||||
@ -1102,10 +1086,7 @@
|
||||
if (token.type === tt.star) {
|
||||
var elt = startNode();
|
||||
next();
|
||||
if (token.type === tt.name && token.value === "as") {
|
||||
next();
|
||||
elt.name = parseIdent();
|
||||
}
|
||||
if (eatContextual("as")) elt.name = parseIdent();
|
||||
elts.push(finishNode(elt, prefix + "BatchSpecifier"));
|
||||
} else {
|
||||
var indent = curIndent, line = curLineStart, continuedLine = nextLineStart;
|
||||
@ -1114,22 +1095,13 @@
|
||||
if (curLineStart > continuedLine) continuedLine = curLineStart;
|
||||
while (!closes(tt.braceR, indent + (curLineStart <= continuedLine ? 1 : 0), line)) {
|
||||
var elt = startNode();
|
||||
if (token.type === tt.star) {
|
||||
next();
|
||||
if (token.type === tt.name && token.value === "as") {
|
||||
next();
|
||||
elt.name = parseIdent();
|
||||
}
|
||||
if (eat(tt.star)) {
|
||||
if (eatContextual("as")) elt.name = parseIdent();
|
||||
finishNode(elt, prefix + "BatchSpecifier");
|
||||
} else {
|
||||
if (token.type === tt.name && token.value === "from") break;
|
||||
if (isContextual("from")) break;
|
||||
elt.id = parseIdent();
|
||||
if (token.type === tt.name && token.value === "as") {
|
||||
next();
|
||||
elt.name = parseIdent();
|
||||
} else {
|
||||
elt.name = null;
|
||||
}
|
||||
elt.name = eatContextual("as") ? parseIdent() : null;
|
||||
finishNode(elt, prefix + "Specifier");
|
||||
}
|
||||
elts.push(elt);
|
||||
@ -1138,12 +1110,7 @@
|
||||
eat(tt.braceR);
|
||||
popCx();
|
||||
}
|
||||
if (token.type === tt.name && token.value === "from") {
|
||||
next();
|
||||
node.source = parseExprAtom();
|
||||
} else {
|
||||
node.source = null;
|
||||
}
|
||||
node.source = eatContextual("from") ? parseExprAtom() : null;
|
||||
}
|
||||
|
||||
function parseExprList(close, allowEmpty) {
|
||||
@ -1154,7 +1121,7 @@
|
||||
elts.push(allowEmpty ? null : dummyIdent());
|
||||
continue;
|
||||
}
|
||||
var elt = parseExpression(true);
|
||||
var elt = parseMaybeAssign();
|
||||
if (isDummy(elt)) {
|
||||
if (closes(close, indent, line)) break;
|
||||
next();
|
||||
@ -1168,7 +1135,7 @@
|
||||
// If there is no closing brace, make the node span to the start
|
||||
// of the next token (this is useful for Tern)
|
||||
lastEnd = token.start;
|
||||
if (options.locations) lastEndLoc = token.startLoc;
|
||||
if (options.locations) lastEndLoc = token.loc.start;
|
||||
}
|
||||
return elts;
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
function ppJSON(v) { return JSON.stringify(v, null, 2); }
|
||||
function ppJSON(v) { return v instanceof RegExp ? v.toString() : JSON.stringify(v, null, 2); }
|
||||
function addPath(str, pt) {
|
||||
if (str.charAt(str.length-1) == ")")
|
||||
return str.slice(0, str.length-1) + "/" + pt + ")";
|
||||
@ -76,6 +76,9 @@
|
||||
var misMatch = exports.misMatch = function(exp, act) {
|
||||
if (!exp || !act || (typeof exp != "object") || (typeof act != "object")) {
|
||||
if (exp !== act) return ppJSON(exp) + " !== " + ppJSON(act);
|
||||
} else if (exp instanceof RegExp || act instanceof RegExp) {
|
||||
var left = ppJSON(exp), right = ppJSON(act);
|
||||
if (left !== right) return left + " !== " + right;
|
||||
} else if (exp.splice) {
|
||||
if (!act.slice) return ppJSON(exp) + " != " + ppJSON(act);
|
||||
if (act.length != exp.length) return "array length mismatch " + exp.length + " != " + act.length;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
148
test/tests.js
148
test/tests.js
@ -169,7 +169,7 @@ test("/[a-z]/g", {
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "Literal",
|
||||
value: /[a-z]/,
|
||||
value: /[a-z]/g,
|
||||
regex: {
|
||||
pattern: "[a-z]",
|
||||
flags: "g"
|
||||
@ -7331,7 +7331,7 @@ test("var x = /[a-z]/i", {
|
||||
},
|
||||
init: {
|
||||
type: "Literal",
|
||||
value: {},
|
||||
value: /[a-z]/i,
|
||||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
@ -7404,7 +7404,7 @@ test("var x = /[x-z]/i", {
|
||||
},
|
||||
init: {
|
||||
type: "Literal",
|
||||
value: {},
|
||||
value: /[x-z]/i,
|
||||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
@ -7477,7 +7477,7 @@ test("var x = /[a-c]/i", {
|
||||
},
|
||||
init: {
|
||||
type: "Literal",
|
||||
value: {},
|
||||
value: /[a-c]/i,
|
||||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
@ -7550,7 +7550,7 @@ test("var x = /[P QR]/i", {
|
||||
},
|
||||
init: {
|
||||
type: "Literal",
|
||||
value: {},
|
||||
value: /[P QR]/i,
|
||||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
@ -7623,7 +7623,7 @@ test("var x = /foo\\/bar/", {
|
||||
},
|
||||
init: {
|
||||
type: "Literal",
|
||||
value: {},
|
||||
value: /foo\/bar/,
|
||||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
@ -7696,7 +7696,7 @@ test("var x = /=([^=\\s])+/g", {
|
||||
},
|
||||
init: {
|
||||
type: "Literal",
|
||||
value: {},
|
||||
value: /=([^=\s])+/g,
|
||||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
@ -7769,7 +7769,7 @@ test("var x = /[P QR]/\\u0067", {
|
||||
},
|
||||
init: {
|
||||
type: "Literal",
|
||||
value: {},
|
||||
value: /[P QR]/g,
|
||||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
@ -23788,21 +23788,23 @@ test("function hello(...rest) { }", {
|
||||
}
|
||||
}
|
||||
},
|
||||
params: [],
|
||||
rest: {
|
||||
type: "Identifier",
|
||||
name: "rest",
|
||||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 18
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 22
|
||||
params: [{
|
||||
type: "RestElement",
|
||||
argument: {
|
||||
type: "Identifier",
|
||||
name: "rest",
|
||||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 18
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 22
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}],
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
body: [],
|
||||
@ -23877,22 +23879,25 @@ test("function hello(a, ...rest) { }", {
|
||||
column: 16
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
rest: {
|
||||
type: "Identifier",
|
||||
name: "rest",
|
||||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 21
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 25
|
||||
},
|
||||
{
|
||||
type: "RestElement",
|
||||
argument: {
|
||||
type: "Identifier",
|
||||
name: "rest",
|
||||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 21
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 25
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
body: [],
|
||||
@ -24089,21 +24094,23 @@ test("var hi = function (...r) { sayHi() };", {
|
||||
init: {
|
||||
type: "FunctionExpression",
|
||||
id: null,
|
||||
params: [],
|
||||
rest: {
|
||||
type: "Identifier",
|
||||
name: "r",
|
||||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 22
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 23
|
||||
params: [{
|
||||
type: "RestElement",
|
||||
argument: {
|
||||
type: "Identifier",
|
||||
name: "r",
|
||||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 22
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 23
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}],
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
body: [
|
||||
@ -28862,3 +28869,48 @@ test("#!/usr/bin/node\n;", {}, {
|
||||
end: 15
|
||||
}]
|
||||
});
|
||||
|
||||
// https://github.com/marijnh/acorn/issues/204
|
||||
test("(function () {} / 1)", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "BinaryExpression",
|
||||
left: {
|
||||
type: "FunctionExpression",
|
||||
id: null,
|
||||
params: [],
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
body: []
|
||||
}
|
||||
},
|
||||
operator: "/",
|
||||
right: {type: "Literal", value: 1}
|
||||
}
|
||||
}]
|
||||
});
|
||||
|
||||
test("function f() {} / 1 /", {
|
||||
type: "Program",
|
||||
body: [
|
||||
{
|
||||
type: "FunctionDeclaration",
|
||||
id: {type: "Identifier", name: "f"},
|
||||
params: [],
|
||||
body: {
|
||||
type: "BlockStatement",
|
||||
body: []
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "Literal",
|
||||
regex: {pattern: " 1 ", flags: ""},
|
||||
value: / 1 /
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
@ -200,7 +200,7 @@
|
||||
base.ReturnStatement = base.YieldExpression = function(node, st, c) {
|
||||
if (node.argument) c(node.argument, st, "Expression");
|
||||
};
|
||||
base.ThrowStatement = base.SpreadElement = function(node, st, c) {
|
||||
base.ThrowStatement = base.SpreadElement = base.RestElement = function(node, st, c) {
|
||||
c(node.argument, st, "Expression");
|
||||
};
|
||||
base.TryStatement = function(node, st, c) {
|
||||
@ -249,13 +249,13 @@
|
||||
|
||||
base.Expression = skipThrough;
|
||||
base.ThisExpression = ignore;
|
||||
base.ArrayExpression = function(node, st, c) {
|
||||
base.ArrayExpression = base.ArrayPattern = function(node, st, c) {
|
||||
for (var i = 0; i < node.elements.length; ++i) {
|
||||
var elt = node.elements[i];
|
||||
if (elt) c(elt, st, "Expression");
|
||||
}
|
||||
};
|
||||
base.ObjectExpression = function(node, st, c) {
|
||||
base.ObjectExpression = base.ObjectPattern = function(node, st, c) {
|
||||
for (var i = 0; i < node.properties.length; ++i)
|
||||
c(node.properties[i], st);
|
||||
};
|
||||
@ -267,7 +267,7 @@
|
||||
base.UnaryExpression = base.UpdateExpression = function(node, st, c) {
|
||||
c(node.argument, st, "Expression");
|
||||
};
|
||||
base.BinaryExpression = base.AssignmentExpression = base.LogicalExpression = function(node, st, c) {
|
||||
base.BinaryExpression = base.AssignmentExpression = base.AssignmentPattern = base.LogicalExpression = function(node, st, c) {
|
||||
c(node.left, st, "Expression");
|
||||
c(node.right, st, "Expression");
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user