Repository: swc-project/swc (rust)

Issue:
Minifier evaluates `toString` of array containing 1-empty hole to invalid expression when `unsafe` is true
### Describe the bug

Currently with `unsafe` option, minifier reduces `toString` call expression with 1-item array.
When the only item in that array is empty hole, minifier results wrong output. 

### Input code

```typescript
console.log([,].toString());
```


### 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": true,
        "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,
        "passes": 3
      },
      "mangle": false
    }
  },
  "module": {
    "type": "es6"
  },
  "minify": false,
  "isModule": true
}
```


### Playground link (or link to the minimal reproduction)

https://play.swc.rs/?version=1.4.6&code=H4sIAAAAAAAAA0vOzyvOz0nVy8lP14jWidUryQ8uKcrMS9fQ1LQGAONauCgcAAAA&config=H4sIAAAAAAAAA32US47bMAyG9zlF4HUXRQp00QN01zMIikU5SvUwRCoTY5C7l5aVTJrQ3tn89JPiQ%2Fzc7ffdGfvu1%2F6TP%2Fln1BkhP%2F7ZglMkfWVLB33Q2Gc3UvftTs84I6s9QjXdFtKRzgNQVeHh%2B%2BHQFJ1PCeGuaLbgorPTc8w%2BhTED4pONreyyBIiE%2F%2Bsby%2BljBpTLs%2F2YkgcdN4jSqFwkGCBLjvvkvR4R1EVnwct8U50dJinEDAuBUWNOo8ijceRS5Jjv1IA2qk8GBOQy9OQuIMk4FssicnpCPhUbOJZhqH1%2BUcNF%2B6JJiAnX2hK%2BreD1lBySsiVKJVzgSg0W2Ir7qnRWZaCS47vunFxc6clfAK6A14hRB5D81hOW52lNbTeVLloeWZoEzvMtZRlh4KIq56xQ2bkykMlJ3cxgSg9zZXvpOg2vlA%2BdAQXW8qwIrvHDUX%2BSgtI0QrIC4P5qKYPFrh6P8PUijc%2FvYQP%2F5iRJnq92Img6rVOcwjH5jQAB6JTMxgHuBKV1nHlJXMd1XqIBngww4pGCFbzvAJ5%2FSsrXdfk2Gvw62KMafDqKW2LkMa89%2FNFst8duDjoOXztgWc%2B7dqALyZQK2%2BKfe76s65%2Fd16H7Zn5k0zn8c1fON9nd%2FgFe41a3RAYAAA%3D%3D

### SWC Info output

_No response_

### Expected behavior

```javascript
console.log("")
```
or don't minify it

### Actual behavior

```javascript
console.log((void 0).toString())
```

### Version

1.4.6

### Additional context

_No response_

Pull request:
fix(es/minifier): Fix eval of `toString` of array with holes
**Description:**


**Related issue:**

 - Closes #8717.

Patch:
diff --git a/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs b/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs
index c1b7ff797f..cd2ac1aea2 100644
--- a/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs
+++ b/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs
@@ -132,7 +132,10 @@ impl Pure<'_> {
                 return;
             }
 
-            if self.options.unsafe_passes && &*method_name.sym == "toString" && arr.elems.len() == 1
+            if self.options.unsafe_passes
+                && &*method_name.sym == "toString"
+                && arr.elems.len() == 1
+                && arr.elems[0].is_some()
             {
                 report_change!("evaluate: Reducing array.toString() call");
                 self.changed = true;


Test patch:
diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/8717/config.json b/crates/swc_ecma_minifier/tests/fixture/issues/8717/config.json
new file mode 100644
index 0000000000..4e7520f965
--- /dev/null
+++ b/crates/swc_ecma_minifier/tests/fixture/issues/8717/config.json
@@ -0,0 +1,48 @@
+{
+    "defaults": true,
+    "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": true,
+    "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,
+    "passes": 3
+}
diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/8717/input.js b/crates/swc_ecma_minifier/tests/fixture/issues/8717/input.js
new file mode 100644
index 0000000000..c4126afc33
--- /dev/null
+++ b/crates/swc_ecma_minifier/tests/fixture/issues/8717/input.js
@@ -0,0 +1,1 @@
+console.log([,].toString());
diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/8717/output.js b/crates/swc_ecma_minifier/tests/fixture/issues/8717/output.js
new file mode 100644
index 0000000000..8f7c4598e1
--- /dev/null
+++ b/crates/swc_ecma_minifier/tests/fixture/issues/8717/output.js
@@ -0,0 +1,3 @@
+console.log([
+    , 
+].toString());