Repository: swc-project/swc (rust)

Issue:
Minify error: evaluate error in inline function
### Describe the bug

`bit & 2` should be `0` instead of `1`

### Input code

```typescript
function foo(bit) {
    a = !(bit & 1)
    b = !(bit & 2)
    return a + b
};
window.v = foo(1);
```


### Config

```json
{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": false,
      "decorators": true
    },
    "transform": {
      "decoratorMetadata": true
    },
    "externalHelpers": true,
    "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,
        "passes": 5
      },
      "mangle": false
    }
  },
  "module": {
    "type": "es6"
  },
  "minify": false,
  "isModule": true
}
```


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

https://play.swc.rs/?version=1.5.8&code=H4sIAAAAAAAAA0srzUsuyczPU0jLz9dIyizRVKjmUgCCRAVbBUWQgIKagqEmWCgJScgIIlSUWlJalAdUrK2QxFVrzVWemZeSX65XBlQJMs9Q0xoAwEMNeGAAAAA%3D&config=H4sIAAAAAAAAA32VzXLiMAyA730KJue9dg%2F7AJ299Bk8IpaDu46VsRQK0%2BHdV3FCSkHhBvr0L1n5etntmg9umz%2B7L%2F2pfwYojGX9rxI%2BZ4GTSho5D8htiYM0v65UeEIBEuMq89hSAaHCiqSMWMFl5o0UyByo9LdBVpN3FPAgYFniSbBkSH8xDbg6v7qF0qFMaSK%2FLvk1iYjxZ35NH3MM59vgLfVDQeYbmUrV39hjFr6vr7JCnz8TqPI9UUItb5s4YBezYDcXcO%2B4pZRgYHRHKIaXKVMokckKMcFR0Luh0GDy7KNE0g4a1CN415JHA8WCrcQjWmYaS80ya3lGPRV73I9dV7fqzhqPkEYQIyae6kg0W8PrgSKLC2O2WjjDjR7McGnuvWUMrqCMJT%2FafVDMGzP5h6gdSMCcoUfLb9UIuk9b1uGpZcxBV1bOBtf9tqrM2GlTXYzB6OzUGSwSrWkW9GOLU2dbK50Fb7SPo0eHIeiuGK75M0p7sIJOZ4WCAXS%2BEKytmoFbX%2BEGnx7EE%2FymVYq9YItGD3LYpnzu95SeBOhRDuSfKOgohLZx0StxGrb5mD3qaqA3VUau4PEI6AMQcqkey4fd0OehHl2XaG%2BeiUH3vA7xdZFd1rPfQ%2B6%2Bj8B8uV8WhaYnP1a4fGemoc%2FH%2BnfzrXQ9zWs1TeT3q2X9Hlz%2BA96ili6zBgAA

### SWC Info output

_No response_

### Expected behavior

should be `window.v = (a = !1) + (b = !0);`


### Actual behavior

_No response_

### Version

1.5.8

### Additional context

_No response_

Pull request:
fix(es/minifier): Add type check to `&` and `|`
**Description:**

**Related issue:**

 - Closes #8964

Patch:
diff --git a/crates/swc_ecma_minifier/src/compress/mod.rs b/crates/swc_ecma_minifier/src/compress/mod.rs
index 834f8d51f0..e63d784d29 100644
--- a/crates/swc_ecma_minifier/src/compress/mod.rs
+++ b/crates/swc_ecma_minifier/src/compress/mod.rs
@@ -188,6 +188,9 @@ impl Compressor<'_> {
 
             let start_time = now();
 
+            #[cfg(feature = "debug")]
+            let start = n.dump();
+
             let mut visitor = expr_simplifier(self.marks.unresolved_mark, ExprSimplifierConfig {});
             n.apply(&mut visitor);
 
