Conflicts:
	acorn.js
	package.json
This commit is contained in:
Sebastian McKenzie 2014-10-22 21:30:58 +11:00
commit 7a4715c2de
11 changed files with 688 additions and 392 deletions

View File

@ -19,9 +19,11 @@ Marijn Haverbeke
Martin Carlberg
Mathias Bynens
Mathieu 'p01' Henri
Max Schaefer
Mihai Bazon
Oskar Schöldström
Paul Harper
Peter Rust
PlNG
r-e-d
zsjforcn

View File

@ -151,8 +151,17 @@ object referring to that same position.
- **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.
@ -195,6 +204,21 @@ console.log(escodegen.generate(ast, {comment: true}));
[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
@ -206,7 +230,7 @@ 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.
tokenizer. The loose parser does not support ECMAScript 6 syntax yet.
### util/walk.js ###

222
acorn.js
View File

@ -28,7 +28,7 @@
})(this, function(exports) {
"use strict";
exports.version = "0.7.1";
exports.version = "0.9.1";
// The main exported interface (under `self.acorn` when in the
// browser) is a `parse` function that takes a code string and
@ -43,6 +43,7 @@
input = String(inpt); inputLen = input.length;
setOptions(opts);
initTokenState();
initParserState();
return parseTopLevel(options.program);
};
@ -111,7 +112,22 @@
sourceFile: null,
// This value, if given, is stored in every node, whether
// `locations` is on or off.
directSourceFile: null
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) {
@ -287,6 +303,14 @@
var inTemplate;
function initParserState() {
lastStart = lastEnd = tokPos;
if (options.locations) lastEndLoc = new Position;
inFunction = inGenerator = strict = false;
labels = [];
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
@ -564,9 +588,15 @@
// Reset the token state. Used at the start of a parse.
function initTokenState() {
tokCurLine = 1;
tokPos = tokLineStart = 0;
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;
inTemplate = inXJSChild = inXJSTag = false;
@ -588,7 +618,7 @@
tokRegexpAllowed = type.beforeExpr;
if (options.onToken) {
options.onToken(new Token());
}
}
}
function skipBlockComment() {
@ -1086,7 +1116,6 @@
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'
@ -1560,19 +1589,26 @@
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.
// Sometimes, a node is only started *after* the token stream passed
// its start position. The functions below help storing a position
// and creating a node from a previous position.
function startNodeFrom(other) {
var node = new Node();
node.start = other.start;
function storeCurrentPos() {
return options.locations ? [tokStart, tokStartLoc] : tokStart;
}
function startNodeAt(pos) {
var node = new Node(), start = pos;
if (options.locations) {
node.loc = new SourceLocation();
node.loc.start = other.loc.start;
node.loc.start = start[1];
start = pos[0];
}
node.start = start;
if (options.directSourceFile)
node.sourceFile = options.directSourceFile;
if (options.ranges)
node.range = [other.range[0], 0];
node.range = [start, 0];
return node;
}
@ -1714,8 +1750,10 @@
break;
case "ArrayPattern":
for (var i = 0; i < param.elements.length; i++)
checkFunctionParam(param.elements[i], nameHash);
for (var i = 0; i < param.elements.length; i++) {
var elem = param.elements[i];
if (elem) checkFunctionParam(elem, nameHash);
}
break;
}
}
@ -1780,6 +1818,10 @@
case "SpreadElement":
break;
case "ParenthesizedExpression":
checkLVal(expr.expression);
break;
default:
raise(expr.start, "Assigning to rvalue");
}
@ -1793,12 +1835,6 @@
// 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) {
@ -1920,13 +1956,13 @@
next();
parseVar(init, true, varKind);
finishNode(init, "VariableDeclaration");
if ((tokType === _in || (tokType === _name && tokVal === "of")) && init.declarations.length === 1 &&
if ((tokType === _in || (options.ecmaVersion >= 6 && 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")) {
if (tokType === _in || (options.ecmaVersion >= 6 && tokType === _name && tokVal === "of")) {
checkLVal(init);
return parseForIn(node, init);
}
@ -2088,7 +2124,7 @@
// function bodies).
function parseBlock(allowStrict) {
var node = startNode(), first = true, strict = false, oldStrict;
var node = startNode(), first = true, oldStrict;
node.body = [];
expect(_braceL);
while (!eat(_braceR)) {
@ -2100,7 +2136,7 @@
}
first = false;
}
if (strict && !oldStrict) setStrict(false);
if (oldStrict === false) setStrict(false);
return finishNode(node, "BlockStatement");
}
@ -2163,9 +2199,10 @@
// or the `in` operator (in for loops initalization expressions).
function parseExpression(noComma, noIn) {
var start = storeCurrentPos();
var expr = parseMaybeAssign(noIn);
if (!noComma && tokType === _comma) {
var node = startNodeFrom(expr);
var node = startNodeAt(start);
node.expressions = [expr];
while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn));
return finishNode(node, "SequenceExpression");
@ -2177,9 +2214,10 @@
// operators like `+=`.
function parseMaybeAssign(noIn) {
var start = storeCurrentPos();
var left = parseMaybeConditional(noIn);
if (tokType.isAssign) {
var node = startNodeFrom(left);
var node = startNodeAt(start);
node.operator = tokVal;
node.left = tokType === _eq ? toAssignable(left) : left;
checkLVal(left);
@ -2193,9 +2231,10 @@
// Parse a ternary conditional (`?:`) operator.
function parseMaybeConditional(noIn) {
var start = storeCurrentPos();
var expr = parseExprOps(noIn);
if (eat(_question)) {
var node = startNodeFrom(expr);
var node = startNodeAt(start);
node.test = expr;
node.consequent = parseExpression(true);
expect(_colon);
@ -2208,7 +2247,8 @@
// Start the precedence parser.
function parseExprOps(noIn) {
return parseExprOp(parseMaybeUnary(), -1, noIn);
var start = storeCurrentPos();
return parseExprOp(parseMaybeUnary(), start, -1, noIn);
}
// Parse binary operators with the operator precedence parsing
@ -2217,18 +2257,19 @@
// 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) {
function parseExprOp(left, leftStart, minPrec, noIn) {
var prec = tokType.binop;
if (prec != null && (!noIn || tokType !== _in)) {
if (prec > minPrec) {
var node = startNodeFrom(left);
var node = startNodeAt(leftStart);
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);
var start = storeCurrentPos();
node.right = parseExprOp(parseMaybeUnary(), start, prec, noIn);
finishNode(node, (op === _logicalOR || op === _logicalAND) ? "LogicalExpression" : "BinaryExpression");
return parseExprOp(node, leftStart, minPrec, noIn);
}
}
return left;
@ -2250,9 +2291,10 @@
raise(node.start, "Deleting local variable in strict mode");
return finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
}
var start = storeCurrentPos();
var expr = parseExprSubscripts();
while (tokType.postfix && !canInsertSemicolon()) {
var node = startNodeFrom(expr);
var node = startNodeAt(start);
node.operator = tokVal;
node.prefix = false;
node.argument = expr;
@ -2266,33 +2308,34 @@
// Parse call, dot, and `[]`-subscript expressions.
function parseExprSubscripts() {
return parseSubscripts(parseExprAtom());
var start = storeCurrentPos();
return parseSubscripts(parseExprAtom(), start);
}
function parseSubscripts(base, noCalls) {
function parseSubscripts(base, start, noCalls) {
if (eat(_dot)) {
var node = startNodeFrom(base);
var node = startNodeAt(start);
node.object = base;
node.property = parseIdent(true);
node.computed = false;
return parseSubscripts(finishNode(node, "MemberExpression"), noCalls);
return parseSubscripts(finishNode(node, "MemberExpression"), start, noCalls);
} else if (eat(_bracketL)) {
var node = startNodeFrom(base);
var node = startNodeAt(start);
node.object = base;
node.property = parseExpression();
node.computed = true;
expect(_bracketR);
return parseSubscripts(finishNode(node, "MemberExpression"), noCalls);
return parseSubscripts(finishNode(node, "MemberExpression"), start, noCalls);
} else if (!noCalls && eat(_parenL)) {
var node = startNodeFrom(base);
var node = startNodeAt(start);
node.callee = base;
node.arguments = parseExprList(_parenR, false);
return parseSubscripts(finishNode(node, "CallExpression"), noCalls);
return parseSubscripts(finishNode(node, "CallExpression"), start, noCalls);
} else if (tokType === _bquote) {
var node = startNodeFrom(base);
var node = startNodeAt(start);
node.tag = base;
node.quasi = parseTemplate();
return parseSubscripts(finishNode(node, "TaggedTemplateExpression"), noCalls);
return parseSubscripts(finishNode(node, "TaggedTemplateExpression"), start, noCalls);
} return base;
}
@ -2312,9 +2355,10 @@
if (inGenerator) return parseYield();
case _name:
var start = storeCurrentPos();
var id = parseIdent(tokType !== _name);
if (eat(_arrow)) {
return parseArrowExpression(startNodeFrom(id), [id]);
return parseArrowExpression(startNodeAt(start), [id]);
}
return id;
@ -2333,43 +2377,41 @@
return finishNode(node, "Literal");
case _parenL:
var start = storeCurrentPos();
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);
val = parseComprehension(startNodeAt(start), 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();
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(startNodeAt(start), 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();
}
}
if (options.preserveParens) {
var par = startNodeAt(start);
par.expression = val;
val = finishNode(par, "ParenthesizedExpression");
}
}
}
}
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:
@ -2417,7 +2459,8 @@
function parseNew() {
var node = startNode();
next();
node.callee = parseSubscripts(parseExprAtom(), true);
var start = storeCurrentPos();
node.callee = parseSubscripts(parseExprAtom(), start, true);
if (eat(_parenL)) node.arguments = parseExprList(_parenR, false);
else node.arguments = empty;
return finishNode(node, "NewExpression");
@ -2446,7 +2489,7 @@
elem.tail = false;
next();
node.quasis.push(finishNode(elem, "TemplateElement"));
if (eat(_bquote)) { // '`', end of template
if (tokType === _bquote) { // '`', end of template
elem.tail = true;
break;
}
@ -2454,9 +2497,12 @@
expect(_dollarBraceL);
node.expressions.push(parseExpression());
inTemplate = true;
// hack to include previously skipped space
tokPos = tokEnd;
expect(_braceR);
}
inTemplate = false;
next();
return finishNode(node, "TemplateLiteral");
}
@ -2608,13 +2654,17 @@
node.rest = toAssignable(parseExprAtom(), false, true);
checkSpreadAssign(node.rest);
expect(_parenR);
defaults.push(null);
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 (options.ecmaVersion >= 6) {
if (eat(_eq)) {
hasDefaults = true;
defaults.push(parseExpression(true));
} else {
defaults.push(null);
}
}
if (!eat(_comma)) {
expect(_parenR);
@ -2964,10 +3014,11 @@
// Parse JSX object.
function parseXJSMemberExpression() {
var start = storeCurrentPos();
var node = parseXJSIdentifier();
while (eat(_dot)) {
var newNode = startNodeFrom(node);
var newNode = startNodeAt(start);
newNode.object = node;
newNode.property = parseXJSIdentifier();
node = finishNode(newNode, "XJSMemberExpression");
@ -3190,6 +3241,7 @@
function parseXJSElement() {
var node = startNode();
var children = [];
var origInXJSChild = inXJSChild;
@ -3230,4 +3282,4 @@
return finishNode(node, "XJSElement");
}
});
});

View File

@ -43,9 +43,11 @@
exports.parse_dammit = function(inpt, opts) {
if (!opts) opts = {};
input = String(inpt);
if (/^#!.*/.test(input)) input = "//" + input.slice(2);
options = opts;
if (!opts.tabSize) opts.tabSize = 4;
fetchToken = acorn.tokenize(inpt, opts);
fetchToken = acorn.tokenize(input, opts);
sourceFile = options.sourceFile || null;
context = [];
nextLineStart = 0;
@ -209,13 +211,27 @@
node.loc = new SourceLocation();
if (options.directSourceFile)
node.sourceFile = options.directSourceFile;
if (options.ranges)
node.range = [token.start, 0];
return node;
}
function startNodeFrom(other) {
var node = new Node(other.start);
if (options.locations)
node.loc = new SourceLocation(other.loc.start);
function storeCurrentPos() {
return options.locations ? [token.start, token.startLoc] : token.start;
}
function startNodeAt(pos) {
var node;
if (options.locations) {
node = new Node(pos[0]);
node.loc = new SourceLocation(pos[1]);
} else {
node = new Node(pos);
}
if (options.directSourceFile)
node.sourceFile = options.directSourceFile;
if (options.ranges)
node.range = [pos[0], 0];
return node;
}
@ -224,24 +240,15 @@
node.end = lastEnd;
if (options.locations)
node.loc.end = lastEndLoc;
if (options.ranges)
node.range[1] = lastEnd;
return node;
}
function getDummyLoc() {
if (options.locations) {
var loc = new SourceLocation();
loc.end = loc.start;
return loc;
}
};
function dummyIdent() {
var dummy = new Node(token.start);
dummy.type = "Identifier";
dummy.end = token.start;
var dummy = startNode();
dummy.name = "✖";
dummy.loc = getDummyLoc();
return dummy;
return finishNode(dummy, "Identifier");
}
function isDummy(node) { return node.name == "✖"; }
@ -399,7 +406,6 @@
case tt._var:
next();
node = parseVar(node);
semicolon();
return node;
case tt._while:
@ -487,13 +493,15 @@
decl.id = dummyIdent();
node.declarations.push(finishNode(decl, "VariableDeclarator"));
}
if (!noIn) semicolon();
return finishNode(node, "VariableDeclaration");
}
function parseExpression(noComma, noIn) {
var start = storeCurrentPos();
var expr = parseMaybeAssign(noIn);
if (!noComma && token.type === tt.comma) {
var node = startNodeFrom(expr);
var node = startNodeAt(start);
node.expressions = [expr];
while (eat(tt.comma)) node.expressions.push(parseMaybeAssign(noIn));
return finishNode(node, "SequenceExpression");
@ -511,9 +519,10 @@
}
function parseMaybeAssign(noIn) {
var start = storeCurrentPos();
var left = parseMaybeConditional(noIn);
if (token.type.isAssign) {
var node = startNodeFrom(left);
var node = startNodeAt(start);
node.operator = token.value;
node.left = checkLVal(left);
next();
@ -524,9 +533,10 @@
}
function parseMaybeConditional(noIn) {
var start = storeCurrentPos();
var expr = parseExprOps(noIn);
if (eat(tt.question)) {
var node = startNodeFrom(expr);
var node = startNodeAt(start);
node.test = expr;
node.consequent = parseExpression(true);
node.alternate = expect(tt.colon) ? parseExpression(true, noIn) : dummyIdent();
@ -536,25 +546,28 @@
}
function parseExprOps(noIn) {
var start = storeCurrentPos();
var indent = curIndent, line = curLineStart;
return parseExprOp(parseMaybeUnary(noIn), -1, noIn, indent, line);
return parseExprOp(parseMaybeUnary(noIn), start, -1, noIn, indent, line);
}
function parseExprOp(left, minPrec, noIn, indent, line) {
function parseExprOp(left, start, minPrec, noIn, indent, line) {
if (curLineStart != line && curIndent < indent && tokenStartsLine()) return left;
var prec = token.type.binop;
if (prec != null && (!noIn || token.type !== tt._in)) {
if (prec > minPrec) {
var node = startNodeFrom(left);
var node = startNodeAt(start);
node.left = left;
node.operator = token.value;
next();
if (curLineStart != line && curIndent < indent && tokenStartsLine())
if (curLineStart != line && curIndent < indent && tokenStartsLine()) {
node.right = dummyIdent();
else
node.right = parseExprOp(parseMaybeUnary(noIn), prec, noIn, indent, line);
var node = finishNode(node, /&&|\|\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression");
return parseExprOp(node, minPrec, noIn, indent, line);
} else {
var rightStart = storeCurrentPos();
node.right = parseExprOp(parseMaybeUnary(noIn), rightStart, prec, noIn, indent, line);
}
finishNode(node, /&&|\|\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression");
return parseExprOp(node, start, minPrec, noIn, indent, line);
}
}
return left;
@ -570,9 +583,10 @@
if (update) node.argument = checkLVal(node.argument);
return finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
}
var start = storeCurrentPos();
var expr = parseExprSubscripts();
while (token.type.postfix && !canInsertSemicolon()) {
var node = startNodeFrom(expr);
var node = startNodeAt(start);
node.operator = token.value;
node.prefix = false;
node.argument = checkLVal(expr);
@ -583,10 +597,11 @@
}
function parseExprSubscripts() {
return parseSubscripts(parseExprAtom(), false, curIndent, curLineStart);
var start = storeCurrentPos();
return parseSubscripts(parseExprAtom(), start, false, curIndent, curLineStart);
}
function parseSubscripts(base, noCalls, startIndent, line) {
function parseSubscripts(base, start, noCalls, startIndent, line) {
for (;;) {
if (curLineStart != line && curIndent <= startIndent && tokenStartsLine()) {
if (token.type == tt.dot && curIndent == startIndent)
@ -596,7 +611,7 @@
}
if (eat(tt.dot)) {
var node = startNodeFrom(base);
var node = startNodeAt(start);
node.object = base;
if (curLineStart != line && curIndent <= startIndent && tokenStartsLine())
node.property = dummyIdent();
@ -607,7 +622,7 @@
} else if (token.type == tt.bracketL) {
pushCx();
next();
var node = startNodeFrom(base);
var node = startNodeAt(start);
node.object = base;
node.property = parseExpression();
node.computed = true;
@ -616,7 +631,7 @@
base = finishNode(node, "MemberExpression");
} else if (!noCalls && token.type == tt.parenL) {
pushCx();
var node = startNodeFrom(base);
var node = startNodeAt(start);
node.callee = base;
node.arguments = parseExprList(tt.parenR);
base = finishNode(node, "CallExpression");
@ -649,11 +664,8 @@
return finishNode(node, "Literal");
case tt.parenL:
var tokStart1 = token.start;
next();
var val = parseExpression();
val.start = tokStart1;
val.end = token.end;
expect(tt.parenR);
return val;
@ -682,7 +694,8 @@
function parseNew() {
var node = startNode(), startIndent = curIndent, line = curLineStart;
next();
node.callee = parseSubscripts(parseExprAtom(), true, startIndent, line);
var start = storeCurrentPos();
node.callee = parseSubscripts(parseExprAtom(), start, true, startIndent, line);
if (token.type == tt.parenL) {
pushCx();
node.arguments = parseExprList(tt.parenR);
@ -696,9 +709,10 @@
var node = startNode();
node.properties = [];
pushCx();
var indent = curIndent + 1, line = curLineStart;
next();
var propIndent = curIndent, line = curLineStart;
while (!closes(tt.braceR, propIndent, line)) {
if (curIndent + 1 < indent) { indent = curIndent; line = curLineStart; }
while (!closes(tt.braceR, indent, line)) {
var name = parsePropertyName();
if (!name) { if (isDummy(parseExpression(true))) next(); eat(tt.comma); continue; }
var prop = startNode();
@ -712,9 +726,7 @@
prop.key = parsePropertyName() || dummyIdent();
prop.value = parseFunction(startNode(), false);
} else {
next();
eat(tt.comma);
continue;
prop.value = dummyIdent();
}
node.properties.push(finishNode(prop, "Property"));

View File

@ -1,6 +1,6 @@
# Combine existing list of authors with everyone known in git, sort, add header.
tail --lines=+3 AUTHORS > AUTHORS.tmp
git log --format='%aN' | grep -v abraidwood >> AUTHORS.tmp
echo -e "List of Acorn contributors. Updated before every release.\n" > AUTHORS
echo "List of Acorn contributors. Updated before every release.\n" > AUTHORS
sort -u AUTHORS.tmp >> AUTHORS
rm -f AUTHORS.tmp

45
bin/without_eval Executable file
View File

@ -0,0 +1,45 @@
#!/usr/bin/env node
var fs = require("fs");
var acornSrc = fs.readFileSync(require.resolve("../acorn"), "utf8");
var acorn = require("../acorn"), walk = require("../util/walk");
var ast = acorn.parse(acornSrc);
var touchups = [], uses = [];
walk.simple(ast, {
FunctionDeclaration: function(node) {
if (node.id.name == "makePredicate")
touchups.push({text: "// Removed to create an eval-free library", from: node.start, to: node.end});
},
VariableDeclaration: function(node) {
node.declarations.forEach(function(decl) {
if (decl.init && decl.init.type == "CallExpression" &&
decl.init.callee.name == "makePredicate")
uses.push(decl);
});
}
});
var results = Object.create(null);
var functions = new Function("predicates", acornSrc.replace(
/\}\);\s*$/, uses.map(function(decl) {
return "predicates[" + JSON.stringify(decl.id.name) + "] = " + decl.id.name + ";";
}).join("") + "});"))(results);
uses.forEach(function(decl) {
touchups.push({text: results[decl.id.name].toString(),
from: decl.init.start, to: decl.init.end});
});
var result = "", pos = 0;
touchups.sort(function(a, b) { return a.from - b.from; });
touchups.forEach(function(touchup) {
result += acornSrc.slice(pos, touchup.from);
result += touchup.text;
pos = touchup.to;
});
result += acornSrc.slice(pos);
process.stdout.write(result);

View File

@ -43,10 +43,9 @@
else callback("ok", test.code);
} else {
var mis = misMatch(test.ast, ast);
if (!mis && test.comments) mis = misMatch(test.comments, comments);
if (mis) callback("fail", test.code, mis);
if (test.comments) mis = misMatch(test.comments, comments);
if (!mis) callback("ok", test.code);
else callback("fail", test.code, mis);
else callback("ok", test.code);
}
} catch(e) {
if (test.error && e instanceof SyntaxError) {
@ -67,7 +66,7 @@
return str + " (" + pt + ")";
}
function misMatch(exp, act) {
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.splice) {
@ -83,7 +82,7 @@
if (mis) return addPath(mis, prop);
}
}
}
};
function mangle(ast) {
if (typeof ast != "object" || !ast) return;

View File

@ -1511,10 +1511,10 @@ test("e => ({ property: 42 })", {
end: {line: 1, column: 20}
}
}],
range: [5, 23],
range: [6, 22],
loc: {
start: {line: 1, column: 5},
end: {line: 1, column: 23}
start: {line: 1, column: 6},
end: {line: 1, column: 22}
}
},
rest: null,
@ -2330,10 +2330,10 @@ test("(x => x)", {
rest: null,
generator: false,
expression: true,
range: [0, 8],
range: [1, 7],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 8}
start: {line: 1, column: 1},
end: {line: 1, column: 7}
}
},
range: [0, 8],
@ -2500,19 +2500,19 @@ test("(x) => ((y, z) => (x, y, z))", {
}
}
],
range: [18, 27],
range: [19, 26],
loc: {
start: {line: 1, column: 18},
end: {line: 1, column: 27}
start: {line: 1, column: 19},
end: {line: 1, column: 26}
}
},
rest: null,
generator: false,
expression: true,
range: [7, 28],
range: [8, 27],
loc: {
start: {line: 1, column: 7},
end: {line: 1, column: 28}
start: {line: 1, column: 8},
end: {line: 1, column: 27}
}
},
rest: null,
@ -4268,10 +4268,10 @@ test("({ responseText: text }) = res", {
end: {line: 1, column: 21}
}
}],
range: [0, 24],
range: [1, 23],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 24}
start: {line: 1, column: 1},
end: {line: 1, column: 23}
}
},
right: {
@ -6115,10 +6115,10 @@ test("(function* () { yield v })", {
rest: null,
generator: true,
expression: false,
range: [0, 26],
range: [1, 25],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 26}
start: {line: 1, column: 1},
end: {line: 1, column: 25}
}
},
range: [0, 26],
@ -6195,10 +6195,10 @@ test("(function* () { yield\nv })", {
rest: null,
generator: true,
expression: false,
range: [0, 26],
range: [1, 25],
loc: {
start: {line: 1, column: 0},
end: {line: 2, column: 4}
start: {line: 1, column: 1},
end: {line: 2, column: 3}
}
},
range: [0, 26],
@ -6264,10 +6264,10 @@ test("(function* () { yield *v })", {
rest: null,
generator: true,
expression: false,
range: [0, 27],
range: [1, 26],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 27}
start: {line: 1, column: 1},
end: {line: 1, column: 26}
}
},
range: [0, 27],
@ -6572,10 +6572,10 @@ test("(function* () { yield yield 10 })", {
rest: null,
generator: true,
expression: false,
range: [0, 33],
range: [1, 32],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 33}
start: {line: 1, column: 1},
end: {line: 1, column: 32}
}
},
range: [0, 33],
@ -8138,10 +8138,10 @@ test("\"use strict\"; (class A {constructor() { super() }})", {
end: {line: 1, column: 50}
}
},
range: [14, 51],
range: [15, 50],
loc: {
start: {line: 1, column: 14},
end: {line: 1, column: 51}
start: {line: 1, column: 15},
end: {line: 1, column: 50}
}
},
range: [14, 51],
@ -8482,10 +8482,10 @@ test("\"use strict\"; (class A { static constructor() { super() }})", {
end: {line: 1, column: 58}
}
},
range: [14, 59],
range: [15, 58],
loc: {
start: {line: 1, column: 14},
end: {line: 1, column: 59}
start: {line: 1, column: 15},
end: {line: 1, column: 58}
}
},
range: [14, 59],
@ -9437,10 +9437,10 @@ test("({[x]: 10})", {
end: {line: 1, column: 9}
}
}],
range: [0, 11],
range: [1, 10],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 11}
start: {line: 1, column: 1},
end: {line: 1, column: 10}
}
},
range: [0, 11],
@ -9517,10 +9517,10 @@ test("({[\"x\" + \"y\"]: 10})", {
end: {line: 1, column: 17}
}
}],
range: [0, 19],
range: [1, 18],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 19}
start: {line: 1, column: 1},
end: {line: 1, column: 18}
}
},
range: [0, 19],
@ -9590,10 +9590,10 @@ test("({[x]: function() {}})", {
end: {line: 1, column: 20}
}
}],
range: [0, 22],
range: [1, 21],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 22}
start: {line: 1, column: 1},
end: {line: 1, column: 21}
}
},
range: [0, 22],
@ -9683,10 +9683,10 @@ test("({[x]: 10, y: 20})", {
}
}
],
range: [0, 18],
range: [1, 17],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 18}
start: {line: 1, column: 1},
end: {line: 1, column: 17}
}
},
range: [0, 18],
@ -9810,10 +9810,10 @@ test("({get [x]() {}, set [x](v) {}})", {
}
}
],
range: [0, 31],
range: [1, 30],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 31}
start: {line: 1, column: 1},
end: {line: 1, column: 30}
}
},
range: [0, 31],
@ -9883,10 +9883,10 @@ test("({[x]() {}})", {
end: {line: 1, column: 10}
}
}],
range: [0, 12],
range: [1, 11],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 12}
start: {line: 1, column: 1},
end: {line: 1, column: 11}
}
},
range: [0, 12],
@ -10769,10 +10769,10 @@ test("({f: function({x} = {x: 10}) {}})", {
end: {line: 1, column: 31}
}
}],
range: [0, 33],
range: [1, 32],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 33}
start: {line: 1, column: 1},
end: {line: 1, column: 32}
}
},
range: [0, 33],
@ -10917,10 +10917,10 @@ test("({f({x} = {x: 10}) {}})", {
end: {line: 1, column: 21}
}
}],
range: [0, 23],
range: [1, 22],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 23}
start: {line: 1, column: 1},
end: {line: 1, column: 22}
}
},
range: [0, 23],
@ -11073,10 +11073,10 @@ test("(class {f({x} = {x: 10}) {}})", {
end: {line: 1, column: 28}
}
},
range: [0, 29],
range: [1, 28],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 29}
start: {line: 1, column: 1},
end: {line: 1, column: 28}
}
},
range: [0, 29],
@ -11192,10 +11192,10 @@ test("(({x} = {x: 10}) => {})", {
rest: null,
generator: false,
expression: false,
range: [0, 23],
range: [1, 22],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 23}
start: {line: 1, column: 1},
end: {line: 1, column: 22}
}
},
range: [0, 23],
@ -12267,10 +12267,10 @@ test("(function x([ a, b ]){})", {
rest: null,
generator: false,
expression: false,
range: [0, 24],
range: [1, 23],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 24}
start: {line: 1, column: 1},
end: {line: 1, column: 23}
}
},
range: [0, 24],
@ -12388,10 +12388,10 @@ test("(function x({ a, b }){})", {
rest: null,
generator: false,
expression: false,
range: [0, 24],
range: [1, 23],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 24}
start: {line: 1, column: 1},
end: {line: 1, column: 23}
}
},
range: [0, 24],
@ -12467,10 +12467,10 @@ test("(function x(...[ a, b ]){})", {
},
generator: false,
expression: false,
range: [0, 27],
range: [1, 26],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 27}
start: {line: 1, column: 1},
end: {line: 1, column: 26}
}
},
range: [0, 27],
@ -12704,10 +12704,10 @@ test("(function x({ a: { w, x }, b: [y, z] }, ...[a, b, c]){})", {
},
generator: false,
expression: false,
range: [0, 56],
range: [1, 55],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 56}
start: {line: 1, column: 1},
end: {line: 1, column: 55}
}
},
range: [0, 56],
@ -12804,10 +12804,10 @@ test("({ x([ a, b ]){} })", {
end: {line: 1, column: 16}
}
}],
range: [0, 19],
range: [1, 18],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 19}
start: {line: 1, column: 1},
end: {line: 1, column: 18}
}
},
range: [0, 19],
@ -12904,10 +12904,10 @@ test("({ x(...[ a, b ]){} })", {
end: {line: 1, column: 19}
}
}],
range: [0, 22],
range: [1, 21],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 22}
start: {line: 1, column: 1},
end: {line: 1, column: 21}
}
},
range: [0, 22],
@ -13162,10 +13162,10 @@ test("({ x({ a: { w, x }, b: [y, z] }, ...[a, b, c]){} })", {
end: {line: 1, column: 48}
}
}],
range: [0, 51],
range: [1, 50],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 51}
start: {line: 1, column: 1},
end: {line: 1, column: 50}
}
},
range: [0, 51],
@ -15086,10 +15086,10 @@ test("(function () { yield* 10 })", {
rest: null,
generator: false,
expression: false,
range: [0, 27],
range: [1, 26],
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 27}
start: {line: 1, column: 1},
end: {line: 1, column: 26}
}
},
range: [0, 27],
@ -15246,3 +15246,170 @@ testFail("\"use strict\"; (eval) => 42", "Defining 'eval' in strict mode (1:15)"
testFail("(eval) => { \"use strict\"; 42 }", "Defining 'eval' in strict mode (1:1)", {ecmaVersion: 6});
testFail("({ get test() { } }) => 42", "Unexpected token (1:7)", {ecmaVersion: 6});
/* Regression tests */
// # https://github.com/marijnh/acorn/issues/127
test('doSmth(`${x} + ${y} = ${x + y}`)', {
type: "Program",
start: 0,
end: 32,
body: [{
type: "ExpressionStatement",
start: 0,
end: 32,
expression: {
type: "CallExpression",
start: 0,
end: 32,
callee: {
type: "Identifier",
start: 0,
end: 6,
name: "doSmth"
},
arguments: [{
type: "TemplateLiteral",
start: 7,
end: 31,
expressions: [
{
type: "Identifier",
start: 10,
end: 11,
name: "x"
},
{
type: "Identifier",
start: 17,
end: 18,
name: "y"
},
{
type: "BinaryExpression",
start: 24,
end: 29,
left: {
type: "Identifier",
start: 24,
end: 25,
name: "x"
},
operator: "+",
right: {
type: "Identifier",
start: 28,
end: 29,
name: "y"
}
}
],
quasis: [
{
type: "TemplateElement",
start: 8,
end: 8,
value: {cooked: "", raw: ""},
tail: false
},
{
type: "TemplateElement",
start: 12,
end: 15,
value: {cooked: " + ", raw: " + "},
tail: false
},
{
type: "TemplateElement",
start: 19,
end: 22,
value: {cooked: " = ", raw: " = "},
tail: false
},
{
type: "TemplateElement",
start: 30,
end: 30,
value: {cooked: "", raw: ""},
tail: true
}
]
}]
}
}]
}, {ecmaVersion: 6});
// # https://github.com/marijnh/acorn/issues/129
test('function normal(x, y = 10) {}', {
type: "Program",
start: 0,
end: 29,
body: [{
type: "FunctionDeclaration",
start: 0,
end: 29,
id: {
type: "Identifier",
start: 9,
end: 15,
name: "normal"
},
params: [
{
type: "Identifier",
start: 16,
end: 17,
name: "x"
},
{
type: "Identifier",
start: 19,
end: 20,
name: "y"
}
],
defaults: [
null,
{
type: "Literal",
start: 23,
end: 25,
value: 10,
raw: "10"
}
],
rest: null,
generator: false,
body: {
type: "BlockStatement",
start: 27,
end: 29,
body: []
},
expression: false
}]
}, {ecmaVersion: 6});
test("'use strict'; function f([x,,z]) {}", {}, {ecmaVersion: 6});
// test preserveParens option with arrow functions
test("() => 42", {
type: "Program",
body: [{
type: "ExpressionStatement",
expression: {
type: "ArrowFunctionExpression"
}
}]
}, {ecmaVersion: 6, preserveParens: true});
// test preserveParens with generators
test("(for (x of array) for (y of array2) if (x === test) x)", {
type: "Program",
body: [{
type: "ExpressionStatement",
expression: {
type: "ComprehensionExpression"
}
}]
}, {ecmaVersion: 6, preserveParens: true});

View File

@ -2029,10 +2029,10 @@ var fbTestFixture = {
},
closingElement: null,
children: [],
range: [0, 9],
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: {
@ -3215,4 +3215,4 @@ for (var code in fbTestFixture.XJS) {
locations: true,
ranges: true
});
}
}

