diff --git a/AUTHORS b/AUTHORS index 276eaace8a..a9e6016d75 100644 --- a/AUTHORS +++ b/AUTHORS @@ -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 diff --git a/README.md b/README.md index 20e6c6d605..75cc2e3951 100644 --- a/README.md +++ b/README.md @@ -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 ### diff --git a/acorn.js b/acorn.js index 3cbdab358a..6bd667a51c 100644 --- a/acorn.js +++ b/acorn.js @@ -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"); } -}); \ No newline at end of file +}); diff --git a/acorn_loose.js b/acorn_loose.js index b3506b46b5..09fbf210fe 100644 --- a/acorn_loose.js +++ b/acorn_loose.js @@ -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")); diff --git a/bin/update_authors.sh b/bin/update_authors.sh index 466c8db586..a517bc0999 100755 --- a/bin/update_authors.sh +++ b/bin/update_authors.sh @@ -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 diff --git a/bin/without_eval b/bin/without_eval new file mode 100755 index 0000000000..e9ef18f380 --- /dev/null +++ b/bin/without_eval @@ -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); diff --git a/test/driver.js b/test/driver.js index 3b1551092a..a08bf6e837 100644 --- a/test/driver.js +++ b/test/driver.js @@ -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; diff --git a/test/tests-harmony.js b/test/tests-harmony.js index 5bfba14a3a..1a883ee051 100644 --- a/test/tests-harmony.js +++ b/test/tests-harmony.js @@ -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}); diff --git a/test/tests-jsx.js b/test/tests-jsx.js index 6563c1a455..5f61b9edf5 100644 --- a/test/tests-jsx.js +++ b/test/tests-jsx.js @@ -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 }); -} \ No newline at end of file +} diff --git a/test/tests.js b/test/tests.js index 936e73a5fb..4fedc72ca1 100644 --- a/test/tests.js +++ b/test/tests.js @@ -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