Repository: swc-project/swc (rust)

Issue:
minifier: `Math.min`, `Math.max` evaluate negative zero incorrectly
### Describe the bug

There is a [special step in specification (4.b)](https://tc39.es/ecma262/#sec-math.max) for handling negative zeros in comparison.

### Input code

```typescript
console.log(Math.min(0, -0));
console.log(Math.max(0, -0));
```


### Config

```json
{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": false
    },
    "target": "es5",
    "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": {
        "toplevel": false,
        "keep_classnames": false,
        "keep_fnames": false,
        "keep_private_props": false,
        "ie8": false,
        "safari10": false
      }
    }
  },
  "module": {
    "type": "commonjs"
  },
  "minify": false,
  "isModule": false
}
```


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

https://play.swc.rs/?version=1.5.8&code=H4sIAAAAAAAAA0vOzyvOz0nVy8lP1%2FBNLMnQy83M0zDQUdA10NS05krGkE2sQMgCAHdnCBc8AAAA&config=H4sIAAAAAAAAA42VzW7bMAyA732KwOcdtsOAYg%2Bw255BUCzKUSaJhkilCYq8%2B2jFTtOGNnYJYn78ESmSen%2FZ7boj9d2v3bv8lY%2FRFoJy%2FxYJXTLbs0g66JOlvoSRu28LPdKEvI0ETXS9kY5tGYCbFf2c1buISLCoz7IUcvCXx4A9prEA0YNMpOKvJshMn%2B1nVvBtAlzqo3yPGMHmDWIsmZAZBiia4x5jtCOBOdmieJlOaksg1EJMsDI4MxYcVZ5d4IBZYj5TB9aZHh0oKBToOZxAM5NYYpZJ0lPyadjBvg5Du%2BQv1nCysVpWYsK5XYmcVvF6wEBsfM1aCW9wpQY3OBf3q2XwpgDXkp%2Ftjhjyyp38BZAKREuUbQLNb9Pw0k9r1n7TMmQvLcsXhUt%2Fa1lmGKSoJgSvVHaqDBQO2m0WcLWHqbK9dpwZr5SPggMD3kuvKK7pLXB%2F0ILyZQT0CpD7tV7rqhsw9ylc4dNAbODfkiXrDTZrJMuHdUqXtMe4ESABH9BtKMhVMK7jIlviPK7zmh1Ia4BTVSo18LwEZAAYTWzL8qk3ZDzEoxki7j%2FWxKxwvS%2FhZPPQ5v1hXzKOEU4Q19r4P0Zkk8rZTlNXL5P9NL3wqjWllcELP75%2FejMklZfltyXVJXT1IaHWk9NbIi2UMB%2Bp%2B9Bcno97pC7Qn8X8FuP6D4cPrcHnBgAA

### SWC Info output

_No response_

### Expected behavior

```javascript
console.log(-0);
console.log(0);
```

### Actual behavior

```javascript
console.log(0);
console.log(-0);
```

### Version

1.5.8

### Additional context

_No response_

Pull request:
fix(es/minifier): Fix comparison of `-0.0` and `0`
**Related issue:**

 - Closes #8972

Patch:
diff --git a/crates/swc_ecma_minifier/src/compress/util/mod.rs b/crates/swc_ecma_minifier/src/compress/util/mod.rs
index 7834921313..eed2bbc304 100644
--- a/crates/swc_ecma_minifier/src/compress/util/mod.rs
+++ b/crates/swc_ecma_minifier/src/compress/util/mod.rs
@@ -1,4 +1,4 @@
-use std::f64;
+use std::{cmp::Ordering, f64};
 
 use swc_common::{util::take::Take, DUMMY_SP};
 use swc_ecma_ast::*;
@@ -486,7 +486,7 @@ pub(crate) fn eval_as_number(expr_ctx: &ExprCtx, e: &Expr) -> Option<f64> {
                             return Some(
                                 numbers
                                     .into_iter()
-                                    .max_by(|a, b| a.partial_cmp(b).unwrap())
+                                    .max_by(|&a, &b| cmp_num(a, b))
                                     .unwrap_or(f64::NEG_INFINITY),
                             );
                         }
@@ -504,7 +504,7 @@ pub(crate) fn eval_as_number(expr_ctx: &ExprCtx, e: &Expr) -> Option<f64> {
                             return Some(
                                 numbers
                                     .into_iter()
-                                    .min_by(|a, b| a.partial_cmp(b).unwrap())
+                                    .min_by(|&a, &b| cmp_num(a, b))
                                     .unwrap_or(f64::INFINITY),
                             );
                         }
@@ -758,3 +758,15 @@ impl Visit for SuperFinder {
         self.found = true;
     }
 }
+
+fn cmp_num(a: f64, b: f64) -> Ordering {
+    if a == -0.0 && b == 0.0 {
+        return Ordering::Greater;
+    }
+
+    if a == 0.0 && b == -0.0 {
+        return Ordering::Less;
+    }
+
+    a.partial_cmp(&b).unwrap()
+}


Test patch:
diff --git a/crates/swc_ecma_minifier/tests/exec.rs b/crates/swc_ecma_minifier/tests/exec.rs
index d2cfbc610b..8ac36c3f02 100644
--- a/crates/swc_ecma_minifier/tests/exec.rs
+++ b/crates/swc_ecma_minifier/tests/exec.rs
@@ -11293,3 +11293,21 @@ fn issue_8964() {
         ",
     );
 }
+
+#[test]
+fn issue_8982_1() {
+    run_default_exec_test(
+        "
+        console.log(Math.max(0, -0));
+        ",
+    );
+}
+
+#[test]
+fn issue_8982_2() {
+    run_default_exec_test(
+        "
+        console.log(Math.min(0, -0));
+        ",
+    );
+}