Skip to content

Commit

Permalink
invalid left-hand assignments based on parenthesis
Browse files Browse the repository at this point in the history
  • Loading branch information
boweihan committed Oct 19, 2019
1 parent d12d61d commit 7e158a1
Show file tree
Hide file tree
Showing 32 changed files with 328 additions and 129 deletions.
20 changes: 3 additions & 17 deletions packages/babel-parser/src/parser/expression.js
Expand Up @@ -201,22 +201,9 @@ export default class ExpressionParser extends LValParser {
if (operator === "||=" || operator === "&&=") {
this.expectPlugin("logicalAssignment");
}

if (this.match(tt.eq)) {
// assignment expressions must be children of non-parenthesized ArrayExpression or ObjectExpression
const allowAssign =
left.type === "ArrayExpression" || left.type === "ObjectExpression";

node.left = this.toAssignable(
left,
undefined,
"assignment expression",
allowAssign,
);
} else {
node.left = left;
}

node.left = this.match(tt.eq)
? this.toAssignable(left, undefined, "assignment expression")
: left;
refShorthandDefaultPos.start = 0; // reset because shorthand default was used correctly

this.checkLVal(left, undefined, undefined, "assignment expression");
Expand Down Expand Up @@ -1913,7 +1900,6 @@ export default class ExpressionParser extends LValParser {
true,
"arrow function parameters",
trailingCommaPos,
true,
);
}

