Repository: babel/babel (TypeScript)

Issue:
[Bug]: Async generators with default parameters compile to invalid code
### 💻

- [ ] Would you like to work on a fix?

### How are you using Babel?

babel-loader (webpack)

### Input code

```js
export async function * foo (p = 1) {
  yield "hello";
}
for await (const x of foo()) {
  console.log(x);
}
```

### Configuration file name

_No response_

### Configuration

_No response_

### Current and expected behavior

With babel v7.17.12, the above code is compiled to:

```js
async function* foo(p) {
  if (p === void 0) {
    p = 1;
  }

  yield "hello";
}

for await (const x of foo()) {
  console.log(x);
}
```

When run with node, this prints `hello` as expected.

With v7.20.2, the compiled code is:

```js
async function foo(p) {
  if (p === void 0) {
    p = 1;
  }
  return async function* () {
    yield "hello";
  }();
}
for await (const x of foo()) {
  console.log(x);
}
```

This throws an exception:

```
Uncaught TypeError: foo(...) is not a function or its return value is not async iterable
```

### Environment

Turn "Bug Fixes" OFF in REPL to reproduce.

### Possible solution

Possible regression caused by #15081 ?

### Additional context

_No response_


Hints:
Hey @codebutler! 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.

Patch:
diff --git a/packages/babel-plugin-transform-parameters/src/params.ts b/packages/babel-plugin-transform-parameters/src/params.ts
--- a/packages/babel-plugin-transform-parameters/src/params.ts
+++ b/packages/babel-plugin-transform-parameters/src/params.ts
@@ -154,7 +154,8 @@ export default function convertFunctionParams(
   // ensure it's a block, useful for arrow functions
   path.ensureBlock();
 
-  if (state.needsOuterBinding || shadowedParams.size > 0 || node.generator) {
+  const { async, generator } = node;
+  if (generator || state.needsOuterBinding || shadowedParams.size > 0) {
     body.push(buildScopeIIFE(shadowedParams, path.node.body));
 
     path.set("body", t.blockStatement(body as t.Statement[]));
@@ -169,12 +170,21 @@ export default function convertFunctionParams(
     // This is an IIFE, so we don't need to worry about the noNewArrows assumption
     arrowPath.arrowFunctionToExpression();
 
-    arrowPath.node.generator = path.node.generator;
-    arrowPath.node.async = path.node.async;
-
-    // We don't reset "async" because if the default value of a parameter
-    // throws, it must reject asynchronously.
-    path.node.generator = false;
+    arrowPath.node.generator = generator;
+    arrowPath.node.async = async;
+
+    node.generator = false;
+    node.async = false;
+    if (async) {
+      // If the default value of a parameter throws, it must reject asynchronously.
+      path.node.body = template.statement.ast`{
+        try {
+          ${path.node.body.body}
+        } catch (e) {
+          return Promise.reject(e);
+        }
+      }` as t.BlockStatement;
+    }
   } else {
     path.get("body").unshiftContainer("body", body);
   }


Test patch:
diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/regression/15145/exec.js b/packages/babel-plugin-transform-parameters/test/fixtures/regression/15145/exec.js
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-transform-parameters/test/fixtures/regression/15145/exec.js
@@ -0,0 +1,10 @@
+async function * foo (p = 1) {
+  yield "hello";
+  yield p;
+}
+
+return (async () => {
+  const res = [];
+  for await (const x of foo()) res.push(x);
+  expect(res).toEqual(["hello", 1]);
+})();
diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/regression/15145/options.json b/packages/babel-plugin-transform-parameters/test/fixtures/regression/15145/options.json
new file mode 100644
--- /dev/null
+++ b/packages/babel-plugin-transform-parameters/test/fixtures/regression/15145/options.json
@@ -0,0 +1,7 @@
+{
+  "plugins": ["transform-parameters"],
+  "parserOpts": {
+    "allowReturnOutsideFunction": true
+  },
+  "minNodeVersion": "10.0.0"
+}
diff --git a/packages/babel-plugin-transform-parameters/test/fixtures/regression/scope-gen-async/output.js b/packages/babel-plugin-transform-parameters/test/fixtures/regression/scope-gen-async/output.js
--- a/packages/babel-plugin-transform-parameters/test/fixtures/regression/scope-gen-async/output.js
+++ b/packages/babel-plugin-transform-parameters/test/fixtures/regression/scope-gen-async/output.js
@@ -5,17 +5,25 @@ function f() {
     return a;
   }(a);
 }
-async function g() {
-  let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
-  return async function (a) {
-    var a = await a;
-    return a;
-  }(a);
+function g() {
+  try {
+    let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
+    return async function (a) {
+      var a = await a;
+      return a;
+    }(a);
+  } catch (e) {
+    return Promise.reject(e);
+  }
 }
-async function h() {
-  let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
-  return async function* (a) {
-    var a = await (yield a);
-    return a;
-  }(a);
+function h() {
+  try {
+    let a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
+    return async function* (a) {
+      var a = await (yield a);
+      return a;
+    }(a);
+  } catch (e) {
+    return Promise.reject(e);
+  }
 }