Repository: swc-project/swc (rust)

Issue:
Switch statement compressed incorrectly
### Describe the bug

A combination of conditionally defined variables and a switch statement is incorrectly compressed

### Input code

```typescript
getInitialProps = (code) => {
  let statusCode, message;

  if (code) {
    statusCode = code;
  }

  switch (statusCode) {
    case 404:
      message = "404";
      break;
    default:
      message = "500";
  }

  return { statusCode, message };
};
```


### Config

```json
{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": false
    },
    "target": "es2022",
    "loose": false,
    "minify": {
      "compress": {
        "arguments": false,
        "arrows": true,
        "booleans": true,
        "booleans_as_integers": false,
        "collapse_vars": true,
        "comparisons": true,
        "computed_props": true,
        "conditionals": true,
        "dead_code": true,
        "directives": true,
        "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": true,
        "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,
        "const_to_let": true,
        "pristine_globals": true
      },
      "mangle": false
    }
  },
  "module": {
    "type": "es6"
  },
  "minify": false,
  "isModule": true
}
```


### Playground link

https://play.swc.rs/?version=1.3.86&code=H4sIAAAAAAAAA22OsRKCMBBEe75ihwpnLCiwMYONlR2%2FEMOBGRGc3GUsGP7dRI1aUO7u273rSU6jFauHxk13Ro3CTC1tUB8wZ8BAAhYtno%2FB3uJGzLonlYXMdgmOJP64MBMDFewlkvywYi4ofkTqGM2Eqqz2L4W0Hwby4ObqY58d6etbtNRpP8hKYVeW%2BfekI%2FFuxLz2PRaVLeoJj1yYHvsAAAA%3D&config=H4sIAAAAAAAAA32UO3LjMAyG%2B5zCozrFjostcoDtcgYOTYIyvXxoCNCxJuO7L0TJj40hdRI%2B%2FAAJgPh%2B2%2B26E5ruY%2FfNn%2Fwz6IJQ7v9swTGRvrClAxM1muIH6t5v9IQTcjogNNN1Jh3p0gM1Fe5%2F7feLogs5I9wUiy365N34nNPkOBRAfLKxlUPWCInwf%2F3CSv6aAJX6bD%2FkHECnDaI0Kp8IeihSYJND0AOCOusiRJlOqovHLKWYYCWwaih5EHmynnxOnPOVWtBWmWxBQL6AIX8GSca5WJaQryfcp2ELh9r3rc8%2F1HDWoWoScsKltYRPK0Q9Zo%2BkXE1SCWe4UoMZLsX9qfROFaBa0qvulH1a6clfAK5A0IhJR5DiNg%2FH87SmdptKnxyPLI0C5%2FmWbpmg56Iq751Q2akyUMhL3Sxgq4GpskY6zoJXyofeggLneFaE0PjlyRylpDQOkJ0AuL%2FaSVM1A3V%2FhSt8ehAb%2BA%2FfkuQBWzyipuM6xTEecthIEIGO2W44cCsor%2BPCW%2BIyrPOaLPBogBVdKjbwugT4AVBWoe3Ll9ng58ERVR%2Fy4bEmFofrfQ9HnfrHe59X8dvi0MVsa4PLkp%2F6O6%2Fm393D6baF7wfvPH7elC3p9R%2BoYzQdMAYAAA%3D%3D

### SWC Info output

_No response_

### Expected behavior

running `getInitialProps(404)` should return `{ statusCode: 404, message: '404' }`

### Actual behavior

After compression, `{ statusCode: undefined, message: '404' }` is returned instead

### Version

1.3.86

### Additional context

_No response_

Pull request description:
fix(es/minifier): Check if object shorthand is skippable for seq inliner
**Related issue:**

 - Closes #7984 