Expand Down
48 changes: 13 additions & 35 deletions packages/babel-parser/src/parser/lval.js
Expand Up @@ -42,12 +42,15 @@ export default class LValParser extends NodeUtils {
node: Node,
isBinding: ?boolean,
contextDescription: string,
allowAssign: boolean,
): Node {
if (node) {
if (node.extra && node.extra.parenthesized) {
// any nested parenthensis invalidates left-hand assignment patterns
allowAssign = false;
if (
node.extra &&
node.extra.parenthesized &&
node.type !== "Identifier" &&
node.type !== "MemberExpression"
) {
this.raise(node.start, "Invalid parenthesized assignment pattern");
}
switch (node.type) {
case "Identifier":
Expand All @@ -65,12 +68,7 @@ export default class LValParser extends NodeUtils {
) {
const prop = node.properties[i];
const isLast = i === last;
this.toAssignableObjectExpressionProp(
prop,
isBinding,
isLast,
allowAssign,
);
this.toAssignableObjectExpressionProp(prop, isBinding, isLast);

if (
isLast &&
Expand All @@ -83,20 +81,15 @@ export default class LValParser extends NodeUtils {
break;

case "ObjectProperty":
this.toAssignable(
node.value,
isBinding,
contextDescription,
allowAssign,
);
this.toAssignable(node.value, isBinding, contextDescription);
break;

case "SpreadElement": {
this.checkToRestConversion(node);

node.type = "RestElement";
const arg = node.argument;
this.toAssignable(arg, isBinding, contextDescription, allowAssign);
this.toAssignable(arg, isBinding, contextDescription);
break;
}

Expand All @@ -107,18 +100,11 @@ export default class LValParser extends NodeUtils {
isBinding,
contextDescription,
node.extra?.trailingComma,
allowAssign,
);
break;

case "AssignmentExpression":
if (node.operator === "=") {
if (!allowAssign) {
this.raise(
node.left.end,
"Invalid assignment pattern in left-hand side of expression",
);
}
node.type = "AssignmentPattern";
delete node.operator;
} else {
Expand All @@ -134,7 +120,6 @@ export default class LValParser extends NodeUtils {
node.expression,
isBinding,
contextDescription,
allowAssign,
);
break;

Expand All @@ -158,7 +143,6 @@ export default class LValParser extends NodeUtils {
prop: Node,
isBinding: ?boolean,
isLast: boolean,
allowAssign: boolean,
) {
if (prop.type === "ObjectMethod") {
const error =
Expand All @@ -170,12 +154,7 @@ export default class LValParser extends NodeUtils {
} else if (prop.type === "SpreadElement" && !isLast) {
this.raiseRestNotLast(prop.start);
} else {
this.toAssignable(
prop,
isBinding,
"object destructuring pattern",
allowAssign,
);
this.toAssignable(prop, isBinding, "object destructuring pattern");
}
}

Expand All @@ -186,7 +165,6 @@ export default class LValParser extends NodeUtils {
isBinding: ?boolean,
contextDescription: string,
trailingCommaPos?: ?number,
allowAssign: boolean,
): $ReadOnlyArray<Pattern> {
let end = exprList.length;
if (end) {
Expand All @@ -196,7 +174,7 @@ export default class LValParser extends NodeUtils {
} else if (last && last.type === "SpreadElement") {
last.type = "RestElement";
const arg = last.argument;
this.toAssignable(arg, isBinding, contextDescription, allowAssign);
this.toAssignable(arg, isBinding, contextDescription);
if (
arg.type !== "Identifier" &&
arg.type !== "MemberExpression" &&
Expand All @@ -216,7 +194,7 @@ export default class LValParser extends NodeUtils {
for (let i = 0; i < end; i++) {
const elt = exprList[i];
if (elt) {
this.toAssignable(elt, isBinding, contextDescription, allowAssign);
this.toAssignable(elt, isBinding, contextDescription);
if (elt.type === "RestElement") {
this.raiseRestNotLast(elt.start);
}
Expand Down
6 changes: 1 addition & 5 deletions packages/babel-parser/src/parser/statement.js
Expand Up @@ -538,11 +538,7 @@ export default class StatementParser extends ExpressionParser {
const description = this.isContextual("of")
? "for-of statement"
: "for-in statement";

// for-in assignable errors have special handling
const allowAssign = true;

this.toAssignable(init, undefined, description, allowAssign);
this.toAssignable(init, undefined, description);
this.checkLVal(init, undefined, undefined, description);
return this.parseForIn(node, init, awaitAt);
} else if (refShorthandDefaultPos.start) {
Expand Down
23 changes: 3 additions & 20 deletions packages/babel-parser/src/plugins/estree.js
Expand Up @@ -366,32 +366,20 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node: N.Node,
isBinding: ?boolean,
contextDescription: string,
allowAssign: boolean,
): N.Node {
if (isSimpleProperty(node)) {
this.toAssignable(
node.value,
isBinding,
contextDescription,
allowAssign,
);
this.toAssignable(node.value, isBinding, contextDescription);

return node;
}

return super.toAssignable(
node,
isBinding,
contextDescription,
allowAssign,
);
return super.toAssignable(node, isBinding, contextDescription);
}

toAssignableObjectExpressionProp(
prop: N.Node,
isBinding: ?boolean,
isLast: boolean,
allowAssign: boolean,
) {
if (prop.kind === "get" || prop.kind === "set") {
this.raise(
Expand All @@ -401,12 +389,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
} else if (prop.method) {
this.raise(prop.key.start, "Object pattern can't contain methods");
} else {
super.toAssignableObjectExpressionProp(
prop,
isBinding,
isLast,
allowAssign,
);
super.toAssignableObjectExpressionProp(prop, isBinding, isLast);
}
}
};
14 changes: 1 addition & 13 deletions packages/babel-parser/src/plugins/flow.js
Expand Up @@ -1799,7 +1799,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
true,
"arrow function parameters",
node.extra?.trailingComma,
true,
);
// Enter scope, as checkParams defines bindings
this.scope.enter(functionFlags(false, false) | SCOPE_ARROW);
Expand All @@ -1823,7 +1822,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
true,
"arrow function parameters",
node.extra?.trailingComma,
true,
);
}
return [arrows, []];
Expand All @@ -1836,7 +1834,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
true,
"arrow function parameters",
node.extra?.trailingComma,
true,
);
return true;
} catch (err) {
Expand Down Expand Up @@ -1994,22 +1991,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node: N.Node,
isBinding: ?boolean,
contextDescription: string,
allowAssign: boolean,
): N.Node {
if (node.type === "TypeCastExpression") {
return super.toAssignable(
this.typeCastToParameter(node),
isBinding,
contextDescription,
allowAssign,
);
} else {
return super.toAssignable(
node,
isBinding,
contextDescription,
allowAssign,
);
return super.toAssignable(node, isBinding, contextDescription);
}
}

Expand All @@ -2019,7 +2009,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
isBinding: ?boolean,
contextDescription: string,
trailingCommaPos?: ?number,
allowAssign: boolean,
): $ReadOnlyArray<N.Pattern> {
for (let i = 0; i < exprList.length; i++) {
const expr = exprList[i];
Expand All @@ -2032,7 +2021,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
isBinding,
contextDescription,
trailingCommaPos,
allowAssign,
);
}

Expand Down
17 changes: 2 additions & 15 deletions packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -2237,40 +2237,27 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node: N.Node,
isBinding: ?boolean,
contextDescription: string,
allowAssign: boolean,
): N.Node {
switch (node.type) {
case "TSTypeCastExpression":
return super.toAssignable(
this.typeCastToParameter(node),
isBinding,
contextDescription,
allowAssign,
);
case "TSParameterProperty":
return super.toAssignable(
node,
isBinding,
contextDescription,
allowAssign,
);
return super.toAssignable(node, isBinding, contextDescription);
case "TSAsExpression":
case "TSNonNullExpression":
case "TSTypeAssertion":
node.expression = this.toAssignable(
node.expression,
isBinding,
contextDescription,
allowAssign,
);
return node;
default:
return super.toAssignable(
node,
isBinding,
contextDescription,
allowAssign,
);
return super.toAssignable(node, isBinding, contextDescription);
}
}

Expand Down
@@ -1 +1 @@
[(a = 1)] = t
(a = 1) = t
@@ -1,3 +1,3 @@
{
"throws": "Invalid assignment pattern in left-hand side of expression (1:3)"
}
"throws": "Invalid parenthesized assignment pattern (1:1)"
}
@@ -1 +1 @@
(a = 1) = t
[(a = 1)] = t
@@ -1,3 +1,3 @@
{
"throws": "Invalid assignment pattern in left-hand side of expression (1:2)"
}
"throws": "Invalid parenthesized assignment pattern (1:2)"
}
@@ -1 +1 @@
[([[[a = 1]]])] = t;
[({ a: [b = 2]})] = t
@@ -1,3 +1,3 @@
{
"throws": "Invalid assignment pattern in left-hand side of expression (1:6)"
}
"throws": "Invalid parenthesized assignment pattern (1:2)"
}
@@ -1,3 +1,3 @@
{
"throws": "Invalid assignment pattern in left-hand side of expression (1:9)"
}
"throws": "Invalid parenthesized assignment pattern (1:7)"
}
@@ -0,0 +1 @@
[([x])] = t;
@@ -0,0 +1,3 @@
{
"throws": "Invalid parenthesized assignment pattern (1:2)"
}
@@ -0,0 +1 @@
[(a.x)] = t;

0 comments on commit 7e158a1

Please sign in to comment.