Repository: swc-project/swc (rust)

Issue:
ReferenceError on a valid code
### Describe the bug

Bug found while migrating actual project from CRA to Vite using defaults. Valid JS code is transpired incorrectly. Reproducible on the default configuration via `npx swc` or the playground.

### Input code

```typescript
const messages = [{ message: 'hello' }];
const logs = messages.map(({ log = () => console.log(message), message }) => log);
logs[0]();
```


### Config

```json
{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": false
    },
    "target": "es5",
    "loose": false,
    "minify": {
      "compress": false,
      "mangle": false
    }
  },
  "module": {
    "type": "es6"
  },
  "minify": false,
  "isModule": true
}
```


### Playground link

https://play.swc.rs/?version=1.3.49&code=H4sIAAAAAAAAA0vOzysuUchNLS5OTE8tVrBViK6G8awU1DNSc3Ly1RVqY625ksEKc%2FLTQYpg6vVyEws0NKpBwkBRDU0FWzsFkML8nFQ9oJgGVJ2mDkyHQi1YDVBO05oLZFi0QawGkAkAxy084IcAAAA%3D&config=H4sIAAAAAAAAA1WPSw7DIAwF9zkF8rrbdtE79BAWdSIifrKJVBTl7iUE0maH3xsz8jooBbNoeKq1PMsQkYX4nEsi2Sf8lARIOxTNJia49XaWvRrRCtVoOxpIyBOluiX3hoMNQajjLXPGmzH%2FC3VwkUnkCu4o%2BsnSVTc0JbjwXmrZDkk50qF%2FwA%2FqsvNjMPLqm4kXGrYvhlQioBQBAAA%3D

### Expected behavior

Outputs `hello` into the console

### Actual behavior

JS error: `Uncaught ReferenceError: message is not defined`

### Version

1.3.49

### Additional context

_No response_

Pull request description:
fix(es/hygiene): Hoist parameter in arrow and constructor
<!-- Note: CI script will automatically rebase your PR so please do not rebase unless required -->

<!-- Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. -->

**Description:**

closes #7248 
**BREAKING CHANGE:**

<!--
If this PR introduces a breaking change, it must contain a notice for it to be included in the CHANGELOG. Add description or remove entirely if not breaking.

You may need to update `MIGRATION.md` for the breaking changes.
-->

**Related issue (if exists):**