Patch:
diff --git a/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs b/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs
index 18bc9afd40..5a7a526d6a 100644
--- a/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs
+++ b/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs
@@ -1894,12 +1894,29 @@ impl Optimizer<'_> {
                         }
                         PropOrSpread::Prop(prop) => {
                             // Inline into key
-                            let key = match &mut **prop {
+                            let computed = match &mut **prop {
+                                Prop::Shorthand(_) | Prop::Assign(_) => None,
+                                Prop::KeyValue(prop) => prop.key.as_mut_computed(),
+                                Prop::Getter(prop) => prop.key.as_mut_computed(),
+                                Prop::Setter(prop) => prop.key.as_mut_computed(),
+                                Prop::Method(prop) => prop.key.as_mut_computed(),
+                            };
+
+                            if let Some(computed) = computed {
+                                if self.merge_sequential_expr(a, &mut computed.expr)? {
+                                    return Ok(true);
+                                }
+
+                                if !self.is_skippable_for_seq(Some(a), &computed.expr) {
+                                    return Ok(false);
+                                }
+                            }
+
+                            match &mut **prop {
                                 Prop::Shorthand(shorthand) => {
                                     // We can't ignore shorthand properties
                                     //
                                     // https://github.com/swc-project/swc/issues/6914
-
                                     let mut new_b = Box::new(Expr::Ident(shorthand.clone()));
                                     if self.merge_sequential_expr(a, &mut new_b)? {
                                         *prop = Box::new(Prop::KeyValue(KeyValueProp {
@@ -1908,40 +1925,15 @@ impl Optimizer<'_> {
                                                 shorthand.span.with_ctxt(SyntaxContext::empty()),
                                             )
                                             .into(),
-                                            value: new_b,
+                                            value: new_b.clone(),
                                         }));
                                     }
 
-                                    continue;
-                                }
-                                Prop::KeyValue(prop) => Some(&mut prop.key),
-                                Prop::Assign(_) => None,
-                                Prop::Getter(prop) => Some(&mut prop.key),
-                                Prop::Setter(prop) => Some(&mut prop.key),
-                                Prop::Method(prop) => Some(&mut prop.key),
-                            };
-
-                            if let Some(PropName::Computed(key)) = key {
-                                if self.merge_sequential_expr(a, &mut key.expr)? {
-                                    return Ok(true);
-                                }
-
-                                if !self.is_skippable_for_seq(Some(a), &key.expr) {
-                                    return Ok(false);
-                                }
-                            }
-
-                            match &mut **prop {
-                                Prop::KeyValue(prop) => {
-                                    if self.merge_sequential_expr(a, &mut prop.value)? {
-                                        return Ok(true);
-                                    }
-
-                                    if !self.is_skippable_for_seq(Some(a), &prop.value) {
+                                    if !self.is_skippable_for_seq(Some(a), &new_b) {
                                         return Ok(false);
                                     }
                                 }
-                                Prop::Assign(prop) => {
+                                Prop::KeyValue(prop) => {
                                     if self.merge_sequential_expr(a, &mut prop.value)? {
                                         return Ok(true);
                                     }


Test patch:
diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/7984/input.js b/crates/swc_ecma_minifier/tests/fixture/issues/7984/input.js
new file mode 100644
index 0000000000..b8620aec7f
--- /dev/null
+++ b/crates/swc_ecma_minifier/tests/fixture/issues/7984/input.js
@@ -0,0 +1,17 @@
+getInitialProps = (code) => {
+    let statusCode, message;
+
+    if (code) {
+        statusCode = code;
+    }
+
+    switch (statusCode) {
+        case 404:
+            message = "404";
+            break;
+        default:
+            message = "500";
+    }
+
+    return { statusCode, message };
+};
diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/7984/output.js b/crates/swc_ecma_minifier/tests/fixture/issues/7984/output.js
new file mode 100644
index 0000000000..e3abb638b7
--- /dev/null
+++ b/crates/swc_ecma_minifier/tests/fixture/issues/7984/output.js
@@ -0,0 +1,7 @@
+getInitialProps = (code)=>{
+    let statusCode, message;
+    return code && (statusCode = code), message = 404 === statusCode ? "404" : "500", {
+        statusCode,
+        message
+    };
+};