Repository: swc-project/swc (rust)

Issue:
if_return returns unreachable code
### Describe the bug

see example

### Input code

```typescript
const IndexPage = () => {
  if (value === "loading") {
    return 1;
  } else if (value === "error") {
    return 2;
  } else {
    return 3;
  }
  return 4;
};
```


### Config

```json
{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": false
    },
    "target": "es2019",
    "loose": false,
    "minify": {
      "compress": {
        "arguments": false,
        "arrows": true,
        "booleans": true,
        "booleans_as_integers": false,
        "collapse_vars": true,
        "comparisons": true,
        "computed_props": false,
        "conditionals": false,
        "dead_code": false,
        "directives": false,
        "drop_console": false,
        "drop_debugger": true,
        "evaluate": true,
        "expression": false,
        "hoist_funs": false,
        "hoist_props": true,
        "hoist_vars": false,
        "if_return": true,
        "join_vars": true,
        "keep_classnames": false,
        "keep_fargs": true,
        "keep_fnames": false,
        "keep_infinity": false,
        "loops": true,
        "negate_iife": true,
        "properties": true,
        "reduce_funcs": false,
        "reduce_vars": false,
        "side_effects": true,
        "switches": false,
        "typeofs": true,
        "unsafe": false,
        "unsafe_arrows": false,
        "unsafe_comps": false,
        "unsafe_Function": false,
        "unsafe_math": false,
        "unsafe_symbols": false,
        "unsafe_methods": false,
        "unsafe_proto": false,
        "unsafe_regexp": false,
        "unsafe_undefined": false,
        "unused": true
      },
      "toplevel": true,
      "mangle": false
    }
  },
  "module": {
    "type": "es6"
  },
  "minify": false,
  "isModule": true
}
```


### Playground link

https://play.swc.rs/?version=1.2.124&code=H4sIAAAAAAAAA0vOzysuUfDMS0mtCEhMT1WwVdDQVLC1U6jmUlDITFPQKEvMKQWK2toqKOXkJ6Zk5qUraYIlFRSKUktKi%2FIUDK2BvFqF1JziVHQdqUVF%2BUXo6o2Q1KNIGIMluOB8E2uuWmsAX3KG16AAAAA%3D&config=H4sIAAAAAAAAA22TTbLbIAzH7%2BJ1Fm0Xnek7QHc9A0NAOLwCYpDIiyeTu1fYDraT7tCPv4S%2BuA%2BfZIaP%2B5B1ISjtRFNifRs%2BBjBRkyk%2B83ASmSCnA8HjNLAuI3CT0I9v33%2FJdUAkWAWnIfrk3dSCGYy5AFE7i1ONkJi6TpeCX2JyqWKdEQPo9GYrTconhhHK5mowBJ0J1FWX7tFe08UTpgOqDFblgnnvnqxnj0nMDi1oqwzarRDrCxj2V9iJJI6IEklyR2jhXMexNXF5Gq46VM3Q7dvcCnm0%2B13QEytXE72gNdvFcUFLoavKO1WAa0lPzSf6dOjFXwDJM2iipOMu%2F5k7mcVR6f6j8snJIHnqVKa8ZZVglOKU965X2LKGwh66qICtBlqFZgu%2BwkNB5C0ocE7a3Z3py7O57LLiKQO6fi9t024bwmKq51IdaduDN%2Fhb0uL9PFYeNV9eGU3xjOEtRAS%2BoH3D0gnGV1hkhW%2F5ldZkQfoMdndRqZmtyvbbMAe4QniWHXUa%2B%2B49RBDR1gbuc4Pmb%2FlzeGzf8Lkz9GcVzoH%2FAau%2FxYX7AwAA

### Expected behavior

```js
const IndexPage = ()=>"loading" === value ? 1 : "error" === value ? 2 : 3;
```

### Actual behavior

```js
const IndexPage = ()=>"loading" === value ? 1 : "error" === value ? 2 : 4;
```

### Version

1.2.124

### Additional context

_No response_

