Repository: babel/babel (TypeScript)

Issue:
[Bug]: Inconsistent on different `createParenthesizedExpressions` option
### 💻

- [ ] Would you like to work on a fix?

### How are you using Babel?

Programmatic API (`babel.transform`, `babel.parse`)

### Input code

```js
new (foo?.bar)();
```

### Configuration file name

_No response_

### Configuration


_No response_

### Current and expected behavior

```console
> require('@babel/parser').parse('new (foo?.bar)();', {createParenthesizedExpressions: true})
Node {
  type: 'File',
  start: 0,
  end: 17,
  ...
```

```console
> require('@babel/parser').parse('new (foo?.bar)();')
Uncaught [SyntaxError: Constructors in/after an Optional Chain are not allowed. (1:14)
] {
  code: 'BABEL_PARSER_SYNTAX_ERROR',
  reasonCode: 'OptionalChainingNoNew',
  loc: Position { line: 1, column: 14, index: 14 },
  pos: [Getter/Setter]
}
```

Should behave the same.

### Environment

`@babel/parser: 7.20.13 => 7.20.13`

Don't think other things matters.

### Possible solution

Maybe forgot to strip `ParenthesizedExpression` somewhere.

### Additional context

_No response_


Hints:
Hey @fisker! We really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we're a limited number of volunteers, so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant [Slack community](https://babeljs.slack.com) that typically always has someone willing to help. You can sign-up [here](https://slack.babeljs.io/) for an invite.
Actually, the first is correct and the second is incorrect. Both should be runtime errors, not syntax errors, because `(foo?.bar)` isn't an optional chain anymore.
You're right, thanks!

Patch:
diff --git a/packages/babel-parser/src/parser/expression.ts b/packages/babel-parser/src/parser/expression.ts
--- 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,
       });


Test patch:
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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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": []
+  }
+}