diff --git a/acorn.js b/acorn.js index ad2f60905a..3326eab0af 100644 --- a/acorn.js +++ b/acorn.js @@ -51,9 +51,9 @@ var defaultOptions = exports.defaultOptions = { // `ecmaVersion` indicates the ECMAScript version to parse. Must - // be either 3 or 5. This - // influences support for strict mode, the set of reserved words, and - // support for getters and setter. + // be either 3, or 5, or 6. This + // influences support for strict mode, the set of reserved words, + // support for getters and setters and other features. ecmaVersion: 5, // Turn on `strictSemicolons` to prevent the parser from doing // automatic semicolon insertion. @@ -113,6 +113,8 @@ for (var opt in defaultOptions) if (!Object.prototype.hasOwnProperty.call(options, opt)) options[opt] = defaultOptions[opt]; sourceFile = options.sourceFile || null; + + isKeyword = options.ecmaVersion >= 6 ? isEcma6Keyword : isEcma5AndLessKeyword; } // The `getLineInfo` function is mostly useful when the @@ -276,6 +278,7 @@ var _finally = {keyword: "finally"}, _for = {keyword: "for", isLoop: true}, _function = {keyword: "function"}; var _if = {keyword: "if"}, _return = {keyword: "return", beforeExpr: true}, _switch = {keyword: "switch"}; var _throw = {keyword: "throw", beforeExpr: true}, _try = {keyword: "try"}, _var = {keyword: "var"}; + var _let = {keyword: "let"}, _const = {keyword: "const"}; var _while = {keyword: "while", isLoop: true}, _with = {keyword: "with"}, _new = {keyword: "new", beforeExpr: true}; var _this = {keyword: "this"}; @@ -296,7 +299,8 @@ "continue": _continue, "debugger": _debugger, "default": _default, "do": _do, "else": _else, "finally": _finally, "for": _for, "function": _function, "if": _if, "return": _return, "switch": _switch, - "throw": _throw, "try": _try, "var": _var, "while": _while, "with": _with, + "throw": _throw, "try": _try, "var": _var, "let": _let, "const": _const, + "while": _while, "with": _with, "null": _null, "true": _true, "false": _false, "new": _new, "in": _in, "instanceof": {keyword: "instanceof", binop: 7, beforeExpr: true}, "this": _this, "typeof": {keyword: "typeof", prefix: true, beforeExpr: true}, @@ -415,7 +419,13 @@ // And the keywords. - var isKeyword = makePredicate("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"); + var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; + + var isEcma5AndLessKeyword = makePredicate(ecma5AndLessKeywords); + + var isEcma6Keyword = makePredicate(ecma5AndLessKeywords + " let const"); + + var isKeyword = isEcma5AndLessKeyword; // ## Character categories @@ -1207,10 +1217,11 @@ labels.push(loopLabel); expect(_parenL); if (tokType === _semi) return parseFor(node, null); - if (tokType === _var) { + if (tokType === _var || tokType === _let) { + var varKind = tokType.keyword; var init = startNode(); next(); - parseVar(init, true); + parseVar(init, true, varKind); finishNode(init, "VariableDeclaration"); if (init.declarations.length === 1 && eat(_in)) return parseForIn(node, init); @@ -1308,9 +1319,11 @@ raise(node.start, "Missing catch or finally clause"); return finishNode(node, "TryStatement"); + case _const: + case _let: case _var: next(); - parseVar(node); + parseVar(node, false, starttype.keyword); semicolon(); return finishNode(node, "VariableDeclaration"); @@ -1421,15 +1434,15 @@ // Parse a list of variable declarations. - function parseVar(node, noIn) { + function parseVar(node, noIn, kind) { node.declarations = []; - node.kind = "var"; + node.kind = kind; for (;;) { var decl = startNode(); decl.id = parseIdent(); if (strict && isStrictBadIdWord(decl.id.name)) raise(decl.id.start, "Binding " + decl.id.name + " in strict mode"); - decl.init = eat(_eq) ? parseExpression(true, noIn) : null; + decl.init = eat(_eq) ? parseExpression(true, noIn) : (kind === _const.keyword ? unexpected() : null); node.declarations.push(finishNode(decl, "VariableDeclarator")); if (!eat(_comma)) break; } diff --git a/index.html b/index.html index 1f74c47c59..00c0182182 100644 --- a/index.html +++ b/index.html @@ -34,9 +34,9 @@ API, with the caveat that the SpiderMonkey-specific syntax return parseTopLevel(options.program); };
A second optional argument can be given to further configure the parser process. These options are recognized:
var defaultOptions = exports.defaultOptions = {ecmaVersion indicates the ECMAScript version to parse. Must
-be either 3 or 5. This
-influences support for strict mode, the set of reserved words, and
-support for getters and setter.
ecmaVersion: 5,Turn on strictSemicolons to prevent the parser from doing
+be either 3, or 5, or 6. This
+influences support for strict mode, the set of reserved words,
+support for getters and setters and other features.
ecmaVersion: 5,Turn on strictSemicolons to prevent the parser from doing
automatic semicolon insertion.
strictSemicolons: false,When allowTrailingCommas is false, the parser will not allow
trailing commas in array and object literals.
allowTrailingCommas: true,By default, reserved words are not enforced. Enable
forbidReserved to enforce them. When this option has the
@@ -73,6 +73,8 @@ file in every node's loc object.
The getLineInfo function is mostly useful when the
locations option is off (for performance reasons) and you
want to find the line/column position for a given character
@@ -172,6 +174,7 @@ continue jumps to that label.
The keywords that denote values.
var _null = {keyword: "null", atomValue: null}, _true = {keyword: "true", atomValue: true};
var _false = {keyword: "false", atomValue: false};Some keywords are treated as regular operators. in sometimes
@@ -180,7 +183,8 @@ we assign a variable name to it for quick comparing.
The ECMAScript 3 reserved word list.
var isReservedWord3 = makePredicate("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile");ECMAScript 5 reserved words.
var isReservedWord5 = makePredicate("class enum extends super const export import");The additional reserved words in strict mode.
var isStrictReservedWord = makePredicate("implements interface let package private protected public static yield");The forbidden variable names in strict mode.
var isStrictBadIdWord = makePredicate("eval arguments");And the keywords.
var isKeyword = makePredicate("break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this");Big ugly regular expressions that match characters in the + }
The ECMAScript 3 reserved word list.
var isReservedWord3 = makePredicate("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile");ECMAScript 5 reserved words.
var isReservedWord5 = makePredicate("class enum extends super const export import");The additional reserved words in strict mode.
var isStrictReservedWord = makePredicate("implements interface let package private protected public static yield");The forbidden variable names in strict mode.
var isStrictBadIdWord = makePredicate("eval arguments");And the keywords.
var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
+
+ var isEcma5AndLessKeyword = makePredicate(ecma5AndLessKeywords);
+
+ var isEcma6Keyword = makePredicate(ecma5AndLessKeywords + " let const");
+
+ var isKeyword = isEcma5AndLessKeyword;Big ugly regular expressions that match characters in the whitespace, identifier, and identifier-start categories. These are only applied when a character is found to actually have a code point above 128.
var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
@@ -865,10 +875,11 @@ a regular for loop. Parse a list of variable declarations.
function parseVar(node, noIn) {
+ }Parse a list of variable declarations.
function parseVar(node, noIn, kind) {
node.declarations = [];
- node.kind = "var";
+ node.kind = kind;
for (;;) {
var decl = startNode();
decl.id = parseIdent();
if (strict && isStrictBadIdWord(decl.id.name))
raise(decl.id.start, "Binding " + decl.id.name + " in strict mode");
- decl.init = eat(_eq) ? parseExpression(true, noIn) : null;
+ decl.init = eat(_eq) ? parseExpression(true, noIn) : (kind === _const.keyword ? unexpected() : null);
node.declarations.push(finishNode(decl, "VariableDeclarator"));
if (!eat(_comma)) break;
}
diff --git a/test/tests.js b/test/tests.js
index 4bc5b4d65d..0b47ada211 100644
--- a/test/tests.js
+++ b/test/tests.js
@@ -27262,6 +27262,1694 @@ testFail("var this = 10;", "Unexpected token (1:4)");
testFail("throw\n10;", "Illegal newline after throw (1:5)");
+
+// ECMA < 6 mode should work as before
+
+testFail("const a;", "Unexpected token (1:6)");
+
+testFail("let x;", "Unexpected token (1:4)");
+
+testFail("const a = 1;", "Unexpected token (1:6)");
+
+testFail("let a = 1;", "Unexpected token (1:4)");
+
+testFail("for(const x = 0;;);", "Unexpected token (1:10)");
+
+testFail("for(let x = 0;;);", "Unexpected token (1:8)");
+
+test("let++", {
+ type: "Program",
+ start: 0,
+ end: 5,
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 5
+ }
+ },
+ body: [
+ {
+ type: "ExpressionStatement",
+ start: 0,
+ end: 5,
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 5
+ }
+ },
+ expression: {
+ type: "UpdateExpression",
+ start: 0,
+ end: 5,
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 5
+ }
+ },
+ operator: "++",
+ prefix: false,
+ argument: {
+ type: "Identifier",
+ start: 0,
+ end: 3,
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 3
+ }
+ },
+ name: "let"
+ }
+ }
+ }
+ ]
+});
+
+// ECMA 6 support
+
+test("let x", {
+ type: "Program",
+ body: [
+ {
+ type: "VariableDeclaration",
+ declarations: [
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "x",
+ loc: {
+ start: {
+ line: 1,
+ column: 4
+ },
+ end: {
+ line: 1,
+ column: 5
+ }
+ }
+ },
+ init: null,
+ loc: {
+ start: {
+ line: 1,
+ column: 4
+ },
+ end: {
+ line: 1,
+ column: 5
+ }
+ }
+ }
+ ],
+ kind: "let",
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 5
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 5
+ }
+ }
+}, {ecmaVersion: 6, locations: true});
+
+test("let x, y;", {
+ type: "Program",
+ body: [
+ {
+ type: "VariableDeclaration",
+ declarations: [
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "x",
+ loc: {
+ start: {
+ line: 1,
+ column: 4
+ },
+ end: {
+ line: 1,
+ column: 5
+ }
+ }
+ },
+ init: null,
+ loc: {
+ start: {
+ line: 1,
+ column: 4
+ },
+ end: {
+ line: 1,
+ column: 5
+ }
+ }
+ },
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "y",
+ loc: {
+ start: {
+ line: 1,
+ column: 7
+ },
+ end: {
+ line: 1,
+ column: 8
+ }
+ }
+ },
+ init: null,
+ loc: {
+ start: {
+ line: 1,
+ column: 7
+ },
+ end: {
+ line: 1,
+ column: 8
+ }
+ }
+ }
+ ],
+ kind: "let",
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 9
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 9
+ }
+ }
+}, {ecmaVersion: 6, locations: true});
+
+test("let x = 42", {
+ type: "Program",
+ body: [
+ {
+ type: "VariableDeclaration",
+ declarations: [
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "x",
+ loc: {
+ start: {
+ line: 1,
+ column: 4
+ },
+ end: {
+ line: 1,
+ column: 5
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 42,
+ loc: {
+ start: {
+ line: 1,
+ column: 8
+ },
+ end: {
+ line: 1,
+ column: 10
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 4
+ },
+ end: {
+ line: 1,
+ column: 10
+ }
+ }
+ }
+ ],
+ kind: "let",
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 10
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 10
+ }
+ }
+}, {ecmaVersion: 6, locations: true});
+
+test("let eval = 42, arguments = 42", {
+ type: "Program",
+ body: [
+ {
+ type: "VariableDeclaration",
+ declarations: [
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "eval",
+ loc: {
+ start: {
+ line: 1,
+ column: 4
+ },
+ end: {
+ line: 1,
+ column: 8
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 42,
+ loc: {
+ start: {
+ line: 1,
+ column: 11
+ },
+ end: {
+ line: 1,
+ column: 13
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 4
+ },
+ end: {
+ line: 1,
+ column: 13
+ }
+ }
+ },
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "arguments",
+ loc: {
+ start: {
+ line: 1,
+ column: 15
+ },
+ end: {
+ line: 1,
+ column: 24
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 42,
+ loc: {
+ start: {
+ line: 1,
+ column: 27
+ },
+ end: {
+ line: 1,
+ column: 29
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 15
+ },
+ end: {
+ line: 1,
+ column: 29
+ }
+ }
+ }
+ ],
+ kind: "let",
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 29
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 29
+ }
+ }
+}, {ecmaVersion: 6, locations: true});
+
+test("let x = 14, y = 3, z = 1977", {
+ type: "Program",
+ body: [
+ {
+ type: "VariableDeclaration",
+ declarations: [
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "x",
+ loc: {
+ start: {
+ line: 1,
+ column: 4
+ },
+ end: {
+ line: 1,
+ column: 5
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 14,
+ loc: {
+ start: {
+ line: 1,
+ column: 8
+ },
+ end: {
+ line: 1,
+ column: 10
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 4
+ },
+ end: {
+ line: 1,
+ column: 10
+ }
+ }
+ },
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "y",
+ loc: {
+ start: {
+ line: 1,
+ column: 12
+ },
+ end: {
+ line: 1,
+ column: 13
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 3,
+ loc: {
+ start: {
+ line: 1,
+ column: 16
+ },
+ end: {
+ line: 1,
+ column: 17
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 12
+ },
+ end: {
+ line: 1,
+ column: 17
+ }
+ }
+ },
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "z",
+ loc: {
+ start: {
+ line: 1,
+ column: 19
+ },
+ end: {
+ line: 1,
+ column: 20
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 1977,
+ loc: {
+ start: {
+ line: 1,
+ column: 23
+ },
+ end: {
+ line: 1,
+ column: 27
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 19
+ },
+ end: {
+ line: 1,
+ column: 27
+ }
+ }
+ }
+ ],
+ kind: "let",
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 27
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 27
+ }
+ }
+}, {ecmaVersion: 6, locations: true});
+
+test("for(let x = 0;;);", {
+ type: "Program",
+ body: [
+ {
+ type: "ForStatement",
+ init: {
+ type: "VariableDeclaration",
+ declarations: [
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "x",
+ loc: {
+ start: {
+ line: 1,
+ column: 8
+ },
+ end: {
+ line: 1,
+ column: 9
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 0,
+ loc: {
+ start: {
+ line: 1,
+ column: 12
+ },
+ end: {
+ line: 1,
+ column: 13
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 8
+ },
+ end: {
+ line: 1,
+ column: 13
+ }
+ }
+ }
+ ],
+ kind: "let",
+ loc: {
+ start: {
+ line: 1,
+ column: 4
+ },
+ end: {
+ line: 1,
+ column: 13
+ }
+ }
+ },
+ test: null,
+ update: null,
+ body: {
+ type: "EmptyStatement",
+ loc: {
+ start: {
+ line: 1,
+ column: 16
+ },
+ end: {
+ line: 1,
+ column: 17
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 17
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 17
+ }
+ }
+}, {ecmaVersion: 6, locations: true});
+
+test("for(let x = 0, y = 1;;);", {
+ type: "Program",
+ body: [
+ {
+ type: "ForStatement",
+ init: {
+ type: "VariableDeclaration",
+ declarations: [
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "x",
+ loc: {
+ start: {
+ line: 1,
+ column: 8
+ },
+ end: {
+ line: 1,
+ column: 9
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 0,
+ loc: {
+ start: {
+ line: 1,
+ column: 12
+ },
+ end: {
+ line: 1,
+ column: 13
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 8
+ },
+ end: {
+ line: 1,
+ column: 13
+ }
+ }
+ },
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "y",
+ loc: {
+ start: {
+ line: 1,
+ column: 15
+ },
+ end: {
+ line: 1,
+ column: 16
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 1,
+ loc: {
+ start: {
+ line: 1,
+ column: 19
+ },
+ end: {
+ line: 1,
+ column: 20
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 15
+ },
+ end: {
+ line: 1,
+ column: 20
+ }
+ }
+ }
+ ],
+ kind: "let",
+ loc: {
+ start: {
+ line: 1,
+ column: 4
+ },
+ end: {
+ line: 1,
+ column: 20
+ }
+ }
+ },
+ test: null,
+ update: null,
+ body: {
+ type: "EmptyStatement",
+ loc: {
+ start: {
+ line: 1,
+ column: 23
+ },
+ end: {
+ line: 1,
+ column: 24
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 24
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 24
+ }
+ }
+}, {ecmaVersion: 6, locations: true});
+
+test("for (let x in list) process(x);", {
+ type: "Program",
+ body: [
+ {
+ type: "ForInStatement",
+ left: {
+ type: "VariableDeclaration",
+ declarations: [
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "x",
+ loc: {
+ start: {
+ line: 1,
+ column: 9
+ },
+ end: {
+ line: 1,
+ column: 10
+ }
+ }
+ },
+ init: null,
+ loc: {
+ start: {
+ line: 1,
+ column: 9
+ },
+ end: {
+ line: 1,
+ column: 10
+ }
+ }
+ }
+ ],
+ kind: "let",
+ loc: {
+ start: {
+ line: 1,
+ column: 5
+ },
+ end: {
+ line: 1,
+ column: 10
+ }
+ }
+ },
+ right: {
+ type: "Identifier",
+ name: "list",
+ loc: {
+ start: {
+ line: 1,
+ column: 14
+ },
+ end: {
+ line: 1,
+ column: 18
+ }
+ }
+ },
+ body: {
+ type: "ExpressionStatement",
+ expression: {
+ type: "CallExpression",
+ callee: {
+ type: "Identifier",
+ name: "process",
+ loc: {
+ start: {
+ line: 1,
+ column: 20
+ },
+ end: {
+ line: 1,
+ column: 27
+ }
+ }
+ },
+ arguments: [
+ {
+ type: "Identifier",
+ name: "x",
+ loc: {
+ start: {
+ line: 1,
+ column: 28
+ },
+ end: {
+ line: 1,
+ column: 29
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 20
+ },
+ end: {
+ line: 1,
+ column: 30
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 20
+ },
+ end: {
+ line: 1,
+ column: 31
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 31
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 31
+ }
+ }
+}, {ecmaVersion: 6, locations: true});
+
+test("for (let x = 42 in list) process(x);", {
+ type: "Program",
+ body: [
+ {
+ type: "ForInStatement",
+ left: {
+ type: "VariableDeclaration",
+ declarations: [
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "x",
+ loc: {
+ start: {
+ line: 1,
+ column: 9
+ },
+ end: {
+ line: 1,
+ column: 10
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 42,
+ loc: {
+ start: {
+ line: 1,
+ column: 13
+ },
+ end: {
+ line: 1,
+ column: 15
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 9
+ },
+ end: {
+ line: 1,
+ column: 15
+ }
+ }
+ }
+ ],
+ kind: "let",
+ loc: {
+ start: {
+ line: 1,
+ column: 5
+ },
+ end: {
+ line: 1,
+ column: 15
+ }
+ }
+ },
+ right: {
+ type: "Identifier",
+ name: "list",
+ loc: {
+ start: {
+ line: 1,
+ column: 19
+ },
+ end: {
+ line: 1,
+ column: 23
+ }
+ }
+ },
+ body: {
+ type: "ExpressionStatement",
+ expression: {
+ type: "CallExpression",
+ callee: {
+ type: "Identifier",
+ name: "process",
+ loc: {
+ start: {
+ line: 1,
+ column: 25
+ },
+ end: {
+ line: 1,
+ column: 32
+ }
+ }
+ },
+ arguments: [
+ {
+ type: "Identifier",
+ name: "x",
+ loc: {
+ start: {
+ line: 1,
+ column: 33
+ },
+ end: {
+ line: 1,
+ column: 34
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 25
+ },
+ end: {
+ line: 1,
+ column: 35
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 25
+ },
+ end: {
+ line: 1,
+ column: 36
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 36
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 36
+ }
+ }
+}, {ecmaVersion: 6, locations: true});
+
+test("for (let i = function() { return 10 in [] } in list) process(x);", {
+ type: "Program",
+ body: [
+ {
+ type: "ForInStatement",
+ left: {
+ type: "VariableDeclaration",
+ declarations: [
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "i",
+ loc: {
+ start: {
+ line: 1,
+ column: 9
+ },
+ end: {
+ line: 1,
+ column: 10
+ }
+ }
+ },
+ init: {
+ type: "FunctionExpression",
+ id: null,
+ params: [],
+ body: {
+ type: "BlockStatement",
+ body: [
+ {
+ type: "ReturnStatement",
+ argument: {
+ type: "BinaryExpression",
+ left: {
+ type: "Literal",
+ value: 10,
+ loc: {
+ start: {
+ line: 1,
+ column: 33
+ },
+ end: {
+ line: 1,
+ column: 35
+ }
+ }
+ },
+ operator: "in",
+ right: {
+ type: "ArrayExpression",
+ elements: [],
+ loc: {
+ start: {
+ line: 1,
+ column: 39
+ },
+ end: {
+ line: 1,
+ column: 41
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 33
+ },
+ end: {
+ line: 1,
+ column: 41
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 26
+ },
+ end: {
+ line: 1,
+ column: 41
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 24
+ },
+ end: {
+ line: 1,
+ column: 43
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 13
+ },
+ end: {
+ line: 1,
+ column: 43
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 9
+ },
+ end: {
+ line: 1,
+ column: 43
+ }
+ }
+ }
+ ],
+ kind: "let",
+ loc: {
+ start: {
+ line: 1,
+ column: 5
+ },
+ end: {
+ line: 1,
+ column: 43
+ }
+ }
+ },
+ right: {
+ type: "Identifier",
+ name: "list",
+ loc: {
+ start: {
+ line: 1,
+ column: 47
+ },
+ end: {
+ line: 1,
+ column: 51
+ }
+ }
+ },
+ body: {
+ type: "ExpressionStatement",
+ expression: {
+ type: "CallExpression",
+ callee: {
+ type: "Identifier",
+ name: "process",
+ loc: {
+ start: {
+ line: 1,
+ column: 53
+ },
+ end: {
+ line: 1,
+ column: 60
+ }
+ }
+ },
+ arguments: [
+ {
+ type: "Identifier",
+ name: "x",
+ loc: {
+ start: {
+ line: 1,
+ column: 61
+ },
+ end: {
+ line: 1,
+ column: 62
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 53
+ },
+ end: {
+ line: 1,
+ column: 63
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 53
+ },
+ end: {
+ line: 1,
+ column: 64
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 64
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 64
+ }
+ }
+}, {ecmaVersion: 6, locations: true});
+
+test("const x = 42", {
+ type: "Program",
+ body: [
+ {
+ type: "VariableDeclaration",
+ declarations: [
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "x",
+ loc: {
+ start: {
+ line: 1,
+ column: 6
+ },
+ end: {
+ line: 1,
+ column: 7
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 42,
+ loc: {
+ start: {
+ line: 1,
+ column: 10
+ },
+ end: {
+ line: 1,
+ column: 12
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 6
+ },
+ end: {
+ line: 1,
+ column: 12
+ }
+ }
+ }
+ ],
+ kind: "const",
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 12
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 12
+ }
+ }
+}, {ecmaVersion: 6, locations: true});
+
+test("const eval = 42, arguments = 42", {
+ type: "Program",
+ body: [
+ {
+ type: "VariableDeclaration",
+ declarations: [
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "eval",
+ loc: {
+ start: {
+ line: 1,
+ column: 6
+ },
+ end: {
+ line: 1,
+ column: 10
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 42,
+ loc: {
+ start: {
+ line: 1,
+ column: 13
+ },
+ end: {
+ line: 1,
+ column: 15
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 6
+ },
+ end: {
+ line: 1,
+ column: 15
+ }
+ }
+ },
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "arguments",
+ loc: {
+ start: {
+ line: 1,
+ column: 17
+ },
+ end: {
+ line: 1,
+ column: 26
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 42,
+ loc: {
+ start: {
+ line: 1,
+ column: 29
+ },
+ end: {
+ line: 1,
+ column: 31
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 17
+ },
+ end: {
+ line: 1,
+ column: 31
+ }
+ }
+ }
+ ],
+ kind: "const",
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 31
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 31
+ }
+ }
+}, {ecmaVersion: 6, locations: true});
+
+test("const x = 14, y = 3, z = 1977", {
+ type: "Program",
+ body: [
+ {
+ type: "VariableDeclaration",
+ declarations: [
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "x",
+ loc: {
+ start: {
+ line: 1,
+ column: 6
+ },
+ end: {
+ line: 1,
+ column: 7
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 14,
+ loc: {
+ start: {
+ line: 1,
+ column: 10
+ },
+ end: {
+ line: 1,
+ column: 12
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 6
+ },
+ end: {
+ line: 1,
+ column: 12
+ }
+ }
+ },
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "y",
+ loc: {
+ start: {
+ line: 1,
+ column: 14
+ },
+ end: {
+ line: 1,
+ column: 15
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 3,
+ loc: {
+ start: {
+ line: 1,
+ column: 18
+ },
+ end: {
+ line: 1,
+ column: 19
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 14
+ },
+ end: {
+ line: 1,
+ column: 19
+ }
+ }
+ },
+ {
+ type: "VariableDeclarator",
+ id: {
+ type: "Identifier",
+ name: "z",
+ loc: {
+ start: {
+ line: 1,
+ column: 21
+ },
+ end: {
+ line: 1,
+ column: 22
+ }
+ }
+ },
+ init: {
+ type: "Literal",
+ value: 1977,
+ loc: {
+ start: {
+ line: 1,
+ column: 25
+ },
+ end: {
+ line: 1,
+ column: 29
+ }
+ }
+ },
+ loc: {
+ start: {
+ line: 1,
+ column: 21
+ },
+ end: {
+ line: 1,
+ column: 29
+ }
+ }
+ }
+ ],
+ kind: "const",
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 29
+ }
+ }
+ }
+ ],
+ loc: {
+ start: {
+ line: 1,
+ column: 0
+ },
+ end: {
+ line: 1,
+ column: 29
+ }
+ }
+}, {ecmaVersion: 6, locations: true});
+
+testFail("const a;", "Unexpected token (1:7)", {ecmaVersion: 6});
+
+testFail("for(const x = 0;;);", "Unexpected token (1:4)", {ecmaVersion: 6});
+
// Assertion Tests
(function() {
var actualComments = [],