Correctly check for-in and for-of loop for invalid left-hand side (#9768)

* Correctly check for-in and for-of loop for invalid left-hand side

* Overwrite with env variable
This commit is contained in:
Daniel Tschinder
2019-03-26 15:32:14 -07:00
committed by GitHub
parent 7f4427432c
commit 6bc9e7ebda
21 changed files with 75 additions and 237 deletions

View File

@@ -519,21 +519,11 @@ export default class StatementParser extends ExpressionParser {
this.parseVar(init, true, kind);
this.finishNode(init, "VariableDeclaration");
if (this.match(tt._in) || this.isContextual("of")) {
if (init.declarations.length === 1) {
const declaration = init.declarations[0];
const isForInInitializer =
kind === "var" &&
declaration.init &&
declaration.id.type != "ObjectPattern" &&
declaration.id.type != "ArrayPattern" &&
!this.isContextual("of");
if (this.state.strict && isForInInitializer) {
this.raise(this.state.start, "for-in initializer in strict mode");
} else if (isForInInitializer || !declaration.init) {
return this.parseForIn(node, init, awaitAt);
}
}
if (
(this.match(tt._in) || this.isContextual("of")) &&
init.declarations.length === 1
) {
return this.parseForIn(node, init, awaitAt);
}
if (awaitAt > -1) {
this.unexpected(awaitAt);
@@ -938,18 +928,36 @@ export default class StatementParser extends ExpressionParser {
parseForIn(
node: N.ForInOf,
init: N.VariableDeclaration,
init: N.VariableDeclaration | N.AssignmentPattern,
awaitAt: number,
): N.ForInOf {
const type = this.match(tt._in) ? "ForInStatement" : "ForOfStatement";
if (awaitAt > -1) {
this.eatContextual("of");
const isForIn = this.match(tt._in);
this.next();
if (isForIn) {
if (awaitAt > -1) this.unexpected(awaitAt);
} else {
this.next();
}
if (type === "ForOfStatement") {
node.await = awaitAt > -1;
}
if (
init.type === "VariableDeclaration" &&
init.declarations[0].init != null &&
(!isForIn ||
this.state.strict ||
init.kind !== "var" ||
init.declarations[0].id.type !== "Identifier")
) {
this.raise(
init.start,
`${
isForIn ? "for-in" : "for-of"
} loop variable declaration may not have an initializer`,
);
} else if (init.type === "AssignmentPattern") {
this.raise(init.start, "Invalid left-hand side in for-loop");
}
node.left = init;
node.right =
type === "ForInStatement"
@@ -969,7 +977,7 @@ export default class StatementParser extends ExpressionParser {
this.scope.exit();
this.state.labels.pop();
return this.finishNode(node, type);
return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement");
}
// Parse a list of variable declarations.

View File

@@ -0,0 +1,3 @@
{
"throws": "Invalid left-hand side in for-loop (2:5)"
}

View File

@@ -1,184 +0,0 @@
{
"type": "File",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 18
}
},
"program": {
"type": "Program",
"start": 0,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 18
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "VariableDeclaration",
"start": 0,
"end": 6,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 6
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 4,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 5
}
},
"id": {
"type": "Identifier",
"start": 4,
"end": 5,
"loc": {
"start": {
"line": 1,
"column": 4
},
"end": {
"line": 1,
"column": 5
},
"identifierName": "a"
},
"name": "a"
},
"init": null
}
],
"kind": "var"
},
{
"type": "ForInStatement",
"start": 7,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 18
}
},
"left": {
"type": "AssignmentPattern",
"start": 12,
"end": 17,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 10
}
},
"left": {
"type": "Identifier",
"start": 12,
"end": 13,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 6
},
"identifierName": "a"
},
"name": "a"
},
"right": {
"type": "NumericLiteral",
"start": 16,
"end": 17,
"loc": {
"start": {
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 10
}
},
"extra": {
"rawValue": 0,
"raw": "0"
},
"value": 0
}
},
"right": {
"type": "ObjectExpression",
"start": 21,
"end": 23,
"loc": {
"start": {
"line": 2,
"column": 14
},
"end": {
"line": 2,
"column": 16
}
},
"properties": []
},
"body": {
"type": "EmptyStatement",
"start": 24,
"end": 25,
"loc": {
"start": {
"line": 2,
"column": 17
},
"end": {
"line": 2,
"column": 18
}
}
}
}
],
"directives": []
}
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Unexpected token, expected \";\" (1:17)"
}
"throws": "for-in loop variable declaration may not have an initializer (1:5)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Unexpected token, expected \";\" (1:15)"
}
"throws": "for-in loop variable declaration may not have an initializer (1:5)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "for-in initializer in strict mode (2:15)"
}
"throws": "for-in loop variable declaration may not have an initializer (2:5)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Unexpected token, expected \";\" (1:17)"
}
"throws": "for-in loop variable declaration may not have an initializer (1:5)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Unexpected token, expected \";\" (1:17)"
}
"throws": "for-in loop variable declaration may not have an initializer (1:5)"
}

View File

@@ -0,0 +1,2 @@
var a;
for (a = 0 of {});

View File

@@ -0,0 +1,3 @@
{
"throws": "Invalid left-hand side in for-loop (2:5)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Unexpected token, expected \";\" (1:16)"
}
"throws": "for-of loop variable declaration may not have an initializer (1:5)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Unexpected token, expected \";\" (1:16)"
}
"throws": "for-in loop variable declaration may not have an initializer (1:5)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Unexpected token, expected \";\" (1:16)"
}
"throws": "for-of loop variable declaration may not have an initializer (1:5)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Unexpected token (2:19)"
}
"throws": "Unexpected token (2:6)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Unexpected token, expected \";\" (1:17)"
}
"throws": "for-of loop variable declaration may not have an initializer (1:5)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Unexpected token, expected \";\" (1:15)"
}
"throws": "for-of loop variable declaration may not have an initializer (1:5)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Unexpected token, expected \";\" (1:15)"
}
"throws": "for-of loop variable declaration may not have an initializer (1:5)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Unexpected token, expected \";\" (1:17)"
}
"throws": "for-in loop variable declaration may not have an initializer (1:5)"
}

View File

@@ -1,3 +1,3 @@
{
"throws": "Unexpected token, expected \";\" (1:15)"
}
"throws": "for-in loop variable declaration may not have an initializer (1:5)"
}

View File

@@ -131,6 +131,14 @@ function runTest(test, parseFunction) {
if (err.message === opts.throws) {
return;
} else {
if (process.env.OVERWRITE) {
const fn = path.dirname(test.expect.loc) + "/options.json";
test.options = test.options || {};
test.options.throws = err.message;
fs.writeFileSync(fn, JSON.stringify(test.options, null, " "));
return;
}
err.message =
"Expected error message: " +
opts.throws +