Pull request description:
fix(es/minifier): Drop unreachable statements eagerly
swc_ecma_minifier:
 - `pure`: Drop unreachable statements. (Closes #3173)

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 89565731a4..c320f2f45e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,12 @@
 # Changelog
 ## [unreleased]
 
+### Bug Fixes
+
+
+
+- **(es/minifier)** Disable inlining of expressions from `collapse_vars` (#3200) ([69b5f79](https://github.com/swc-project/swc/commit/69b5f799f3d40947ce3b5bc851ee44d3caad5328))
+
 ### Features
 
 
diff --git a/Cargo.lock b/Cargo.lock
index aaf4774335..21d0073c01 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3021,7 +3021,7 @@ dependencies = [
 
 [[package]]
 name = "swc_ecma_minifier"
-version = "0.64.0"
+version = "0.64.1"
 dependencies = [
  "ahash",
  "ansi_term",
diff --git a/crates/swc_ecma_minifier/Cargo.toml b/crates/swc_ecma_minifier/Cargo.toml
index bea6cad95c..3bf3bab70a 100644
--- a/crates/swc_ecma_minifier/Cargo.toml
+++ b/crates/swc_ecma_minifier/Cargo.toml
@@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "src/lists/*.json"]
 license = "Apache-2.0"
 name = "swc_ecma_minifier"
 repository = "https://github.com/swc-project/swc.git"
-version = "0.64.0"
+version = "0.64.1"
 
 [package.metadata.docs.rs]
 all-features = true
diff --git a/crates/swc_ecma_minifier/src/compress/drop_console.rs b/crates/swc_ecma_minifier/src/compress/drop_console.rs
index 7b66b31c10..e9a9daf820 100644
--- a/crates/swc_ecma_minifier/src/compress/drop_console.rs
+++ b/crates/swc_ecma_minifier/src/compress/drop_console.rs
@@ -72,7 +72,7 @@ impl VisitMut for DropConsole {
                             }
                         }
 
-                        // Sioplifier will remove side-effect-free items.
+                        // Simplifier will remove side-effect-free items.
                         *n = Expr::Seq(SeqExpr {
                             span: *span,
                             exprs: take(args).into_iter().map(|arg| arg.expr).collect(),
diff --git a/crates/swc_ecma_minifier/src/compress/pure/if_return.rs b/crates/swc_ecma_minifier/src/compress/pure/if_return.rs
index eeee117fd5..9d276a53a1 100644
--- a/crates/swc_ecma_minifier/src/compress/pure/if_return.rs
+++ b/crates/swc_ecma_minifier/src/compress/pure/if_return.rs
@@ -1,9 +1,43 @@
 use super::Pure;
-use crate::compress::util::{is_fine_for_if_cons, negate};
+use crate::compress::util::{always_terminates, is_fine_for_if_cons, negate};
 use swc_common::{util::take::Take, DUMMY_SP};
 use swc_ecma_ast::*;
 
 impl<M> Pure<'_, M> {
+    pub(super) fn drop_unreachable_stmts(&mut self, stmts: &mut Vec<Stmt>) {
+        if !self.options.dead_code && !self.options.side_effects {
+            return;
+        }
+
+        let idx = stmts
+            .iter()
+            .enumerate()
+            .find(|(_, stmt)| always_terminates(&stmt));
+
+        if let Some((idx, _)) = idx {
+            stmts.iter_mut().skip(idx + 1).for_each(|stmt| match stmt {
+                Stmt::Decl(
+                    Decl::Var(VarDecl {
+                        kind: VarDeclKind::Var,
+                        ..
+                    })
+                    | Decl::Fn(..),
+                ) => {
+                    // Preserve
+                }
+
+                Stmt::Empty(..) => {
+                    // noop
+                }
+
+                _ => {
+                    self.changed = true;
+                    stmt.take();
+                }
+            });
+        }
+    }
+
     /// # Input
     ///
     /// ```js
diff --git a/crates/swc_ecma_minifier/src/compress/pure/mod.rs b/crates/swc_ecma_minifier/src/compress/pure/mod.rs
index 2f5bad7de2..1ba2fed238 100644
--- a/crates/swc_ecma_minifier/src/compress/pure/mod.rs
+++ b/crates/swc_ecma_minifier/src/compress/pure/mod.rs
@@ -95,6 +95,8 @@ where
     }
 
     fn optimize_fn_stmts(&mut self, stmts: &mut Vec<Stmt>) {
+        self.drop_unreachable_stmts(stmts);
+
         self.remove_useless_return(stmts);
 
         self.negate_if_terminate(stmts, true, false);
diff --git a/cspell.json b/cspell.json
index 9cb0df5289..65c9fb9bc5 100644
--- a/cspell.json
+++ b/cspell.json
@@ -100,6 +100,7 @@
         "nncs",
         "noinline",
         "NOINLINE",
+        "optimizable",
         "paren",
         "Paren",
         "pmutil",


Test patch:
diff --git a/crates/swc_ecma_minifier/tests/compress/fixture/issues/2257/full/output.js b/crates/swc_ecma_minifier/tests/compress/fixture/issues/2257/full/output.js
index 9710b9c8db..1affd62af8 100644
--- a/crates/swc_ecma_minifier/tests/compress/fixture/issues/2257/full/output.js
+++ b/crates/swc_ecma_minifier/tests/compress/fixture/issues/2257/full/output.js
@@ -17340,13 +17340,8 @@
         },
         87832: function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
             "use strict";
-            __webpack_require__.r(__webpack_exports__);
-            var prefix = "Invariant failed";
-            __webpack_exports__.default = function(condition, message) {
-                if (!condition) {
-                    throw new Error(prefix);
-                    throw new Error(prefix + ": " + (message || ""));
-                }
+            __webpack_require__.r(__webpack_exports__), __webpack_exports__.default = function(condition, message) {
+                if (!condition) throw new Error("Invariant failed");
             };
         },
         98009: function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
diff --git a/crates/swc_ecma_minifier/tests/compress/fixture/issues/3173/1/input.js b/crates/swc_ecma_minifier/tests/compress/fixture/issues/3173/1/input.js
new file mode 100644
index 0000000000..2182f5d5d6
--- /dev/null
+++ b/crates/swc_ecma_minifier/tests/compress/fixture/issues/3173/1/input.js
@@ -0,0 +1,10 @@
+export const IndexPage = (value) => {
+    if (value === "loading") {
+        return 1;
+    } else if (value === "error") {
+        return 2;
+    } else {
+        return 3;
+    }
+    return 4;
+};
\ No newline at end of file
diff --git a/crates/swc_ecma_minifier/tests/compress/fixture/issues/3173/1/output.js b/crates/swc_ecma_minifier/tests/compress/fixture/issues/3173/1/output.js
new file mode 100644
index 0000000000..dc3175a527
--- /dev/null
+++ b/crates/swc_ecma_minifier/tests/compress/fixture/issues/3173/1/output.js
@@ -0,0 +1,2 @@
+export const IndexPage = (value)=>"loading" === value ? 1 : "error" === value ? 2 : 3
+;