diff --git a/packages/babel-parser/src/parser/lval.js b/packages/babel-parser/src/parser/lval.js index 13b4b6b42555..bb4c951709e5 100644 --- a/packages/babel-parser/src/parser/lval.js +++ b/packages/babel-parser/src/parser/lval.js @@ -99,7 +99,7 @@ export default class LValParser extends NodeUtils { ) { const prop = node.properties[i]; const isLast = i === last; - this.toAssignableObjectExpressionProp(prop, isLast); + this.toAssignableObjectExpressionProp(prop, isLast, isLHS); if ( isLast && @@ -112,8 +112,7 @@ export default class LValParser extends NodeUtils { break; case "ObjectProperty": - // ObjectProperty is not allowed in LHS - this.toAssignable(node.value); + this.toAssignable(node.value, isLHS); break; case "SpreadElement": { @@ -137,8 +136,7 @@ export default class LValParser extends NodeUtils { node.type = "AssignmentPattern"; delete node.operator; - // AssignmentPattern is not allowed in LHS - this.toAssignable(node.left); + this.toAssignable(node.left, isLHS); break; case "ParenthesizedExpression": @@ -153,7 +151,11 @@ export default class LValParser extends NodeUtils { return node; } - toAssignableObjectExpressionProp(prop: Node, isLast: boolean) { + toAssignableObjectExpressionProp( + prop: Node, + isLast: boolean, + isLHS: boolean, + ) { if (prop.type === "ObjectMethod") { const error = prop.kind === "get" || prop.kind === "set" @@ -166,8 +168,7 @@ export default class LValParser extends NodeUtils { } else if (prop.type === "SpreadElement" && !isLast) { this.raiseRestNotLast(prop.start); } else { - // ObjectPattern is not allowed in LHS - this.toAssignable(prop); + this.toAssignable(prop, isLHS); } } diff --git a/packages/babel-parser/src/plugins/estree.js b/packages/babel-parser/src/plugins/estree.js index 8111cd2891e3..f520ae2c9db4 100644 --- a/packages/babel-parser/src/plugins/estree.js +++ b/packages/babel-parser/src/plugins/estree.js @@ -351,13 +351,13 @@ export default (superClass: Class): Class => return super.toAssignable(node, isLHS); } - toAssignableObjectExpressionProp(prop: N.Node, isLast: boolean) { + toAssignableObjectExpressionProp(prop: N.Node, ...args) { if (prop.kind === "get" || prop.kind === "set") { throw this.raise(prop.key.start, Errors.PatternHasAccessor); } else if (prop.method) { throw this.raise(prop.key.start, Errors.PatternHasMethod); } else { - super.toAssignableObjectExpressionProp(prop, isLast); + super.toAssignableObjectExpressionProp(prop, ...args); } } diff --git a/packages/babel-parser/src/plugins/flow.js b/packages/babel-parser/src/plugins/flow.js index e14638301a63..a02102a2ad9c 100644 --- a/packages/babel-parser/src/plugins/flow.js +++ b/packages/babel-parser/src/plugins/flow.js @@ -1955,6 +1955,7 @@ export default (superClass: Class): Class => // has not been converted yet. ((node.params: any): N.Expression[]), node.extra?.trailingComma, + /* isLHS */ false, ); // Enter scope, as checkParams defines bindings this.scope.enter(SCOPE_FUNCTION | SCOPE_ARROW); @@ -2204,7 +2205,7 @@ export default (superClass: Class): Class => toAssignableList( exprList: N.Expression[], trailingCommaPos?: ?number, - isLHS: boolean = true, + isLHS: boolean, ): $ReadOnlyArray { for (let i = 0; i < exprList.length; i++) { const expr = exprList[i]; diff --git a/packages/babel-parser/test/fixtures/es2015/arrow-functions/.inner-parens-array-pattern-2/input.js b/packages/babel-parser/test/fixtures/es2015/arrow-functions/.inner-parens-array-pattern-2/input.js new file mode 100644 index 000000000000..c87a5386e5d6 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/arrow-functions/.inner-parens-array-pattern-2/input.js @@ -0,0 +1 @@ +([ [(a)] = [] ] = []) => {} diff --git a/packages/babel-parser/test/fixtures/es2015/arrow-functions/.inner-parens-array-pattern-2/output.json b/packages/babel-parser/test/fixtures/es2015/arrow-functions/.inner-parens-array-pattern-2/output.json new file mode 100644 index 000000000000..7b7ee9fd382d --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/arrow-functions/.inner-parens-array-pattern-2/output.json @@ -0,0 +1,71 @@ +{ + "type": "File", + "start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":27}}, + "program": { + "type": "Program", + "start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":27}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":27}}, + "expression": { + "type": "ArrowFunctionExpression", + "start":0,"end":27,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":27}}, + "id": null, + "generator": false, + "async": false, + "params": [ + { + "type": "AssignmentPattern", + "start":1,"end":20,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":20}}, + "left": { + "type": "ArrayPattern", + "start":1,"end":15,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":15}}, + "elements": [ + { + "type": "AssignmentPattern", + "start":3,"end":13,"loc":{"start":{"line":1,"column":3},"end":{"line":1,"column":13}}, + "left": { + "type": "ArrayPattern", + "start":3,"end":8,"loc":{"start":{"line":1,"column":3},"end":{"line":1,"column":8}}, + "elements": [ + { + "type": "Identifier", + "start":5,"end":6,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":6},"identifierName":"a"}, + "extra": { + "parenthesized": true, + "parenStart": 4 + }, + "name": "a" + } + ] + }, + "right": { + "type": "ArrayExpression", + "start":11,"end":13,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":13}}, + "elements": [] + } + } + ] + }, + "right": { + "type": "ArrayExpression", + "start":18,"end":20,"loc":{"start":{"line":1,"column":18},"end":{"line":1,"column":20}}, + "elements": [] + } + } + ], + "body": { + "type": "BlockStatement", + "start":25,"end":27,"loc":{"start":{"line":1,"column":25},"end":{"line":1,"column":27}}, + "body": [], + "directives": [] + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/arrow-functions/.inner-parens-object-pattern/input.js b/packages/babel-parser/test/fixtures/es2015/arrow-functions/.inner-parens-object-pattern/input.js new file mode 100644 index 000000000000..009433301e2c --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/arrow-functions/.inner-parens-object-pattern/input.js @@ -0,0 +1 @@ +({ a: (foo) } = {}) => {} diff --git a/packages/babel-parser/test/fixtures/es2015/arrow-functions/.inner-parens-object-pattern/output.json b/packages/babel-parser/test/fixtures/es2015/arrow-functions/.inner-parens-object-pattern/output.json new file mode 100644 index 000000000000..5877bb92cdf0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/arrow-functions/.inner-parens-object-pattern/output.json @@ -0,0 +1,68 @@ +{ + "type": "File", + "start":0,"end":25,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":25}}, + "program": { + "type": "Program", + "start":0,"end":25,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":25}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":25,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":25}}, + "expression": { + "type": "ArrowFunctionExpression", + "start":0,"end":25,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":25}}, + "id": null, + "generator": false, + "async": false, + "params": [ + { + "type": "AssignmentPattern", + "start":1,"end":18,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":18}}, + "left": { + "type": "ObjectPattern", + "start":1,"end":13,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":13}}, + "properties": [ + { + "type": "ObjectProperty", + "start":3,"end":11,"loc":{"start":{"line":1,"column":3},"end":{"line":1,"column":11}}, + "method": false, + "key": { + "type": "Identifier", + "start":3,"end":4,"loc":{"start":{"line":1,"column":3},"end":{"line":1,"column":4},"identifierName":"a"}, + "name": "a" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "Identifier", + "start":7,"end":10,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":10},"identifierName":"foo"}, + "extra": { + "parenthesized": true, + "parenStart": 6 + }, + "name": "foo" + } + } + ] + }, + "right": { + "type": "ObjectExpression", + "start":16,"end":18,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":18}}, + "properties": [] + } + } + ], + "body": { + "type": "BlockStatement", + "start":23,"end":25,"loc":{"start":{"line":1,"column":23},"end":{"line":1,"column":25}}, + "body": [], + "directives": [] + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/destructuring/lhs-parenthesized-assignment/input.js b/packages/babel-parser/test/fixtures/es2015/destructuring/lhs-parenthesized-assignment/input.js new file mode 100644 index 000000000000..0fdb1d81c96d --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/destructuring/lhs-parenthesized-assignment/input.js @@ -0,0 +1 @@ +({ a: (a.b) = (c.d) } = {}); diff --git a/packages/babel-parser/test/fixtures/es2015/destructuring/lhs-parenthesized-assignment/output.json b/packages/babel-parser/test/fixtures/es2015/destructuring/lhs-parenthesized-assignment/output.json new file mode 100644 index 000000000000..26d23fd2ab71 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/destructuring/lhs-parenthesized-assignment/output.json @@ -0,0 +1,91 @@ +{ + "type": "File", + "start":0,"end":28,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":28}}, + "program": { + "type": "Program", + "start":0,"end":28,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":28}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":28,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":28}}, + "expression": { + "type": "AssignmentExpression", + "start":1,"end":26,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":26}}, + "extra": { + "parenthesized": true, + "parenStart": 0 + }, + "operator": "=", + "left": { + "type": "ObjectPattern", + "start":1,"end":21,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":21}}, + "properties": [ + { + "type": "ObjectProperty", + "start":3,"end":19,"loc":{"start":{"line":1,"column":3},"end":{"line":1,"column":19}}, + "method": false, + "key": { + "type": "Identifier", + "start":3,"end":4,"loc":{"start":{"line":1,"column":3},"end":{"line":1,"column":4},"identifierName":"a"}, + "name": "a" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "AssignmentPattern", + "start":6,"end":19,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":19}}, + "left": { + "type": "MemberExpression", + "start":7,"end":10,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":10}}, + "extra": { + "parenthesized": true, + "parenStart": 6 + }, + "object": { + "type": "Identifier", + "start":7,"end":8,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":8},"identifierName":"a"}, + "name": "a" + }, + "computed": false, + "property": { + "type": "Identifier", + "start":9,"end":10,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":10},"identifierName":"b"}, + "name": "b" + } + }, + "right": { + "type": "MemberExpression", + "start":15,"end":18,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":18}}, + "extra": { + "parenthesized": true, + "parenStart": 14 + }, + "object": { + "type": "Identifier", + "start":15,"end":16,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":16},"identifierName":"c"}, + "name": "c" + }, + "computed": false, + "property": { + "type": "Identifier", + "start":17,"end":18,"loc":{"start":{"line":1,"column":17},"end":{"line":1,"column":18},"identifierName":"d"}, + "name": "d" + } + } + } + } + ] + }, + "right": { + "type": "ObjectExpression", + "start":24,"end":26,"loc":{"start":{"line":1,"column":24},"end":{"line":1,"column":26}}, + "properties": [] + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/destructuring/lhs-parenthesized-object/input.js b/packages/babel-parser/test/fixtures/es2015/destructuring/lhs-parenthesized-object/input.js new file mode 100644 index 000000000000..5093d4e7afd0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/destructuring/lhs-parenthesized-object/input.js @@ -0,0 +1 @@ +({ a: (a.b) } = {}); diff --git a/packages/babel-parser/test/fixtures/es2015/destructuring/lhs-parenthesized-object/output.json b/packages/babel-parser/test/fixtures/es2015/destructuring/lhs-parenthesized-object/output.json new file mode 100644 index 000000000000..8e08d2747603 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/destructuring/lhs-parenthesized-object/output.json @@ -0,0 +1,68 @@ +{ + "type": "File", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "program": { + "type": "Program", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "expression": { + "type": "AssignmentExpression", + "start":1,"end":18,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":18}}, + "extra": { + "parenthesized": true, + "parenStart": 0 + }, + "operator": "=", + "left": { + "type": "ObjectPattern", + "start":1,"end":13,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":13}}, + "properties": [ + { + "type": "ObjectProperty", + "start":3,"end":11,"loc":{"start":{"line":1,"column":3},"end":{"line":1,"column":11}}, + "method": false, + "key": { + "type": "Identifier", + "start":3,"end":4,"loc":{"start":{"line":1,"column":3},"end":{"line":1,"column":4},"identifierName":"a"}, + "name": "a" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "MemberExpression", + "start":7,"end":10,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":10}}, + "extra": { + "parenthesized": true, + "parenStart": 6 + }, + "object": { + "type": "Identifier", + "start":7,"end":8,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":8},"identifierName":"a"}, + "name": "a" + }, + "computed": false, + "property": { + "type": "Identifier", + "start":9,"end":10,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":10},"identifierName":"b"}, + "name": "b" + } + } + } + ] + }, + "right": { + "type": "ObjectExpression", + "start":16,"end":18,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":18}}, + "properties": [] + } + } + } + ], + "directives": [] + } +} \ No newline at end of file