Patch:
diff --git a/crates/swc_ecma_transforms_base/src/resolver/mod.rs b/crates/swc_ecma_transforms_base/src/resolver/mod.rs
index ef9e482120..e2b098dff7 100644
--- a/crates/swc_ecma_transforms_base/src/resolver/mod.rs
+++ b/crates/swc_ecma_transforms_base/src/resolver/mod.rs
@@ -549,6 +549,18 @@ impl<'a> VisitMut for Resolver<'a> {
 
             let old = child.ident_type;
             child.ident_type = IdentType::Binding;
+            {
+                let params = e
+                    .params
+                    .iter()
+                    .filter(|p| !p.is_rest())
+                    .flat_map(find_pat_ids)
+                    .collect::<Vec<Id>>();
+
+                for id in params {
+                    child.current.declared_symbols.insert(id.0, DeclKind::Param);
+                }
+            }
             e.params.visit_mut_with(child);
             child.ident_type = old;
 
@@ -716,6 +728,21 @@ impl<'a> VisitMut for Resolver<'a> {
         self.with_child(ScopeKind::Fn, |child| {
             let old = child.ident_type;
             child.ident_type = IdentType::Binding;
+            {
+                let params = c
+                    .params
+                    .iter()
+                    .filter(|p| match p {
+                        ParamOrTsParamProp::TsParamProp(_) => false,
+                        ParamOrTsParamProp::Param(p) => !p.pat.is_rest(),
+                    })
+                    .flat_map(find_pat_ids)
+                    .collect::<Vec<Id>>();
+
+                for id in params {
+                    child.current.declared_symbols.insert(id.0, DeclKind::Param);
+                }
+            }
             c.params.visit_mut_with(child);
             child.ident_type = old;
 
@@ -802,7 +829,6 @@ impl<'a> VisitMut for Resolver<'a> {
 
     fn visit_mut_fn_decl(&mut self, node: &mut FnDecl) {
         // We don't fold ident as Hoister handles this.
-
         node.function.decorators.visit_mut_with(self);
 
         self.with_child(ScopeKind::Fn, |child| node.function.visit_mut_with(child));


Test patch:
diff --git a/crates/swc/tests/exec/issues-7xxx/7248/1/exec.js b/crates/swc/tests/exec/issues-7xxx/7248/1/exec.js
new file mode 100644
index 0000000000..0b9fa2a5f5
--- /dev/null
+++ b/crates/swc/tests/exec/issues-7xxx/7248/1/exec.js
@@ -0,0 +1,3 @@
+const messages = [{ message: 'hello' }];
+const logs = messages.map(({ log = () => console.log(message), message }) => log);
+logs[0]();
diff --git a/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing.1.normal.js b/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing.1.normal.js
index d53f7b1e85..8dd7cd705b 100644
--- a/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing.1.normal.js
+++ b/crates/swc/tests/tsc-references/parameterInitializersForwardReferencing.1.normal.js
@@ -1,7 +1,7 @@
 //// [parameterInitializersForwardReferencing.ts]
 import { _ as _class_call_check } from "@swc/helpers/_/_class_call_check";
 function left(a) {
-    var b1 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : a, c1 = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : b1;
+    var b1 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : a, c = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : b1;
     a;
     b1;
 }
@@ -11,10 +11,10 @@ function right() {
     b1;
 }
 function right2() {
-    var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : b1, b1 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : c1, c1 = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : a;
+    var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : b1, b1 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : c, c = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : a;
     a;
     b1;
-    c1;
+    c;
 }
 function inside() {
     var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : b;
@@ -42,7 +42,7 @@ function defaultArgArrow() {
 var C = /*#__PURE__*/ function() {
     "use strict";
     function C() {
-        var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : b, _$b = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 1;
+        var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : b1, b1 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 1;
         _class_call_check(this, C);
     }
     var _proto = C.prototype;
@@ -53,12 +53,12 @@ var C = /*#__PURE__*/ function() {
 }();
 // Function expressions
 var x = function() {
-    var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : b, _$b = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : c, _$c = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : d;
+    var a = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : b1, b1 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : c, c = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : d;
     var _$d;
 };
 // Should not produce errors - can reference later parameters if they occur within a function expression initializer.
 function f(a) {
     var b1 = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : function() {
-        return c1;
-    }, c1 = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : b1();
+        return c;
+    }, c = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : b1();
 }
diff --git a/crates/swc_ecma_transforms_base/tests/resolver/issue-7248/input.js b/crates/swc_ecma_transforms_base/tests/resolver/issue-7248/input.js
new file mode 100644
index 0000000000..8986164c59
--- /dev/null
+++ b/crates/swc_ecma_transforms_base/tests/resolver/issue-7248/input.js
@@ -0,0 +1,9 @@
+const messages = [{ message: "hello" }];
+const logs = messages.map(
+    ({ log = () => console.log(message), message }) => log
+);
+logs[0]();
+
+class A {
+    constructor({ log = () => console.log(message), message }) {}
+}
diff --git a/crates/swc_ecma_transforms_base/tests/resolver/issue-7248/output.js b/crates/swc_ecma_transforms_base/tests/resolver/issue-7248/output.js
new file mode 100644
index 0000000000..cb5517272f
--- /dev/null
+++ b/crates/swc_ecma_transforms_base/tests/resolver/issue-7248/output.js
@@ -0,0 +1,10 @@
+const messages__2 = [
+    {
+        message: "hello"
+    }
+];
+const logs__2 = messages__2.map(({ log__3 =()=>console.log(message__3) , message__3  })=>log__3);
+logs__2[0]();
+class A__2 {
+    constructor({ log__4 =()=>console.log(message__4) , message__4  }){}
+}
diff --git a/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/2/output.ts b/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/2/output.ts
index 97812b7117..286b0bb890 100644
--- a/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/2/output.ts
+++ b/crates/swc_ecma_transforms_base/tests/ts-resolver/issue-5622/2/output.ts
@@ -25,10 +25,10 @@ function defaultArgFunction__2(a__9 = function() {
 }, b__9 = 1) {}
 function defaultArgArrow__2(a__11 = ()=>()=>b__11, b__11 = 3) {}
 class C__2 {
-    constructor(a__12 = b, b__12 = 1){}
+    constructor(a__12 = b__12, b__12 = 1){}
     method(a__13 = b__13, b__13 = 1) {}
 }
-var x__2 = (a__14 = b, b__14 = c, c__14 = d)=>{
+var x__2 = (a__14 = b__14, b__14 = c__14, c__14 = d)=>{
     var d__14;
 };
 function f__2(a__15, b__15 = function() {