@@ -196,7 +199,10 @@ impl Compressor<'_> {
                 debug!("compressor: Simplified expressions");
                 #[cfg(feature = "debug")]
                 {
-                    debug!("===== Simplified =====\n{}", dump(&*n, false));
+                    debug!(
+                        "===== Simplified =====\n{start}===== ===== ===== =====\n{}",
+                        n.dump()
+                    );
                 }
             }
 
diff --git a/crates/swc_ecma_utils/src/lib.rs b/crates/swc_ecma_utils/src/lib.rs
index f2937ba7ee..aa1292659b 100644
--- a/crates/swc_ecma_utils/src/lib.rs
+++ b/crates/swc_ecma_utils/src/lib.rs
@@ -756,6 +756,10 @@ pub trait ExprExt {
                 ref right,
                 ..
             }) => {
+                if left.get_type() != Known(BoolType) || right.get_type() != Known(BoolType) {
+                    return (MayBeImpure, Unknown);
+                }
+
                 // TODO: Ignore purity if value cannot be reached.
 
                 let (lp, lv) = left.cast_to_bool(ctx);


Test patch:
diff --git a/crates/swc_ecma_minifier/tests/exec.rs b/crates/swc_ecma_minifier/tests/exec.rs
index ff42d21131..d2cfbc610b 100644
--- a/crates/swc_ecma_minifier/tests/exec.rs
+++ b/crates/swc_ecma_minifier/tests/exec.rs
@@ -11278,3 +11278,18 @@ fn issue_8943() {
         ",
     );
 }
+
+#[test]
+fn issue_8964() {
+    run_default_exec_test(
+        "
+        function foo(bit) {
+            a = !(bit & 1)
+            b = !(bit & 2)
+            return a + b
+        };
+        
+        console.log(foo(1));
+        ",
+    );
+}
diff --git a/crates/swc_ecma_minifier/tests/terser/compress/issue_597/issue_1724/output.js b/crates/swc_ecma_minifier/tests/terser/compress/issue_597/issue_1724/output.js
index 15dc8997bf..bd1de30903 100644
--- a/crates/swc_ecma_minifier/tests/terser/compress/issue_597/issue_1724/output.js
+++ b/crates/swc_ecma_minifier/tests/terser/compress/issue_597/issue_1724/output.js
@@ -1,3 +1,3 @@
 var a = 0;
-++a, a++;
+++a % (1 / 0) | 1 / 0 ? a++ : 0;
 console.log(a);
diff --git a/crates/swc_ecma_minifier/tests/terser/compress/issue_640/conditional/output.js b/crates/swc_ecma_minifier/tests/terser/compress/issue_640/conditional/output.js
index 5b5f9574c7..ea4749f246 100644
--- a/crates/swc_ecma_minifier/tests/terser/compress/issue_640/conditional/output.js
+++ b/crates/swc_ecma_minifier/tests/terser/compress/issue_640/conditional/output.js
@@ -1,6 +1,6 @@
-a(), b();
-a(), b();
-a();
+1 | a() ? b() : c();
+1 | a() && b();
+1 | a() || c();
 a();
 b();
 b();
diff --git a/crates/swc_ecma_transforms_optimization/src/simplify/branch/tests.rs b/crates/swc_ecma_transforms_optimization/src/simplify/branch/tests.rs
index c824614f8e..e01c55468f 100644
--- a/crates/swc_ecma_transforms_optimization/src/simplify/branch/tests.rs
+++ b/crates/swc_ecma_transforms_optimization/src/simplify/branch/tests.rs
@@ -165,8 +165,8 @@ fn test_if() {
         "} else log(3);",
     ));
     test_same("if (0 | x) y = 1; else y = 2;");
-    test("if (1 | x) y = 1; else y = 2;", "y=1;");
-    test("if (0 & x) y = 1; else y = 2;", "y=2");
+    // test("if (1 | x) y = 1; else y = 2;", "y=1;");
+    // test("if (0 & x) y = 1; else y = 2;", "y=2");
     test_same("if (1 & x) y = 1; else y = 2;");
 }