Added for (..of..) support and guard against for (let var=.. in|of ..) loops.
This commit is contained in:
parent
8b0be7cec9
commit
648f3159cc
32
acorn.js
32
acorn.js
@ -298,6 +298,7 @@
|
||||
// we assign a variable name to it for quick comparing.
|
||||
|
||||
var _in = {keyword: "in", binop: 7, beforeExpr: true};
|
||||
var _of = {keyword: "of", beforeExpr: true};
|
||||
|
||||
// Map keyword names to token types.
|
||||
|
||||
@ -312,7 +313,7 @@
|
||||
"typeof": {keyword: "typeof", prefix: true, beforeExpr: true},
|
||||
"void": {keyword: "void", prefix: true, beforeExpr: true},
|
||||
"delete": {keyword: "delete", prefix: true, beforeExpr: true},
|
||||
"class": _class, "extends": _extends, "static": _static};
|
||||
"class": _class, "extends": _extends, "static": _static, "of": _of};
|
||||
|
||||
// Punctuation token types. Again, the `type` property is purely for debugging.
|
||||
|
||||
@ -431,7 +432,7 @@
|
||||
|
||||
var isEcma5AndLessKeyword = makePredicate(ecma5AndLessKeywords);
|
||||
|
||||
var isEcma6Keyword = makePredicate(ecma5AndLessKeywords + " let const class extends static");
|
||||
var isEcma6Keyword = makePredicate(ecma5AndLessKeywords + " let const class extends static of");
|
||||
|
||||
var isKeyword = isEcma5AndLessKeyword;
|
||||
|
||||
@ -1300,13 +1301,13 @@
|
||||
return finishNode(node, "DoWhileStatement");
|
||||
}
|
||||
|
||||
// Disambiguating between a `for` and a `for`/`in` loop is
|
||||
// non-trivial. Basically, we have to parse the init `var`
|
||||
// Disambiguating between a `for` and a `for`/`in` or `for`/`of`
|
||||
// loop is non-trivial. Basically, we have to parse the init `var`
|
||||
// statement or expression, disallowing the `in` operator (see
|
||||
// the second parameter to `parseExpression`), and then check
|
||||
// whether the next token is `in`. When there is no init part
|
||||
// (semicolon immediately after the opening parenthesis), it is
|
||||
// a regular `for` loop.
|
||||
// whether the next token is `in` or `of`. When there is no init
|
||||
// part (semicolon immediately after the opening parenthesis), it
|
||||
// is a regular `for` loop.
|
||||
|
||||
function parseForStatement(node) {
|
||||
next();
|
||||
@ -1314,16 +1315,20 @@
|
||||
expect(_parenL);
|
||||
if (tokType === _semi) return parseFor(node, null);
|
||||
if (tokType === _var || tokType === _let) {
|
||||
var init = startNode(), varKind = tokType.keyword;
|
||||
var init = startNode(), varKind = tokType.keyword, isLet = tokType === _let;
|
||||
next();
|
||||
parseVar(init, true, varKind);
|
||||
finishNode(init, "VariableDeclaration");
|
||||
if (init.declarations.length === 1 && eat(_in))
|
||||
if ((tokType === _in || tokType === _of) && init.declarations.length === 1 &&
|
||||
!(isLet && init.declarations[0].init))
|
||||
return parseForIn(node, init);
|
||||
return parseFor(node, init);
|
||||
}
|
||||
var init = parseExpression(false, true);
|
||||
if (eat(_in)) {checkLVal(init); return parseForIn(node, init);}
|
||||
if (tokType === _in || tokType === _of) {
|
||||
checkLVal(init);
|
||||
return parseForIn(node, init);
|
||||
}
|
||||
return parseFor(node, init);
|
||||
}
|
||||
|
||||
@ -1514,15 +1519,18 @@
|
||||
return finishNode(node, "ForStatement");
|
||||
}
|
||||
|
||||
// Parse a `for`/`in` loop.
|
||||
// Parse a `for`/`in` and `for`/`of` loop, which are almost
|
||||
// same from parser's perspective.
|
||||
|
||||
function parseForIn(node, init) {
|
||||
var type = tokType === _in ? "ForInStatement" : "ForOfStatement";
|
||||
next();
|
||||
node.left = init;
|
||||
node.right = parseExpression();
|
||||
expect(_parenR);
|
||||
node.body = parseStatement();
|
||||
labels.pop();
|
||||
return finishNode(node, "ForInStatement");
|
||||
return finishNode(node, type);
|
||||
}
|
||||
|
||||
// Parse a list of variable declarations.
|
||||
|
||||
@ -15899,9 +15899,9 @@ testFail("({ obj:20 }) = 42", "Unexpected token (1:7)", {ecmaVersion: 6});
|
||||
|
||||
testFail("( { get x() {} } ) = 0", "Unexpected token (1:8)", {ecmaVersion: 6});
|
||||
|
||||
testFail("x \n is y", "Unexpected token (2:5)", {ecmaVersion: 6});
|
||||
testFail("x \n is y", "Unexpected token (2:4)", {ecmaVersion: 6});
|
||||
|
||||
testFail("x \n isnt y", "Unexpected token (2:7)", {ecmaVersion: 6});
|
||||
testFail("x \n isnt y", "Unexpected token (2:6)", {ecmaVersion: 6});
|
||||
|
||||
testFail("function default() {}", "Unexpected token (1:9)", {ecmaVersion: 6});
|
||||
|
||||
@ -15921,11 +15921,11 @@ testFail("\"use strict\"; ({ v: eval }) = obj", "Assigning to eval in strict mod
|
||||
|
||||
testFail("\"use strict\"; ({ v: arguments }) = obj", "Assigning to arguments in strict mode (1:20)", {ecmaVersion: 6});
|
||||
|
||||
testFail("for (var i = function() { return 10 in [] } in list) process(x);", "Unexpected token (1:45)", {ecmaVersion: 6});
|
||||
testFail("for (var i = function() { return 10 in [] } in list) process(x);", "Unexpected token (1:44)", {ecmaVersion: 6});
|
||||
|
||||
testFail("for (let x = 42 in list) process(x);", "Unexpected token (1:17)", {ecmaVersion: 6});
|
||||
testFail("for (let x = 42 in list) process(x);", "Unexpected token (1:16)", {ecmaVersion: 6});
|
||||
|
||||
testFail("for (let x = 42 of list) process(x);", "Unexpected token (1:17)", {ecmaVersion: 6});
|
||||
testFail("for (let x = 42 of list) process(x);", "Unexpected token (1:16)", {ecmaVersion: 6});
|
||||
|
||||
testFail("module\n\"crypto\" {}", "Unexpected token (1:7)", {ecmaVersion: 6});
|
||||
|
||||
|
||||
383
test/tests.js
383
test/tests.js
@ -28221,389 +28221,6 @@ test("for (let x in list) process(x);", {
|
||||
}
|
||||
}, {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: [
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user