diff --git a/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs b/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs index 9918be606..58332ac0e 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs @@ -258,6 +258,9 @@ impl<'a, 'b> PeepholeFoldConstants { let Expression::BinaryExpression(left) = &mut e.left else { return None; }; + if left.operator != op { + return None; + } let (v, expr_to_move); if let Some(result) = ctx.eval_binary_operation(op, &left.left, &e.right) { @@ -1276,6 +1279,13 @@ mod test { test("x = null & 1", "x = 0"); test("x = (2 ** 31 - 1) | 1", "x = 2147483647"); test("x = (2 ** 31) | 1", "x = -2147483647"); + + // https://github.com/oxc-project/oxc/issues/7944 + test_same("(x - 1) & 1"); + test_same("(y >> 3) & 7"); + test("(y & 3) & 7", "y & 3"); + test_same("(y | 3) & 7"); + test("y | 3 & 7", "y | 3"); } #[test] @@ -1364,6 +1374,7 @@ mod test { test_same("z = x * y"); test_same("x = y * 5"); // test("x = y + (z * 24 * 60 * 60 * 1000)", "x = y + z * 864E5"); + test("x = y + (z & 24 & 60 & 60 & 1000)", "x = y + (z & 8)"); } #[test] @@ -1393,6 +1404,52 @@ mod test { test("x = Infinity % 0", "x = NaN"); } + #[test] + fn test_fold_left() { + test_same("(+x - 1) + 2"); // not yet + test("(+x & 1) & 2", "+x & 0"); + } + + #[test] + fn test_fold_left_child_op() { + test_same("x & infinity & 2"); // FIXME: want x & 0 + test_same("x - infinity - 2"); // FIXME: want "x-infinity" + test_same("x - 1 + infinity"); + test_same("x - 2 + 1"); + test_same("x - 2 + 3"); + test_same("1 + x - 2 + 1"); + test_same("1 + x - 2 + 3"); + test_same("1 + x - 2 + 3 - 1"); + test_same("f(x)-0"); + test_same("x-0-0"); // FIXME: want x - 0 + test_same("x+2-2+2"); + test_same("x+2-2+2-2"); + test_same("x-2+2"); + test_same("x-2+2-2"); + test_same("x-2+2-2+2"); + + test_same("1+x-0-na_n"); + test_same("1+f(x)-0-na_n"); + test_same("1+x-0+na_n"); + test_same("1+f(x)-0+na_n"); + + test_same("1+x+na_n"); // unfoldable + test_same("x+2-2"); // unfoldable + test_same("x+2"); // nothing to do + test_same("x-2"); // nothing to do + } + + #[test] + fn test_associative_fold_constants_with_variables() { + // mul and add should not fold + test_same("alert(x * 12 * 20);"); + test_same("alert(12 * x * 20);"); + test_same("alert(x + 12 + 20);"); + test_same("alert(12 + x + 20);"); + test("alert(x & 12 & 20);", "alert(x & 4);"); + test("alert(12 & x & 20);", "alert(x & 4);"); + } + #[test] fn test_to_number() { test("x = +''", "x = 0"); diff --git a/tasks/minsize/minsize.snap b/tasks/minsize/minsize.snap index fdc3b083f..cde7b6963 100644 --- a/tasks/minsize/minsize.snap +++ b/tasks/minsize/minsize.snap @@ -5,23 +5,23 @@ Original | minified | minified | gzip | gzip | Fixture 173.90 kB | 61.61 kB | 59.82 kB | 19.55 kB | 19.33 kB | moment.js -287.63 kB | 92.60 kB | 90.07 kB | 32.26 kB | 31.95 kB | jquery.js +287.63 kB | 92.61 kB | 90.07 kB | 32.27 kB | 31.95 kB | jquery.js 342.15 kB | 121.79 kB | 118.14 kB | 44.59 kB | 44.37 kB | vue.js 544.10 kB | 73.37 kB | 72.48 kB | 26.13 kB | 26.20 kB | lodash.js -555.77 kB | 276.15 kB | 270.13 kB | 91.13 kB | 90.80 kB | d3.js +555.77 kB | 276.22 kB | 270.13 kB | 91.15 kB | 90.80 kB | d3.js 1.01 MB | 467.14 kB | 458.89 kB | 126.74 kB | 126.71 kB | bundle.min.js -1.25 MB | 662.53 kB | 646.76 kB | 163.97 kB | 163.73 kB | three.js +1.25 MB | 662.68 kB | 646.76 kB | 164.00 kB | 163.73 kB | three.js -2.14 MB | 740.87 kB | 724.14 kB | 181.46 kB | 181.07 kB | victory.js +2.14 MB | 740.94 kB | 724.14 kB | 181.49 kB | 181.07 kB | victory.js -3.20 MB | 1.02 MB | 1.01 MB | 332.10 kB | 331.56 kB | echarts.js +3.20 MB | 1.02 MB | 1.01 MB | 332.09 kB | 331.56 kB | echarts.js 6.69 MB | 2.39 MB | 2.31 MB | 496.17 kB | 488.28 kB | antd.js -10.95 MB | 3.55 MB | 3.49 MB | 910.45 kB | 915.50 kB | typescript.js +10.95 MB | 3.55 MB | 3.49 MB | 910.48 kB | 915.50 kB | typescript.js