From 7fe3ebf4db01eea9cb3a0cbb944840b03cf0f697 Mon Sep 17 00:00:00 2001 From: Federico Ciardi Date: Tue, 6 Apr 2021 16:07:13 +0200 Subject: [PATCH] fix: raise `SyntaxError` for unparenthesized assert and assign (#13099) * fix: raise `SyntaxError` for unparenthesized assert and assign * chore --- .../src/plugins/typescript/index.js | 14 ++- .../cast/assert-and-assign/input.ts | 3 +- .../cast/assert-and-assign/output.json | 78 ++++++++++++- .../multiple-assert-and-assign/output.json | 8 +- .../type-assertion-and-assign/output.json | 8 +- .../input.ts | 2 + .../output.json | 110 ++++++++++++++++++ .../input.ts | 1 + .../output.json | 47 ++++++++ 9 files changed, 254 insertions(+), 17 deletions(-) create mode 100644 packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/input.ts create mode 100644 packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/output.json create mode 100644 packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-type-assertion-and-assign/input.ts create mode 100644 packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-type-assertion-and-assign/output.json diff --git a/packages/babel-parser/src/plugins/typescript/index.js b/packages/babel-parser/src/plugins/typescript/index.js index 56e3efc99f75..eebfce60b601 100644 --- a/packages/babel-parser/src/plugins/typescript/index.js +++ b/packages/babel-parser/src/plugins/typescript/index.js @@ -2589,7 +2589,7 @@ export default (superClass: Class): Class => if ( expr.type !== "ArrowFunctionExpression" || - (expr.extra && expr.extra.parenthesized) + expr.extra?.parenthesized ) { abort(); } @@ -2743,8 +2743,18 @@ export default (superClass: Class): Class => this.checkLVal(expr.parameter, "parameter property", ...args); return; case "TSAsExpression": - case "TSNonNullExpression": case "TSTypeAssertion": + if ( + /*bindingType*/ !args[0] && + contextDescription !== "parenthesized expression" && + !expr.extra?.parenthesized + ) { + this.raise(expr.start, Errors.InvalidLhs, contextDescription); + break; + } + this.checkLVal(expr.expression, "parenthesized expression", ...args); + return; + case "TSNonNullExpression": this.checkLVal(expr.expression, contextDescription, ...args); return; default: diff --git a/packages/babel-parser/test/fixtures/typescript/cast/assert-and-assign/input.ts b/packages/babel-parser/test/fixtures/typescript/cast/assert-and-assign/input.ts index f5f2dc3a4950..1e4413d4a6bc 100644 --- a/packages/babel-parser/test/fixtures/typescript/cast/assert-and-assign/input.ts +++ b/packages/babel-parser/test/fixtures/typescript/cast/assert-and-assign/input.ts @@ -1 +1,2 @@ -(a as number) = 42; \ No newline at end of file +(a as number) = 42; +({ a: (b as any) = 2000 } = x); diff --git a/packages/babel-parser/test/fixtures/typescript/cast/assert-and-assign/output.json b/packages/babel-parser/test/fixtures/typescript/cast/assert-and-assign/output.json index bc0f97cffd33..4431d1e3807b 100644 --- a/packages/babel-parser/test/fixtures/typescript/cast/assert-and-assign/output.json +++ b/packages/babel-parser/test/fixtures/typescript/cast/assert-and-assign/output.json @@ -1,9 +1,9 @@ { "type": "File", - "start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}}, + "start":0,"end":51,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":31}}, "program": { "type": "Program", - "start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}}, + "start":0,"end":51,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":31}}, "sourceType": "module", "interpreter": null, "body": [ @@ -17,6 +17,10 @@ "left": { "type": "TSAsExpression", "start":1,"end":12,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":12}}, + "extra": { + "parenthesized": true, + "parenStart": 0 + }, "expression": { "type": "Identifier", "start":1,"end":2,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":2},"identifierName":"a"}, @@ -25,10 +29,6 @@ "typeAnnotation": { "type": "TSNumberKeyword", "start":6,"end":12,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":12}} - }, - "extra": { - "parenthesized": true, - "parenStart": 0 } }, "right": { @@ -41,6 +41,72 @@ "value": 42 } } + }, + { + "type": "ExpressionStatement", + "start":20,"end":51,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":31}}, + "expression": { + "type": "AssignmentExpression", + "start":21,"end":49,"loc":{"start":{"line":2,"column":1},"end":{"line":2,"column":29}}, + "extra": { + "parenthesized": true, + "parenStart": 20 + }, + "operator": "=", + "left": { + "type": "ObjectPattern", + "start":21,"end":45,"loc":{"start":{"line":2,"column":1},"end":{"line":2,"column":25}}, + "properties": [ + { + "type": "ObjectProperty", + "start":23,"end":43,"loc":{"start":{"line":2,"column":3},"end":{"line":2,"column":23}}, + "method": false, + "key": { + "type": "Identifier", + "start":23,"end":24,"loc":{"start":{"line":2,"column":3},"end":{"line":2,"column":4},"identifierName":"a"}, + "name": "a" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "AssignmentPattern", + "start":26,"end":43,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":23}}, + "left": { + "type": "TSAsExpression", + "start":27,"end":35,"loc":{"start":{"line":2,"column":7},"end":{"line":2,"column":15}}, + "extra": { + "parenthesized": true, + "parenStart": 26 + }, + "expression": { + "type": "Identifier", + "start":27,"end":28,"loc":{"start":{"line":2,"column":7},"end":{"line":2,"column":8},"identifierName":"b"}, + "name": "b" + }, + "typeAnnotation": { + "type": "TSAnyKeyword", + "start":32,"end":35,"loc":{"start":{"line":2,"column":12},"end":{"line":2,"column":15}} + } + }, + "right": { + "type": "NumericLiteral", + "start":39,"end":43,"loc":{"start":{"line":2,"column":19},"end":{"line":2,"column":23}}, + "extra": { + "rawValue": 2000, + "raw": "2000" + }, + "value": 2000 + } + } + } + ] + }, + "right": { + "type": "Identifier", + "start":48,"end":49,"loc":{"start":{"line":2,"column":28},"end":{"line":2,"column":29},"identifierName":"x"}, + "name": "x" + } + } } ], "directives": [] diff --git a/packages/babel-parser/test/fixtures/typescript/cast/multiple-assert-and-assign/output.json b/packages/babel-parser/test/fixtures/typescript/cast/multiple-assert-and-assign/output.json index cbd35d32f71d..6741a2fd154a 100644 --- a/packages/babel-parser/test/fixtures/typescript/cast/multiple-assert-and-assign/output.json +++ b/packages/babel-parser/test/fixtures/typescript/cast/multiple-assert-and-assign/output.json @@ -17,6 +17,10 @@ "left": { "type": "TSAsExpression", "start":1,"end":19,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":19}}, + "extra": { + "parenthesized": true, + "parenStart": 0 + }, "expression": { "type": "TSAsExpression", "start":1,"end":12,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":12}}, @@ -33,10 +37,6 @@ "typeAnnotation": { "type": "TSAnyKeyword", "start":16,"end":19,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":19}} - }, - "extra": { - "parenthesized": true, - "parenStart": 0 } }, "right": { diff --git a/packages/babel-parser/test/fixtures/typescript/cast/type-assertion-and-assign/output.json b/packages/babel-parser/test/fixtures/typescript/cast/type-assertion-and-assign/output.json index 5b7a8bb9fd6c..6e656ebb14da 100644 --- a/packages/babel-parser/test/fixtures/typescript/cast/type-assertion-and-assign/output.json +++ b/packages/babel-parser/test/fixtures/typescript/cast/type-assertion-and-assign/output.json @@ -17,6 +17,10 @@ "left": { "type": "TSTypeAssertion", "start":1,"end":11,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":11}}, + "extra": { + "parenthesized": true, + "parenStart": 0 + }, "typeAnnotation": { "type": "TSNumberKeyword", "start":2,"end":8,"loc":{"start":{"line":1,"column":2},"end":{"line":1,"column":8}} @@ -25,10 +29,6 @@ "type": "Identifier", "start":10,"end":11,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":11},"identifierName":"x"}, "name": "x" - }, - "extra": { - "parenthesized": true, - "parenStart": 0 } }, "right": { diff --git a/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/input.ts b/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/input.ts new file mode 100644 index 000000000000..216b4e5b262d --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/input.ts @@ -0,0 +1,2 @@ +foo as any = 10; +({ a: b as any = 2000 } = x); diff --git a/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/output.json b/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/output.json new file mode 100644 index 000000000000..6497654889f0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/output.json @@ -0,0 +1,110 @@ +{ + "type": "File", + "start":0,"end":46,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":29}}, + "errors": [ + "SyntaxError: Invalid left-hand side in assignment expression (1:0)", + "SyntaxError: Invalid left-hand side in assignment expression (2:6)" + ], + "program": { + "type": "Program", + "start":0,"end":46,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":29}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":16}}, + "expression": { + "type": "AssignmentExpression", + "start":0,"end":15,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":15}}, + "operator": "=", + "left": { + "type": "TSAsExpression", + "start":0,"end":10,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":10}}, + "expression": { + "type": "Identifier", + "start":0,"end":3,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":3},"identifierName":"foo"}, + "name": "foo" + }, + "typeAnnotation": { + "type": "TSAnyKeyword", + "start":7,"end":10,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":10}} + } + }, + "right": { + "type": "NumericLiteral", + "start":13,"end":15,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":15}}, + "extra": { + "rawValue": 10, + "raw": "10" + }, + "value": 10 + } + } + }, + { + "type": "ExpressionStatement", + "start":17,"end":46,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":29}}, + "expression": { + "type": "AssignmentExpression", + "start":18,"end":44,"loc":{"start":{"line":2,"column":1},"end":{"line":2,"column":27}}, + "extra": { + "parenthesized": true, + "parenStart": 17 + }, + "operator": "=", + "left": { + "type": "ObjectPattern", + "start":18,"end":40,"loc":{"start":{"line":2,"column":1},"end":{"line":2,"column":23}}, + "properties": [ + { + "type": "ObjectProperty", + "start":20,"end":38,"loc":{"start":{"line":2,"column":3},"end":{"line":2,"column":21}}, + "method": false, + "key": { + "type": "Identifier", + "start":20,"end":21,"loc":{"start":{"line":2,"column":3},"end":{"line":2,"column":4},"identifierName":"a"}, + "name": "a" + }, + "computed": false, + "shorthand": false, + "value": { + "type": "AssignmentPattern", + "start":23,"end":38,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":21}}, + "left": { + "type": "TSAsExpression", + "start":23,"end":31,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":14}}, + "expression": { + "type": "Identifier", + "start":23,"end":24,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":7},"identifierName":"b"}, + "name": "b" + }, + "typeAnnotation": { + "type": "TSAnyKeyword", + "start":28,"end":31,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":14}} + } + }, + "right": { + "type": "NumericLiteral", + "start":34,"end":38,"loc":{"start":{"line":2,"column":17},"end":{"line":2,"column":21}}, + "extra": { + "rawValue": 2000, + "raw": "2000" + }, + "value": 2000 + } + } + } + ] + }, + "right": { + "type": "Identifier", + "start":43,"end":44,"loc":{"start":{"line":2,"column":26},"end":{"line":2,"column":27},"identifierName":"x"}, + "name": "x" + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-type-assertion-and-assign/input.ts b/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-type-assertion-and-assign/input.ts new file mode 100644 index 000000000000..065e483e39b1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-type-assertion-and-assign/input.ts @@ -0,0 +1 @@ +foo = '100'; diff --git a/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-type-assertion-and-assign/output.json b/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-type-assertion-and-assign/output.json new file mode 100644 index 000000000000..78450d163a7a --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-type-assertion-and-assign/output.json @@ -0,0 +1,47 @@ +{ + "type": "File", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "errors": [ + "SyntaxError: Invalid left-hand side in assignment expression (1:0)" + ], + "program": { + "type": "Program", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}}, + "expression": { + "type": "AssignmentExpression", + "start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}}, + "operator": "=", + "left": { + "type": "TSTypeAssertion", + "start":0,"end":11,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":11}}, + "typeAnnotation": { + "type": "TSStringKeyword", + "start":1,"end":7,"loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":7}} + }, + "expression": { + "type": "Identifier", + "start":8,"end":11,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":11},"identifierName":"foo"}, + "name": "foo" + } + }, + "right": { + "type": "StringLiteral", + "start":14,"end":19,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":19}}, + "extra": { + "rawValue": "100", + "raw": "'100'" + }, + "value": "100" + } + } + } + ], + "directives": [] + } +} \ No newline at end of file