Skip to content

Commit

Permalink
Correctly check for-in and for-of loop for invalid left-hand side (#9768
Browse files Browse the repository at this point in the history
)

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

* Overwrite with env variable
  • Loading branch information
danez committed Mar 26, 2019
1 parent 7f44274 commit 6bc9e7e
Show file tree
Hide file tree
Showing 21 changed files with 75 additions and 237 deletions.
54 changes: 31 additions & 23 deletions packages/babel-parser/src/parser/statement.js
Expand Up @@ -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);
Expand Down Expand Up @@ -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"
Expand All @@ -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.
Expand Down
@@ -0,0 +1,3 @@
{
"throws": "Invalid left-hand side in for-loop (2:5)"
}

This file was deleted.

@@ -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)"
}
@@ -0,0 +1,2 @@
var a;
for (a = 0 of {});
@@ -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)"
}
8 changes: 8 additions & 0 deletions packages/babel-parser/test/helpers/runFixtureTests.js
Expand Up @@ -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 +
Expand Down
2 changes: 0 additions & 2 deletions scripts/tests/test262/test262_whitelist.txt
@@ -1,5 +1,3 @@
annexB/language/statements/for-in/bare-initializer.js(default)
annexB/language/statements/for-in/bare-initializer.js(strict mode)
built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_F-negated.js(default)
built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_F-negated.js(strict mode)
built-ins/RegExp/property-escapes/binary-property-with-value-ASCII_-_F.js(default)
Expand Down

0 comments on commit 6bc9e7e

Please sign in to comment.