Repository: swc-project/swc (rust)

Issue:
Incorrect compressor behavior in switch
### Describe the bug

See example

### Input code

```typescript
const getString = () => {
  switch ("apple") {
    case 'apple':
      return '1';
    case 'banana':
      return '2';
  }
  return "3"
};


console.log(getString());
```


### Config

```json
{
 "jsc": {
  "parser": {
   "syntax": "ecmascript",
  },
  "target": "es5",
  "minify": {
    "mangle": false,
    "compress": true,
  }
 },
}
```


### Playground link (or link to the minimal reproduction)

https://play.swc.rs/?version=1.7.28&code=H4sIAAAAAAAAA0vOzysuUUhPLQkuKcrMS1ewVdDQVLC1U6jm5VJQKC7PLEnOUNBQSiwoyElV0oSIKigkJxanKqiDBdWtIEIKCkWpJaVFeQrqhurWyKqSEvOAEFOZEURZLYiAiikZK%2FFy1QKFQTAZ6LD8nFS9nPx0DbjzNDQ1rQEoac67sgAAAA%3D%3D&config=H4sIAAAAAAAAAzWMQQqFMAwF9z1FyNqtG28TSpSKrSWJoEjvbqz%2Fbx7MDLw7AK4acYI7AGAlUZYfAepVjE5H5JhJo6RqOHhq76CRLGw969g95lTSfP0PnKksGzvPtCkPn4x7rsKqrk2Oblt4P9sDpwS%2Bn48AAAA%3D

### SWC Info output

_No response_

### Expected behavior

```js
console.log('1');
```

### Actual behavior

```js
console.log('3');
```

### Version

1.7.28

### Additional context

_No response_

Pull request description:
fix(es/minifier): Only merge last if return
<!-- 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:**

<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->

**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):**
Closes #9628

Patch:
diff --git a/.changeset/good-lions-design.md b/.changeset/good-lions-design.md
new file mode 100644
index 0000000000..15b155573d
--- /dev/null
+++ b/.changeset/good-lions-design.md
@@ -0,0 +1,6 @@
+---
+swc_core: patch
+swc_ecma_minifier: patch
+---
+
+fix(es/minifier): Only merge last if return
diff --git a/.changeset/wicked-windows-occur.md b/.changeset/wicked-windows-occur.md
new file mode 100644
index 0000000000..49e23d989e
--- /dev/null
+++ b/.changeset/wicked-windows-occur.md
@@ -0,0 +1,6 @@
+---
+swc_core: patch
+swc_ecma_lints: patch
+---
+
+fix(es/lints): Correct the false positive error of TS2309
diff --git a/crates/swc_ecma_lints/src/rules/duplicate_exports.rs b/crates/swc_ecma_lints/src/rules/duplicate_exports.rs
index fca3ffdd2f..942990e04a 100644
--- a/crates/swc_ecma_lints/src/rules/duplicate_exports.rs
+++ b/crates/swc_ecma_lints/src/rules/duplicate_exports.rs
@@ -1,4 +1,4 @@
-use std::collections::hash_map::Entry;
+use std::{collections::hash_map::Entry, mem};
 
 use swc_atoms::JsWord;
 use swc_common::{collections::AHashMap, errors::HANDLER, Span};
@@ -82,7 +82,9 @@ impl Visit for DuplicateExports {
 
     fn visit_ts_module_decl(&mut self, d: &TsModuleDecl) {
         if !d.declare {
+            let old = mem::take(self);
             d.visit_children_with(self);
+            *self = old;
         }
     }
 
diff --git a/crates/swc_ecma_minifier/src/compress/optimize/if_return.rs b/crates/swc_ecma_minifier/src/compress/optimize/if_return.rs
index e5ad4d9de2..e7fe6b811c 100644
--- a/crates/swc_ecma_minifier/src/compress/optimize/if_return.rs
+++ b/crates/swc_ecma_minifier/src/compress/optimize/if_return.rs
@@ -494,16 +494,16 @@ impl Optimizer<'_> {
         }
     }
 
-    fn can_merge_stmt_as_if_return(&self, s: &Stmt, _is_last: bool) -> bool {
+    fn can_merge_stmt_as_if_return(&self, s: &Stmt, is_last: bool) -> bool {
         // if !res {
         //     trace!("Cannot merge: {}", dump(s));
         // }
 
         match s {
             Stmt::Expr(..) => true,
-            Stmt::Return(..) => true,
+            Stmt::Return(..) => is_last,
             Stmt::Block(s) => {
-                s.stmts.len() == 1 && self.can_merge_stmt_as_if_return(&s.stmts[0], false)
+                s.stmts.len() == 1 && self.can_merge_stmt_as_if_return(&s.stmts[0], is_last)
             }
             Stmt::If(stmt) => {
                 matches!(&*stmt.cons, Stmt::Return(..))


Test patch:
diff --git a/crates/swc_ecma_lints/tests/pass/issue-9632/1/input.ts b/crates/swc_ecma_lints/tests/pass/issue-9632/1/input.ts
new file mode 100644
index 0000000000..ab9852c08a
--- /dev/null
+++ b/crates/swc_ecma_lints/tests/pass/issue-9632/1/input.ts
@@ -0,0 +1,9 @@
+import * as meta from "./meta.js";
+
+function nameof(obj: unknown) { }
+
+namespace nameof {
+    export import version = meta.version;
+}
+
+export = nameof;
\ No newline at end of file
diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/9628/input.js b/crates/swc_ecma_minifier/tests/fixture/issues/9628/input.js
new file mode 100644
index 0000000000..d72cd31502
--- /dev/null
+++ b/crates/swc_ecma_minifier/tests/fixture/issues/9628/input.js
@@ -0,0 +1,11 @@
+const getString = () => {
+    switch ("apple") {
+        case "apple":
+            return "1";
+        case "banana":
+            return "2";
+    }
+    return "3";
+};
+
+console.log(getString());
diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/9628/output.js b/crates/swc_ecma_minifier/tests/fixture/issues/9628/output.js
new file mode 100644
index 0000000000..eaedf96c62
--- /dev/null
+++ b/crates/swc_ecma_minifier/tests/fixture/issues/9628/output.js
@@ -0,0 +1,1 @@
+console.log("1");