Fix Unexpected "Invalid left-hand side in for-in" error
Fixes #1920
Fixes #1944
Closes gh-1993
diff --git a/src/parser.ts b/src/parser.ts
index 417df38..900e68c 100644
--- a/src/parser.ts
+++ b/src/parser.ts
@@ -2322,6 +2322,10 @@
}
} else {
const initStartToken = this.lookahead;
+ const previousIsBindingElement = this.context.isBindingElement;
+ const previousIsAssignmentTarget = this.context.isAssignmentTarget;
+ const previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError;
+
const previousAllowIn = this.context.allowIn;
this.context.allowIn = false;
init = this.inheritCoverGrammar(this.parseAssignmentExpression);
@@ -2349,6 +2353,11 @@
init = null;
forIn = false;
} else {
+ // The `init` node was not parsed isolated, but we would have wanted it to.
+ this.context.isBindingElement = previousIsBindingElement;
+ this.context.isAssignmentTarget = previousIsAssignmentTarget;
+ this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError;
+
if (this.match(',')) {
const initSeq = [init];
while (this.match(',')) {
@@ -2364,11 +2373,11 @@
if (typeof left === 'undefined') {
if (!this.match(';')) {
- test = this.parseExpression();
+ test = this.isolateCoverGrammar(this.parseExpression);
}
this.expect(';');
if (!this.match(')')) {
- update = this.parseExpression();
+ update = this.isolateCoverGrammar(this.parseExpression);
}
}
diff --git a/test/fixtures/statement/if/else-declaration-following-classic-for.js b/test/fixtures/statement/if/else-declaration-following-classic-for.js
new file mode 100644
index 0000000..4cc3f8c
--- /dev/null
+++ b/test/fixtures/statement/if/else-declaration-following-classic-for.js
@@ -0,0 +1,6 @@
+if (true)
+ for (1;;)
+ 1;
+else
+ for (x of y)
+ 2;
diff --git a/test/fixtures/statement/if/else-declaration-following-classic-for.tree.json b/test/fixtures/statement/if/else-declaration-following-classic-for.tree.json
new file mode 100644
index 0000000..e8ff223
--- /dev/null
+++ b/test/fixtures/statement/if/else-declaration-following-classic-for.tree.json
@@ -0,0 +1,599 @@
+{
+ "type": "Program",
+ "body": [
+ {
+ "type": "IfStatement",
+ "test": {
+ "type": "Literal",
+ "value": true,
+ "raw": "true",
+ "range": [
+ 4,
+ 8
+ ],
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 4
+ },
+ "end": {
+ "line": 1,
+ "column": 8
+ }
+ }
+ },
+ "consequent": {
+ "type": "ForStatement",
+ "init": {
+ "type": "Literal",
+ "value": 1,
+ "raw": "1",
+ "range": [
+ 19,
+ 20
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ "test": null,
+ "update": null,
+ "body": {
+ "type": "ExpressionStatement",
+ "expression": {
+ "type": "Literal",
+ "value": 1,
+ "raw": "1",
+ "range": [
+ 32,
+ 33
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 8
+ },
+ "end": {
+ "line": 3,
+ "column": 9
+ }
+ }
+ },
+ "range": [
+ 32,
+ 34
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 8
+ },
+ "end": {
+ "line": 3,
+ "column": 10
+ }
+ }
+ },
+ "range": [
+ 14,
+ 34
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 4
+ },
+ "end": {
+ "line": 3,
+ "column": 10
+ }
+ }
+ },
+ "alternate": {
+ "type": "ForOfStatement",
+ "left": {
+ "type": "Identifier",
+ "name": "x",
+ "range": [
+ 49,
+ 50
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 9
+ },
+ "end": {
+ "line": 5,
+ "column": 10
+ }
+ }
+ },
+ "right": {
+ "type": "Identifier",
+ "name": "y",
+ "range": [
+ 54,
+ 55
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 14
+ },
+ "end": {
+ "line": 5,
+ "column": 15
+ }
+ }
+ },
+ "body": {
+ "type": "ExpressionStatement",
+ "expression": {
+ "type": "Literal",
+ "value": 2,
+ "raw": "2",
+ "range": [
+ 65,
+ 66
+ ],
+ "loc": {
+ "start": {
+ "line": 6,
+ "column": 8
+ },
+ "end": {
+ "line": 6,
+ "column": 9
+ }
+ }
+ },
+ "range": [
+ 65,
+ 67
+ ],
+ "loc": {
+ "start": {
+ "line": 6,
+ "column": 8
+ },
+ "end": {
+ "line": 6,
+ "column": 10
+ }
+ }
+ },
+ "range": [
+ 44,
+ 67
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 4
+ },
+ "end": {
+ "line": 6,
+ "column": 10
+ }
+ }
+ },
+ "range": [
+ 0,
+ 67
+ ],
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 0
+ },
+ "end": {
+ "line": 6,
+ "column": 10
+ }
+ }
+ }
+ ],
+ "sourceType": "script",
+ "range": [
+ 0,
+ 67
+ ],
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 0
+ },
+ "end": {
+ "line": 6,
+ "column": 10
+ }
+ },
+ "tokens": [
+ {
+ "type": "Keyword",
+ "value": "if",
+ "range": [
+ 0,
+ 2
+ ],
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 0
+ },
+ "end": {
+ "line": 1,
+ "column": 2
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "(",
+ "range": [
+ 3,
+ 4
+ ],
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 3
+ },
+ "end": {
+ "line": 1,
+ "column": 4
+ }
+ }
+ },
+ {
+ "type": "Boolean",
+ "value": "true",
+ "range": [
+ 4,
+ 8
+ ],
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 4
+ },
+ "end": {
+ "line": 1,
+ "column": 8
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ")",
+ "range": [
+ 8,
+ 9
+ ],
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 8
+ },
+ "end": {
+ "line": 1,
+ "column": 9
+ }
+ }
+ },
+ {
+ "type": "Keyword",
+ "value": "for",
+ "range": [
+ 14,
+ 17
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 4
+ },
+ "end": {
+ "line": 2,
+ "column": 7
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "(",
+ "range": [
+ 18,
+ 19
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 8
+ },
+ "end": {
+ "line": 2,
+ "column": 9
+ }
+ }
+ },
+ {
+ "type": "Numeric",
+ "value": "1",
+ "range": [
+ 19,
+ 20
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 9
+ },
+ "end": {
+ "line": 2,
+ "column": 10
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ";",
+ "range": [
+ 20,
+ 21
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 10
+ },
+ "end": {
+ "line": 2,
+ "column": 11
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ";",
+ "range": [
+ 21,
+ 22
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 11
+ },
+ "end": {
+ "line": 2,
+ "column": 12
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ")",
+ "range": [
+ 22,
+ 23
+ ],
+ "loc": {
+ "start": {
+ "line": 2,
+ "column": 12
+ },
+ "end": {
+ "line": 2,
+ "column": 13
+ }
+ }
+ },
+ {
+ "type": "Numeric",
+ "value": "1",
+ "range": [
+ 32,
+ 33
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 8
+ },
+ "end": {
+ "line": 3,
+ "column": 9
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ";",
+ "range": [
+ 33,
+ 34
+ ],
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 9
+ },
+ "end": {
+ "line": 3,
+ "column": 10
+ }
+ }
+ },
+ {
+ "type": "Keyword",
+ "value": "else",
+ "range": [
+ 35,
+ 39
+ ],
+ "loc": {
+ "start": {
+ "line": 4,
+ "column": 0
+ },
+ "end": {
+ "line": 4,
+ "column": 4
+ }
+ }
+ },
+ {
+ "type": "Keyword",
+ "value": "for",
+ "range": [
+ 44,
+ 47
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 4
+ },
+ "end": {
+ "line": 5,
+ "column": 7
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": "(",
+ "range": [
+ 48,
+ 49
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 8
+ },
+ "end": {
+ "line": 5,
+ "column": 9
+ }
+ }
+ },
+ {
+ "type": "Identifier",
+ "value": "x",
+ "range": [
+ 49,
+ 50
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 9
+ },
+ "end": {
+ "line": 5,
+ "column": 10
+ }
+ }
+ },
+ {
+ "type": "Identifier",
+ "value": "of",
+ "range": [
+ 51,
+ 53
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 11
+ },
+ "end": {
+ "line": 5,
+ "column": 13
+ }
+ }
+ },
+ {
+ "type": "Identifier",
+ "value": "y",
+ "range": [
+ 54,
+ 55
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 14
+ },
+ "end": {
+ "line": 5,
+ "column": 15
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ")",
+ "range": [
+ 55,
+ 56
+ ],
+ "loc": {
+ "start": {
+ "line": 5,
+ "column": 15
+ },
+ "end": {
+ "line": 5,
+ "column": 16
+ }
+ }
+ },
+ {
+ "type": "Numeric",
+ "value": "2",
+ "range": [
+ 65,
+ 66
+ ],
+ "loc": {
+ "start": {
+ "line": 6,
+ "column": 8
+ },
+ "end": {
+ "line": 6,
+ "column": 9
+ }
+ }
+ },
+ {
+ "type": "Punctuator",
+ "value": ";",
+ "range": [
+ 66,
+ 67
+ ],
+ "loc": {
+ "start": {
+ "line": 6,
+ "column": 9
+ },
+ "end": {
+ "line": 6,
+ "column": 10
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file