Repository: swc-project/swc (rust)

Issue:
minifier: Expand an argument with a spread with an array
### Describe the feature

```js
function logTheNine() {
    ((theThree, theNine)=>{
        console.log(theNine);
    })(...[
        3,
        9
    ]);
}
logTheNine();


```

=>

```js
function logTheNine() {
    ((theThree, theNine)=>{
        console.log(theNine);
    })(
        3,
        9
    );
}
logTheNine();


```

### Babel plugin or link to the feature description

_No response_

### Additional context

_No response_

Pull request description:
feat(es/minifier): Evaluate spread of arrays
**Description:**


**Related issue:**

 - Closes #8808

Patch:
diff --git a/crates/swc_ecma_minifier/src/compress/pure/misc.rs b/crates/swc_ecma_minifier/src/compress/pure/misc.rs
index dea9485d66..33fa6915a4 100644
--- a/crates/swc_ecma_minifier/src/compress/pure/misc.rs
+++ b/crates/swc_ecma_minifier/src/compress/pure/misc.rs
@@ -7,7 +7,7 @@ use swc_ecma_ast::*;
 use swc_ecma_transforms_optimization::debug_assert_valid;
 use swc_ecma_usage_analyzer::util::is_global_var_with_pure_property_access;
 use swc_ecma_utils::{
-    ExprExt, ExprFactory, IdentUsageFinder, Type,
+    undefined, ExprExt, ExprFactory, IdentUsageFinder, Type,
     Value::{self, Known},
 };
 
@@ -57,6 +57,54 @@ fn can_compress_new_regexp(args: Option<&[ExprOrSpread]>) -> bool {
 }
 
 impl Pure<'_> {
+    /// `foo(...[1, 2])`` => `foo(1, 2)`
+    pub(super) fn eval_spread_array(&mut self, args: &mut Vec<ExprOrSpread>) {
+        if args
+            .iter()
+            .all(|arg| arg.spread.is_none() || !arg.expr.is_array())
+        {
+            return;
+        }
+
+        let mut new_args = vec![];
+        for arg in args.take() {
+            match arg {
+                ExprOrSpread {
+                    spread: Some(spread),
+                    expr,
+                } => match *expr {
+                    Expr::Array(ArrayLit { elems, .. }) => {
+                        for elem in elems {
+                            match elem {
+                                Some(ExprOrSpread { expr, spread }) => {
+                                    new_args.push(ExprOrSpread { spread, expr });
+                                }
+                                None => {
+                                    new_args.push(ExprOrSpread {
+                                        spread: None,
+                                        expr: undefined(DUMMY_SP),
+                                    });
+                                }
+                            }
+                        }
+                    }
+                    _ => {
+                        new_args.push(ExprOrSpread {
+                            spread: Some(spread),
+                            expr,
+                        });
+                    }
+                },
+                arg => new_args.push(arg),
+            }
+        }
+
+        self.changed = true;
+        report_change!("Compressing spread array");
+
+        *args = new_args;
+    }
+
     pub(super) fn remove_invalid(&mut self, e: &mut Expr) {
         match e {
             Expr::Seq(seq) => {
diff --git a/crates/swc_ecma_minifier/src/compress/pure/mod.rs b/crates/swc_ecma_minifier/src/compress/pure/mod.rs
index 9c46f68351..587d381f15 100644
--- a/crates/swc_ecma_minifier/src/compress/pure/mod.rs
+++ b/crates/swc_ecma_minifier/src/compress/pure/mod.rs
@@ -300,6 +300,8 @@ impl VisitMut for Pure<'_> {
 
         e.args.visit_mut_with(self);
 
+        self.eval_spread_array(&mut e.args);
+
         self.drop_arguments_of_symbol_call(e);
     }
 


Test patch:
diff --git a/crates/swc/tests/tsc-references/callWithSpread4.2.minified.js b/crates/swc/tests/tsc-references/callWithSpread4.2.minified.js
index 968e5458a0..b2ed6035dc 100644
--- a/crates/swc/tests/tsc-references/callWithSpread4.2.minified.js
+++ b/crates/swc/tests/tsc-references/callWithSpread4.2.minified.js
@@ -1,6 +1,2 @@
 //// [callWithSpread4.ts]
-pli(reads, ...gun, tr, fun, ...gz, writes), test(...anys), pli(...[
-    reads,
-    writes,
-    writes
-]);
+pli(reads, ...gun, tr, fun, ...gz, writes), test(...anys), pli(reads, writes, writes);
diff --git a/crates/swc/tests/tsc-references/callWithSpreadES6.2.minified.js b/crates/swc/tests/tsc-references/callWithSpreadES6.2.minified.js
index 38a0705a17..35fc4c5f8f 100644
--- a/crates/swc/tests/tsc-references/callWithSpreadES6.2.minified.js
+++ b/crates/swc/tests/tsc-references/callWithSpreadES6.2.minified.js
@@ -4,8 +4,4 @@ var a, obj, xa;
     ...a
 ], [
     ...a
-], obj.foo(1, 2, "abc"), obj.foo(1, 2, ...a), obj.foo(1, 2, ...a, "abc"), obj.foo(1, 2, "abc"), obj.foo(1, 2, ...a), obj.foo(1, 2, ...a, "abc"), xa[1].foo(1, 2, "abc"), xa[1].foo(1, 2, ...a), xa[1].foo(1, 2, ...a, "abc"), xa[1].foo(...[
-    1,
-    2,
-    "abc"
-]);
+], obj.foo(1, 2, "abc"), obj.foo(1, 2, ...a), obj.foo(1, 2, ...a, "abc"), obj.foo(1, 2, "abc"), obj.foo(1, 2, ...a), obj.foo(1, 2, ...a, "abc"), xa[1].foo(1, 2, "abc"), xa[1].foo(1, 2, ...a), xa[1].foo(1, 2, ...a, "abc"), xa[1].foo(1, 2, "abc");
diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/8806/output.js b/crates/swc_ecma_minifier/tests/fixture/issues/8806/output.js
index 40a257d077..f1e4f71b4b 100644
--- a/crates/swc_ecma_minifier/tests/fixture/issues/8806/output.js
+++ b/crates/swc_ecma_minifier/tests/fixture/issues/8806/output.js
@@ -1,9 +1,4 @@
 function logTheNine() {
-    ((theThree, theNine)=>{
-        console.log(theNine);
-    })(...[
-        3,
-        9
-    ]);
+    console.log(9);
 }
 logTheNine();