View File

@ -2,9 +2,8 @@
// (http://esprima.org/test/)
if (typeof exports != "undefined") {
var test = require("./driver.js").test;
var testFail = require("./driver.js").testFail;
var testAssert = require("./driver.js").testAssert;
var driver = require("./driver.js");
var test = driver.test, testFail = driver.testFail, testAssert = driver.testAssert, misMatch = driver.misMatch;
var acorn = require("..");
}
@ -174,6 +173,118 @@ test("(1 + 2 ) * 3", {
}
}
},
loc: {
start: {
line: 1,
column: 1
},
end: {
line: 1,
column: 6
}
}
},
operator: "*",
right: {
type: "Literal",
value: 3,
loc: {
start: {
line: 1,
column: 11
},
end: {
line: 1,
column: 12
}
}
},
loc: {
start: {
line: 1,
column: 0
},
end: {
line: 1,
column: 12
}
}
},
loc: {
start: {
line: 1,
column: 0
},
end: {
line: 1,
column: 12
}
}
}
],
loc: {
start: {
line: 1,
column: 0
},
end: {
line: 1,
column: 12
}
}
});
test("(1 + 2 ) * 3", {
type: "Program",
body: [
{
type: "ExpressionStatement",
expression: {
type: "BinaryExpression",
left: {
type: "ParenthesizedExpression",
expression: {
type: "BinaryExpression",
left: {
type: "Literal",
value: 1,
loc: {
start: {
line: 1,
column: 1
},
end: {
line: 1,
column: 2
}
}
},
operator: "+",
right: {
type: "Literal",
value: 2,
loc: {
start: {
line: 1,
column: 5
},
end: {
line: 1,
column: 6
}
}
},
loc: {
start: {
line: 1,
column: 1
},
end: {
line: 1,
column: 6
}
}
},
loc: {
start: {
line: 1,
@ -233,8 +344,13 @@ test("(1 + 2 ) * 3", {
column: 12
}
}
}, {
locations: true,
preserveParens: true
});
test("(x) = 23", {}, { preserveParens: true });
test("x = []", {
type: "Program",
body: [
@ -8202,11 +8318,11 @@ test("( new foo).bar()", {
loc: {
start: {
line: 1,
column: 0
column: 2
},
end: {
line: 1,
column: 10
column: 9
}
}
},
@ -8371,11 +8487,11 @@ test("( foo )()", {
loc: {
start: {
line: 1,
column: 0
column: 5
},
end: {
line: 1,
column: 11
column: 8
}
}
},
@ -17217,11 +17333,11 @@ test("if (morning) (function(){})", {
loc: {
start: {
line: 1,
column: 13
column: 14
},
end: {
line: 1,
column: 27
column: 26
}
}
},
@ -20508,11 +20624,11 @@ test("(function(){ return })", {
loc: {
start: {
line: 1,
column: 0
column: 1
},
end: {
line: 1,
column: 22
column: 21
}
}
},
@ -20581,11 +20697,11 @@ test("(function(){ return; })", {
loc: {
start: {
line: 1,
column: 0
column: 1
},
end: {
line: 1,
column: 23
column: 22
}
}
},
@ -20667,11 +20783,11 @@ test("(function(){ return x; })", {
loc: {
start: {
line: 1,
column: 0
column: 1
},
end: {
line: 1,
column: 25
column: 24
}
}
},
@ -20781,11 +20897,11 @@ test("(function(){ return x * y })", {
loc: {
start: {
line: 1,
column: 0
column: 1
},
end: {
line: 1,
column: 28
column: 27
}
}
},
@ -23194,11 +23310,11 @@ test("(function test(t, t) { })", {
loc: {
start: {
line: 1,
column: 0
column: 1
},
end: {
line: 1,
column: 25
column: 24
}
}
},
@ -24412,11 +24528,11 @@ test("(function(){})", {
loc: {
start: {
line: 1,
column: 0
column: 1
},
end: {
line: 1,
column: 14
column: 13
}
}
},
@ -25522,11 +25638,11 @@ test("(function(){ return\nx; })", {
loc: {
start: {
line: 1,
column: 0
column: 1
},
end: {
line: 2,
column: 5
column: 4
}
}
},
@ -25622,11 +25738,11 @@ test("(function(){ return // Comment\nx; })", {
loc: {
start: {
line: 1,
column: 0
column: 1
},
end: {
line: 2,
column: 5
column: 4
}
}
},
@ -25722,11 +25838,11 @@ test("(function(){ return/* Multiline\nComment */x; })", {
loc: {
start: {
line: 1,
column: 0
column: 1
},
end: {
line: 2,
column: 15
column: 14
}
}
},
@ -26026,8 +26142,6 @@ test("", {
test("foo: if (true) break foo;", {
type: "Program",
start: 0,
end: 25,
loc: {
start: {
line: 1,
@ -26041,8 +26155,6 @@ test("foo: if (true) break foo;", {
body: [
{
type: "LabeledStatement",
start: 0,
end: 25,
loc: {
start: {
line: 1,
@ -26055,8 +26167,6 @@ test("foo: if (true) break foo;", {
},
body: {
type: "IfStatement",
start: 5,
end: 25,
loc: {
start: {
line: 1,
@ -26069,8 +26179,6 @@ test("foo: if (true) break foo;", {
},
test: {
type: "Literal",
start: 9,
end: 13,
loc: {
start: {
line: 1,
@ -26085,8 +26193,6 @@ test("foo: if (true) break foo;", {
},
consequent: {
type: "BreakStatement",
start: 15,
end: 25,
loc: {
start: {
line: 1,
@ -26099,8 +26205,6 @@ test("foo: if (true) break foo;", {
},
label: {
type: "Identifier",
start: 21,
end: 24,
loc: {
start: {
line: 1,
@ -26118,8 +26222,6 @@ test("foo: if (true) break foo;", {
},
label: {
type: "Identifier",
start: 0,
end: 3,
loc: {
start: {
line: 1,
@ -26138,8 +26240,6 @@ test("foo: if (true) break foo;", {
test("(function () {\n 'use strict';\n '\0';\n}())", {
type: "Program",
start: 0,
end: 40,
loc: {
start: {
line: 1,
@ -26153,8 +26253,6 @@ test("(function () {\n 'use strict';\n '\0';\n}())", {
body: [
{
type: "ExpressionStatement",
start: 0,
end: 40,
loc: {
start: {
line: 1,
@ -26167,21 +26265,18 @@ test("(function () {\n 'use strict';\n '\0';\n}())", {
},
expression: {
type: "CallExpression",
start: 0,
loc: {
start: {
line: 1,
column: 0
column: 1
},
end: {
line: 4,
column: 4
column: 3
}
},
callee: {
type: "FunctionExpression",
start: 1,
end: 37,
loc: {
start: {
line: 1,
@ -26196,8 +26291,6 @@ test("(function () {\n 'use strict';\n '\0';\n}())", {
params: [],
body: {
type: "BlockStatement",
start: 13,
end: 37,
loc: {
start: {
line: 1,
@ -26211,8 +26304,6 @@ test("(function () {\n 'use strict';\n '\0';\n}())", {
body: [
{
type: "ExpressionStatement",
start: 16,
end: 29,
loc: {
start: {
line: 2,
@ -26225,8 +26316,6 @@ test("(function () {\n 'use strict';\n '\0';\n}())", {
},
expression: {
type: "Literal",
start: 16,
end: 28,
loc: {
start: {
line: 2,
@ -26242,8 +26331,6 @@ test("(function () {\n 'use strict';\n '\0';\n}())", {
},
{
type: "ExpressionStatement",
start: 31,
end: 35,
loc: {
start: {
line: 3,
@ -26256,8 +26343,6 @@ test("(function () {\n 'use strict';\n '\0';\n}())", {
},
expression: {
type: "Literal",
start: 31,
end: 34,
loc: {
start: {
line: 3,
@ -26275,7 +26360,6 @@ test("(function () {\n 'use strict';\n '\0';\n}())", {
}
},
arguments: [],
end: 40
}
}
]
@ -26283,43 +26367,29 @@ test("(function () {\n 'use strict';\n '\0';\n}())", {
test("123..toString(10)", {
type: "Program",
start: 0,
end: 17,
body: [
{
type: "ExpressionStatement",
start: 0,
end: 17,
expression: {
type: "CallExpression",
start: 0,
callee: {
type: "MemberExpression",
start: 0,
object: {
type: "Literal",
start: 0,
end: 4,
value: 123
},
property: {
type: "Identifier",
start: 5,
end: 13,
name: "toString"
},
computed: false,
end: 13
},
arguments: [
{
type: "Literal",
start: 14,
end: 16,
value: 10
}
],
end: 17
}
}
]
@ -26327,30 +26397,20 @@ test("123..toString(10)", {
test("123.+2", {
type: "Program",
start: 0,
end: 6,
body: [
{
type: "ExpressionStatement",
start: 0,
end: 6,
expression: {
type: "BinaryExpression",
start: 0,
left: {
type: "Literal",
start: 0,
end: 4,
value: 123
},
operator: "+",
right: {
type: "Literal",
start: 5,
end: 6,
value: 2
},
end: 6
}
}
]
@ -26358,28 +26418,18 @@ test("123.+2", {
test("a\u2028b", {
type: "Program",
start: 0,
end: 3,
body: [
{
type: "ExpressionStatement",
start: 0,
end: 1,
expression: {
type: "Identifier",
start: 0,
end: 1,
name: "a"
}
},
{
type: "ExpressionStatement",
start: 2,
end: 3,
expression: {
type: "Identifier",
start: 2,
end: 3,
name: "b"
}
}
@ -26437,28 +26487,18 @@ test("foo: 10; foo: 20;", {
test("if(1)/ foo/", {
type: "Program",
start: 0,
end: 12,
body: [
{
type: "IfStatement",
start: 0,
end: 12,
test: {
type: "Literal",
start: 3,
end: 4,
value: 1,
raw: "1"
},
consequent: {
type: "ExpressionStatement",
start: 5,
end: 12,
expression: {
type: "Literal",
start: 5,
end: 12,
raw: "/ foo/"
}
},
@ -26475,8 +26515,6 @@ test("price_9̶9̶_89", {
expression: {
type: "Identifier",
name: "price_9̶9̶_89",
start: 0,
end: 13
}
}
]
@ -26486,8 +26524,6 @@ test("price_9̶9̶_89", {
test("var a = 1;", {
type: "Program",
start: 0,
end: 10,
loc: {
start: {
line: 1,
@ -26502,8 +26538,6 @@ test("var a = 1;", {
body: [
{
type: "VariableDeclaration",
start: 0,
end: 10,
loc: {
start: {
line: 1,
@ -26518,8 +26552,6 @@ test("var a = 1;", {
declarations: [
{
type: "VariableDeclarator",
start: 4,
end: 9,
loc: {
start: {
line: 1,
@ -26533,8 +26565,6 @@ test("var a = 1;", {
},
id: {
type: "Identifier",
start: 4,
end: 5,
loc: {
start: {
line: 1,
@ -26550,8 +26580,6 @@ test("var a = 1;", {
},
init: {
type: "Literal",
start: 8,
end: 9,
loc: {
start: {
line: 1,
@ -26624,28 +26652,18 @@ test("{}/=/", {
test("foo <!--bar\n+baz", {
type: "Program",
start: 0,
end: 16,
body: [
{
type: "ExpressionStatement",
start: 0,
end: 16,
expression: {
type: "BinaryExpression",
start: 0,
end: 16,
left: {
type: "Identifier",
start: 0,
end: 3,
name: "foo"
},
operator: "+",
right: {
type: "Identifier",
start: 13,
end: 16,
name: "baz"
}
}
@ -26795,7 +26813,7 @@ testFail("func() = 4",
"Assigning to rvalue (1:0)");
testFail("(1 + 1) = 10",
"Assigning to rvalue (1:0)");
"Assigning to rvalue (1:1)");
testFail("1++",
"Assigning to rvalue (1:0)");
@ -26810,7 +26828,7 @@ testFail("--1",
"Assigning to rvalue (1:2)");
testFail("for((1 + 1) in list) process(x);",
"Assigning to rvalue (1:4)");
"Assigning to rvalue (1:5)");
testFail("[",
"Unexpected token (1:1)");
@ -27285,6 +27303,9 @@ testFail("(function a(eval) { \"use strict\"; })",
testFail("(function a(package) { \"use strict\"; })",
"Defining 'package' in strict mode (1:12)");
testFail("\"use strict\";function foo(){\"use strict\";}function bar(){var v = 015}",
"Invalid number (1:65)");
testFail("var this = 10;", "Unexpected token (1:4)");
testFail("throw\n10;", "Illegal newline after throw (1:5)");
@ -27306,8 +27327,6 @@ testFail("for(let x = 0;;);", "Unexpected token (1:8)");
test("let++", {
type: "Program",
start: 0,
end: 5,
loc: {
start: {
line: 1,
@ -27321,8 +27340,6 @@ test("let++", {
body: [
{
type: "ExpressionStatement",
start: 0,
end: 5,
loc: {
start: {
line: 1,
@ -27335,8 +27352,6 @@ test("let++", {
},
expression: {
type: "UpdateExpression",
start: 0,
end: 5,
loc: {
start: {
line: 1,
@ -27351,8 +27366,6 @@ test("let++", {
prefix: false,
argument: {
type: "Identifier",
start: 0,
end: 3,
loc: {
start: {
line: 1,
@ -28594,6 +28607,10 @@ testFail("const a;", "Unexpected token (1:7)", {ecmaVersion: 6});
testFail("for(const x = 0;;);", "Unexpected token (1:4)", {ecmaVersion: 6});
testFail("for(x of a);", "Unexpected token (1:6)");
testFail("for(var x of a);", "Unexpected token (1:10)");
// Assertion Tests
(function() {
var actualComments = [],
@ -28697,8 +28714,6 @@ test("<!--\n;", {
{
type: tokTypes._var,
value: "var",
start: 0,
end: 3,
loc: {
start: {line: 1, column: 0},
end: {line: 1, column: 3}
@ -28707,8 +28722,6 @@ test("<!--\n;", {
{
type: tokTypes.name,
value: "x",
start: 4,
end: 5,
loc: {
start: {line: 1, column: 4},
end: {line: 1, column: 5}
@ -28717,8 +28730,6 @@ test("<!--\n;", {
{
type: tokTypes.eq,
value: "=",
start: 6,
end: 7,
loc: {
start: {line: 1, column: 6},
end: {line: 1, column: 7}
@ -28727,8 +28738,6 @@ test("<!--\n;", {
{
type: tokTypes.parenL,
value: undefined,
start: 8,
end: 9,
loc: {
start: {line: 1, column: 8},
end: {line: 1, column: 9}
@ -28737,8 +28746,6 @@ test("<!--\n;", {
{
type: tokTypes.num,
value: 1,
start: 9,
end: 10,
loc: {
start: {line: 1, column: 9},
end: {line: 1, column: 10}
@ -28747,8 +28754,6 @@ test("<!--\n;", {
{
type: {binop: 9, prefix: true, beforeExpr: true},
value: "+",
start: 11,
end: 12,
loc: {
start: {line: 1, column: 11},
end: {line: 1, column: 12}
@ -28757,8 +28762,6 @@ test("<!--\n;", {
{
type: tokTypes.num,
value: 2,
start: 13,
end: 14,
loc: {
start: {line: 1, column: 13},
end: {line: 1, column: 14}
@ -28767,8 +28770,6 @@ test("<!--\n;", {
{
type: tokTypes.parenR,
value: undefined,
start: 14,
end: 15,
loc: {
start: {line: 1, column: 14},
end: {line: 1, column: 15}
@ -28777,8 +28778,6 @@ test("<!--\n;", {
{
type: tokTypes.eof,
value: undefined,
start: 15,
end: 15,
loc: {
start: {line: 1, column: 15},
end: {line: 1, column: 15}
@ -28787,17 +28786,11 @@ test("<!--\n;", {
];
testAssert('var x = (1 + 2)', function assert(ast) {
if (actualTokens.length !== expectedTokens.length) {
return JSON.stringify(actualTokens) + " !== " + JSON.stringify(expectedTokens);
return "Bad token stream length: expected " + expectedTokens.length + ", got " + actualTokens.length;
} else {
for (var i=0, n=actualTokens.length; i < n; i++) {
var actualToken = JSON.stringify(
actualTokens[i],
// just remove this when startLoc/endLoc support is dropped
function (key, value) { if (key !== 'startLoc' && key !== 'endLoc') return value; }
);
var expectedToken = JSON.stringify(expectedTokens[i]);
if (actualToken !== expectedToken)
return actualToken + ' !== ' + expectedToken;
var mis = misMatch(expectedTokens[i], actualTokens[i]);
if (mis) return mis;
}
}
}, {

View File

@ -306,6 +306,8 @@
c(node.body, st, "Expression");
};
// NOTE: the stuff below is deprecated, and will be removed when 1.0 is released
// A custom walker that keeps track of the scope chain and the
// variables defined in it.
function makeScope(prev, isCatch) {