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:
@@ -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.
|
||||
|
||||
3
packages/babel-parser/test/fixtures/es2015/for-in/bare-initializer/options.json
vendored
Normal file
3
packages/babel-parser/test/fixtures/es2015/for-in/bare-initializer/options.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Invalid left-hand side in for-loop (2:5)"
|
||||
}
|
||||
@@ -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": []
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token, expected \";\" (1:17)"
|
||||
}
|
||||
"throws": "for-in loop variable declaration may not have an initializer (1:5)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token, expected \";\" (1:15)"
|
||||
}
|
||||
"throws": "for-in loop variable declaration may not have an initializer (1:5)"
|
||||
}
|
||||
@@ -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)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token, expected \";\" (1:17)"
|
||||
}
|
||||
"throws": "for-in loop variable declaration may not have an initializer (1:5)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token, expected \";\" (1:17)"
|
||||
}
|
||||
"throws": "for-in loop variable declaration may not have an initializer (1:5)"
|
||||
}
|
||||
2
packages/babel-parser/test/fixtures/es2015/for-of/bare-initializer/input.js
vendored
Normal file
2
packages/babel-parser/test/fixtures/es2015/for-of/bare-initializer/input.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
var a;
|
||||
for (a = 0 of {});
|
||||
3
packages/babel-parser/test/fixtures/es2015/for-of/bare-initializer/options.json
vendored
Normal file
3
packages/babel-parser/test/fixtures/es2015/for-of/bare-initializer/options.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"throws": "Invalid left-hand side in for-loop (2:5)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token, expected \";\" (1:16)"
|
||||
}
|
||||
"throws": "for-of loop variable declaration may not have an initializer (1:5)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token, expected \";\" (1:16)"
|
||||
}
|
||||
"throws": "for-in loop variable declaration may not have an initializer (1:5)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token, expected \";\" (1:16)"
|
||||
}
|
||||
"throws": "for-of loop variable declaration may not have an initializer (1:5)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token (2:19)"
|
||||
}
|
||||
"throws": "Unexpected token (2:6)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token, expected \";\" (1:17)"
|
||||
}
|
||||
"throws": "for-of loop variable declaration may not have an initializer (1:5)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token, expected \";\" (1:15)"
|
||||
}
|
||||
"throws": "for-of loop variable declaration may not have an initializer (1:5)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token, expected \";\" (1:15)"
|
||||
}
|
||||
"throws": "for-of loop variable declaration may not have an initializer (1:5)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token, expected \";\" (1:17)"
|
||||
}
|
||||
"throws": "for-in loop variable declaration may not have an initializer (1:5)"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"throws": "Unexpected token, expected \";\" (1:15)"
|
||||
}
|
||||
"throws": "for-in loop variable declaration may not have an initializer (1:5)"
|
||||
}
|
||||
@@ -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 +
|
||||
|
||||
Reference in New Issue
Block a user