Skip to content

Commit c8579f8

Browse files
rishipalcopybara-github
authored andcommitted
Report parse error on illegal LHS of += and similar operators.
The code snippet should produce a closure compiler parse error instead of a runtime crash (regardless of optimization mode). ``` for ( ....; .... ; [i,j] += [j, j+1]) { ... } ``` On chrome, this gives: Uncaught SyntaxError: Invalid left-hand side in assignment PiperOrigin-RevId: 498162532
1 parent d0fff58 commit c8579f8

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

src/com/google/javascript/jscomp/parsing/parser/Parser.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2352,6 +2352,14 @@ private ParseTree parseAssignment(Expression expressionIn) {
23522352
}
23532353

23542354
if (peekAssignmentOperator()) {
2355+
if (!peek(TokenType.EQUAL)) {
2356+
// not the vanilla assignment operator `=`, but a special equals operator (`+=`, `-=`,
2357+
// `**=`, etc)
2358+
if (!left.isValidNonVanillaAssignmentTarget()) {
2359+
reportError("invalid assignment target");
2360+
return new MissingPrimaryExpressionTree(getTreeLocation(getTreeStartLocation()));
2361+
}
2362+
}
23552363
left = transformLeftHandSideExpression(left);
23562364
if (!left.isValidAssignmentTarget()) {
23572365
reportError("invalid assignment target");

src/com/google/javascript/jscomp/parsing/parser/trees/ParseTree.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,27 @@ public boolean isPattern() {
216216
}
217217
}
218218

219+
/** Is valid assignment target for non-vanilla assignment operators like `+=`, `-+`, `**=`, etc */
220+
public boolean isValidNonVanillaAssignmentTarget() {
221+
ParseTree parseTree = this;
222+
while (parseTree.type == ParseTreeType.PAREN_EXPRESSION) {
223+
parseTree = parseTree.asParenExpression().expression;
224+
}
225+
switch (parseTree.type) {
226+
case IDENTIFIER_EXPRESSION:
227+
case MEMBER_EXPRESSION:
228+
case MEMBER_LOOKUP_EXPRESSION:
229+
case DEFAULT_PARAMETER:
230+
return true;
231+
case ARRAY_PATTERN:
232+
case OBJECT_PATTERN:
233+
return false;
234+
default:
235+
return false;
236+
}
237+
}
238+
239+
/** Is valid assignment target for any assignment operator like `=`, `+=`, `-+`, `**=`, etc */
219240
public boolean isValidAssignmentTarget() {
220241
ParseTree parseTree = this;
221242
while (parseTree.type == ParseTreeType.PAREN_EXPRESSION) {

test/com/google/javascript/jscomp/parsing/ParserTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3097,6 +3097,25 @@ public void testArrayDestructuringVar() {
30973097
parse("var [x,y] = foo();");
30983098
}
30993099

3100+
@Test
3101+
public void testLHSOfNonVanillaEqualsOperator() {
3102+
strictMode = SLOPPY;
3103+
mode = LanguageMode.ECMASCRIPT_2015;
3104+
3105+
// object pattern or array pattern on the lhs of vanilla equals passes
3106+
parse("for (let [i,j] = [2,0]; j < 2; [i,j] = [j, j+1]) {}");
3107+
parse("for (let [i,j] = [2,0]; j < 2; {i,j} = [j, j+1]) {}");
3108+
3109+
// error with object pattern or array pattern on the lhs of +=
3110+
parseError(
3111+
"for (let [i,j] = [2,0]; j < 2; [i,j] += [j, j+1]) {}", "invalid assignment target");
3112+
parseError(
3113+
"for (let [i,j] = [2,0]; j < 2; {i,j} += [j, j+1]) {}", "invalid assignment target");
3114+
3115+
parse("let [i,j] = [2, 2];");
3116+
parseError("let [i,j] += [2, 2];", "destructuring must have an initializer");
3117+
}
3118+
31003119
@Test
31013120
public void testArrayDestructuringVarInvalid() {
31023121
// arbitrary LHS assignment target not allowed

0 commit comments

Comments
 (0)