Repository: swc-project/swc (rust)

Issue:
Improper export with object descructuring
### Describe the bug

When `es5` or lower is picked, `swc` isn't able to properly transpile the following code:

```js
export const {
    a: a2,
    b: b2
} = {a: 1, b: 2}
```

### Input code

```typescript
const {
    a: a1,
    b: b1
} = {a: 1, b: 2}

export const {
    a: a2,
    b: b2
} = {a: 1, b: 2}
```


### Config

```json
{
  "jsc": {
    "parser": {
      "syntax": "ecmascript"
    },
    "target": "es5"
  }
}
```


### Playground link

_No response_

### Expected behavior

```js
var ref = {
    a: 1,
    b: 2
}, a1 = ref.a, b1 = ref.b;
var ref1 = {
    a: 1,
    b: 2
}, a2 = ref1.a, b2 = ref1.b;
export { a2, b2 };
```


### Version

1.2.111

### Additional context

In output `ES Modules`: we can see that an `ref` object is exported, but in `Common JS`, all 3 `ref`,  `a2`, and `b2` are exported (when only `a2` an `b2` should be exported):

ES Modules | CommonJS
-|-
![image](https://user-images.githubusercontent.com/22725671/143169432-13aaa48d-9784-4a62-887f-14b4bc0b4aad.png)  | ![image](https://user-images.githubusercontent.com/22725671/143169468-f2523a5b-1f63-4f20-a7c1-c22c1886c38e.png)


Pull request:
fix(ecma/transforms): correct export ref in object descructuring
<!-- Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. -->

**Description:**

<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->


**Related issue (if exists):**
fix #2858 


Patch:
diff --git a/crates/swc_ecma_transforms_compat/src/es2015/destructuring.rs b/crates/swc_ecma_transforms_compat/src/es2015/destructuring.rs
index 738970203d..da797290a6 100644
--- a/crates/swc_ecma_transforms_compat/src/es2015/destructuring.rs
+++ b/crates/swc_ecma_transforms_compat/src/es2015/destructuring.rs
@@ -349,11 +349,18 @@ impl AssignFolder {
                 }
 
                 let can_be_null = can_be_null(decl.init.as_ref().unwrap());
-                let ref_ident = make_ref_ident(self.c, decls, decl.init);
+
+                let ref_decls = if self.exporting {
+                    &mut self.vars
+                } else {
+                    decls.as_mut()
+                };
+
+                let ref_ident = make_ref_ident(self.c, ref_decls, decl.init);
 
                 let ref_ident = if can_be_null {
                     let init = Box::new(Expr::Ident(ref_ident.clone()));
-                    make_ref_ident(self.c, decls, Some(init))
+                    make_ref_ident(self.c, ref_decls, Some(init))
                 } else {
                     ref_ident
                 };


Test patch:
diff --git a/crates/swc/tests/fixture/issue-2858/1/input/.swcrc b/crates/swc/tests/fixture/issue-2858/1/input/.swcrc
new file mode 100644
index 0000000000..d662368e3f
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2858/1/input/.swcrc
@@ -0,0 +1,11 @@
+{
+    "jsc": {
+        "parser": {
+            "syntax": "ecmascript"
+        },
+        "target": "es5"
+    },
+    "module": {
+        "type": "es6"
+    }
+}
diff --git a/crates/swc/tests/fixture/issue-2858/1/input/index.js b/crates/swc/tests/fixture/issue-2858/1/input/index.js
new file mode 100644
index 0000000000..6a1d8ccd2f
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2858/1/input/index.js
@@ -0,0 +1,9 @@
+const {
+    a: a1,
+    b: b1
+} = {a: 1, b: 2}
+
+export const {
+    a: a2,
+    b: b2
+} = {a: 1, b: 2}
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issue-2858/1/output/index.js b/crates/swc/tests/fixture/issue-2858/1/output/index.js
new file mode 100644
index 0000000000..b404ebbeff
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2858/1/output/index.js
@@ -0,0 +1,9 @@
+var ref = {
+    a: 1,
+    b: 2
+}, a1 = ref.a, b1 = ref.b;
+var ref1 = {
+    a: 1,
+    b: 2
+};
+export var a2 = ref1.a, b2 = ref1.b;
diff --git a/crates/swc/tests/fixture/issue-2858/2/input/.swcrc b/crates/swc/tests/fixture/issue-2858/2/input/.swcrc
new file mode 100644
index 0000000000..2862bc7a82
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2858/2/input/.swcrc
@@ -0,0 +1,11 @@
+{
+    "jsc": {
+        "parser": {
+            "syntax": "ecmascript"
+        },
+        "target": "es5"
+    },
+    "module": {
+        "type": "commonjs"
+    }
+}
diff --git a/crates/swc/tests/fixture/issue-2858/2/input/index.js b/crates/swc/tests/fixture/issue-2858/2/input/index.js
new file mode 100644
index 0000000000..6a1d8ccd2f
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2858/2/input/index.js
@@ -0,0 +1,9 @@
+const {
+    a: a1,
+    b: b1
+} = {a: 1, b: 2}
+
+export const {
+    a: a2,
+    b: b2
+} = {a: 1, b: 2}
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issue-2858/2/output/index.js b/crates/swc/tests/fixture/issue-2858/2/output/index.js
new file mode 100644
index 0000000000..b367e2aa57
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2858/2/output/index.js
@@ -0,0 +1,16 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.b2 = exports.a2 = void 0;
+var ref = {
+    a: 1,
+    b: 2
+}, a1 = ref.a, b1 = ref.b;
+var ref1 = {
+    a: 1,
+    b: 2
+};
+var a2 = ref1.a, b2 = ref1.b;
+exports.a2 = a2;
+exports.b2 = b2;
diff --git a/crates/swc_ecma_transforms_compat/tests/es2015_destructuring.rs b/crates/swc_ecma_transforms_compat/tests/es2015_destructuring.rs
index 6ddb6efe61..7e02ff1eea 100644
--- a/crates/swc_ecma_transforms_compat/tests/es2015_destructuring.rs
+++ b/crates/swc_ecma_transforms_compat/tests/es2015_destructuring.rs
@@ -354,6 +354,58 @@ z = _objectWithoutProperties(_o, ["x", "y"]);
 _o;"#
 );
 
+test!(
+    syntax(),
+    |_| tr(),
+    export_variable_issue_2858_1,
+    r#"export const { a: a2, b: b2 } = { a: 1, b: 2 };"#,
+    r#"
+var ref = {
+    a: 1,
+    b: 2,
+};
+export const a2 = ref.a, b2 = ref.b;
+"#
+);
+
+test!(
+    syntax(),
+    |_| tr(),
+    export_variable_issue_2858_2,
+    r#"export const { a: b } = { a: 1 }"#,
+    r#"
+var ref = {
+    a: 1
+};
+export const b = ref.a;
+"#
+);
+
+test!(
+    syntax(),
+    |_| tr(),
+    export_variable_issue_2858_3,
+    r#"
+export const {
+    a: a1,
+    b: b1,
+    b: { c: c1 },
+} = { a: 1, b: { c: 1 } };
+"#,
+    r#"
+var ref = {
+    a: 1,
+    b: {
+      c: 1,
+    },
+  },
+  _b = ref.b;
+export const a1 = ref.a,
+  b1 = ref.b,
+  c1 = _b.c;
+"#
+);
+
 test!(
     ignore,
     syntax(),