diff --git a/packages/babel-parser/src/parser/expression.ts b/packages/babel-parser/src/parser/expression.ts index 7df759211928..8779b6086e39 100644 --- a/packages/babel-parser/src/parser/expression.ts +++ b/packages/babel-parser/src/parser/expression.ts @@ -1918,7 +1918,10 @@ export default abstract class ExpressionParser extends LValParser { node.callee = this.parseNoCallExpr(); if (node.callee.type === "Import") { this.raise(Errors.ImportCallNotNewExpression, { at: node.callee }); - } else if (this.isOptionalChain(node.callee)) { + } else if ( + this.isOptionalChain(node.callee) && + !node.callee.extra?.parenthesized + ) { this.raise(Errors.OptionalChainingNoNew, { at: this.state.lastTokEndLoc, }); diff --git a/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-false/input.js b/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-false/input.js new file mode 100644 index 000000000000..8cea0fe632ae --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-false/input.js @@ -0,0 +1 @@ +new (foo?.bar)(); diff --git a/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-false/options.json b/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-false/options.json new file mode 100644 index 000000000000..0861962d889d --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-false/options.json @@ -0,0 +1,3 @@ +{ + "createParenthesizedExpressions": true +} diff --git a/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-false/output.json b/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-false/output.json new file mode 100644 index 000000000000..3551a078ef2e --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-false/output.json @@ -0,0 +1,42 @@ +{ + "type": "File", + "start":0,"end":17,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":17,"index":17}}, + "program": { + "type": "Program", + "start":0,"end":17,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":17,"index":17}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":17,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":17,"index":17}}, + "expression": { + "type": "NewExpression", + "start":0,"end":16,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":16,"index":16}}, + "callee": { + "type": "ParenthesizedExpression", + "start":4,"end":14,"loc":{"start":{"line":1,"column":4,"index":4},"end":{"line":1,"column":14,"index":14}}, + "expression": { + "type": "OptionalMemberExpression", + "start":5,"end":13,"loc":{"start":{"line":1,"column":5,"index":5},"end":{"line":1,"column":13,"index":13}}, + "object": { + "type": "Identifier", + "start":5,"end":8,"loc":{"start":{"line":1,"column":5,"index":5},"end":{"line":1,"column":8,"index":8},"identifierName":"foo"}, + "name": "foo" + }, + "computed": false, + "property": { + "type": "Identifier", + "start":10,"end":13,"loc":{"start":{"line":1,"column":10,"index":10},"end":{"line":1,"column":13,"index":13},"identifierName":"bar"}, + "name": "bar" + }, + "optional": true + } + }, + "arguments": [] + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-true/input.js b/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-true/input.js new file mode 100644 index 000000000000..d754caa35932 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-true/input.js @@ -0,0 +1,4 @@ +new foo?.bar(); +new foo.bar?.(); + +new (foo?.bar)(); diff --git a/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-true/options.json b/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-true/options.json new file mode 100644 index 000000000000..66d8346cbf5f --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-true/options.json @@ -0,0 +1,3 @@ +{ + "createParenthesizedExpressions": false +} diff --git a/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-true/output.json b/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-true/output.json new file mode 100644 index 000000000000..a6acdb65d98f --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2020/optional-chaining/new-createParenthesizedExpressions-true/output.json @@ -0,0 +1,95 @@ +{ + "type": "File", + "start":0,"end":51,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":4,"column":17,"index":51}}, + "errors": [ + "SyntaxError: Constructors in/after an Optional Chain are not allowed. (1:12)", + "SyntaxError: Constructors in/after an Optional Chain are not allowed. (2:13)" + ], + "program": { + "type": "Program", + "start":0,"end":51,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":4,"column":17,"index":51}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start":0,"end":15,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":15,"index":15}}, + "expression": { + "type": "NewExpression", + "start":0,"end":14,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":14,"index":14}}, + "callee": { + "type": "OptionalMemberExpression", + "start":4,"end":12,"loc":{"start":{"line":1,"column":4,"index":4},"end":{"line":1,"column":12,"index":12}}, + "object": { + "type": "Identifier", + "start":4,"end":7,"loc":{"start":{"line":1,"column":4,"index":4},"end":{"line":1,"column":7,"index":7},"identifierName":"foo"}, + "name": "foo" + }, + "computed": false, + "property": { + "type": "Identifier", + "start":9,"end":12,"loc":{"start":{"line":1,"column":9,"index":9},"end":{"line":1,"column":12,"index":12},"identifierName":"bar"}, + "name": "bar" + }, + "optional": true + }, + "arguments": [] + } + }, + { + "type": "ExpressionStatement", + "start":16,"end":32,"loc":{"start":{"line":2,"column":0,"index":16},"end":{"line":2,"column":16,"index":32}}, + "expression": { + "type": "NewExpression", + "start":16,"end":31,"loc":{"start":{"line":2,"column":0,"index":16},"end":{"line":2,"column":15,"index":31}}, + "callee": { + "type": "MemberExpression", + "start":20,"end":27,"loc":{"start":{"line":2,"column":4,"index":20},"end":{"line":2,"column":11,"index":27}}, + "object": { + "type": "Identifier", + "start":20,"end":23,"loc":{"start":{"line":2,"column":4,"index":20},"end":{"line":2,"column":7,"index":23},"identifierName":"foo"}, + "name": "foo" + }, + "computed": false, + "property": { + "type": "Identifier", + "start":24,"end":27,"loc":{"start":{"line":2,"column":8,"index":24},"end":{"line":2,"column":11,"index":27},"identifierName":"bar"}, + "name": "bar" + } + }, + "arguments": [] + } + }, + { + "type": "ExpressionStatement", + "start":34,"end":51,"loc":{"start":{"line":4,"column":0,"index":34},"end":{"line":4,"column":17,"index":51}}, + "expression": { + "type": "NewExpression", + "start":34,"end":50,"loc":{"start":{"line":4,"column":0,"index":34},"end":{"line":4,"column":16,"index":50}}, + "callee": { + "type": "OptionalMemberExpression", + "start":39,"end":47,"loc":{"start":{"line":4,"column":5,"index":39},"end":{"line":4,"column":13,"index":47}}, + "object": { + "type": "Identifier", + "start":39,"end":42,"loc":{"start":{"line":4,"column":5,"index":39},"end":{"line":4,"column":8,"index":42},"identifierName":"foo"}, + "name": "foo" + }, + "computed": false, + "property": { + "type": "Identifier", + "start":44,"end":47,"loc":{"start":{"line":4,"column":10,"index":44},"end":{"line":4,"column":13,"index":47},"identifierName":"bar"}, + "name": "bar" + }, + "optional": true, + "extra": { + "parenthesized": true, + "parenStart": 38 + } + }, + "arguments": [] + } + } + ], + "directives": [] + } +}