diff --git a/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs b/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs index fa08ba031ec42..8ef342f5e019b 100644 --- a/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs +++ b/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs @@ -1,4 +1,5 @@ use oxc_ast::{ast::*, NONE}; +use oxc_ecmascript::side_effects::MayHaveSideEffects; use oxc_span::{ContentEq, GetSpan}; use oxc_syntax::es_target::ESTarget; @@ -241,14 +242,15 @@ impl<'a> PeepholeOptimizations { } // `a ? b(c, d) : b(e, d)` -> `b(a ? c : e, d)` - if let ( - Expression::Identifier(test), - Expression::CallExpression(consequent), - Expression::CallExpression(alternate), - ) = (&expr.test, &mut expr.consequent, &mut expr.alternate) + if let (Expression::CallExpression(consequent), Expression::CallExpression(alternate)) = + (&mut expr.consequent, &mut expr.alternate) { if consequent.arguments.len() == alternate.arguments.len() - && !ctx.is_global_reference(test) + // we can improve compression by allowing side effects on one side if the other side is + // an identifier that is not modified after it is declared. + // but for now, we only perform compression if neither side has side effects. + && !(ctx.expression_may_have_side_effects(&expr.test) + || ctx.expression_may_have_side_effects(&consequent.callee)) && ctx.expr_eq(&consequent.callee, &alternate.callee) && consequent .arguments @@ -647,9 +649,13 @@ mod test { test("a ? (b, c) : c", "(a && b), c"); test("a ? b || c : c", "(a && b) || c"); test("a ? c : b && c", "(a || b) && c"); - test("var a; a ? b(c, d) : b(e, d)", "var a; b(a ? c : e, d)"); - test("var a; a ? b(...c) : b(...e)", "var a; b(...a ? c : e)"); - test("var a; a ? b(c) : b(e)", "var a; b(a ? c : e)"); + test("var a, b; a ? b(c, d) : b(e, d)", "var a, b; b(a ? c : e, d)"); + test("var a, b; a ? b(...c) : b(...e)", "var a, b; b(...a ? c : e)"); + test("var a, b; a ? b(c) : b(e)", "var a, b; b(a ? c : e)"); + test("var a, b; a === 0 ? b(c) : b(e)", "var a, b; b(a === 0 ? c : e)"); + test_same("var a; a === 0 ? b(c) : b(e)"); // accessing global `b` may assign a different value to `a` + test_same("var b; a === 0 ? b(c) : b(e)"); // accessing global `a` may assign a different value to `b` + test_same("a === 0 ? b(c) : b(e)"); // accessing global `a`, `b` may have a side effect test("a() != null ? a() : b", "a() == null ? b : a()"); test("var a; a != null ? a : b", "var a; a ?? b"); test("var a; (a = _a) != null ? a : b", "var a; (a = _a) ?? b"); diff --git a/crates/oxc_minifier/tests/peephole/mod.rs b/crates/oxc_minifier/tests/peephole/mod.rs index 251e5fae1f7d8..a83fcab3f8d01 100644 --- a/crates/oxc_minifier/tests/peephole/mod.rs +++ b/crates/oxc_minifier/tests/peephole/mod.rs @@ -22,7 +22,7 @@ fn integration() { return console.log(JSON.stringify(os)) })", r#"require("./index.js")(function(e, os) { - return console.log(e || JSON.stringify(os)); + return e ? console.log(e) : console.log(JSON.stringify(os)); });"#, ); diff --git a/tasks/minsize/minsize.snap b/tasks/minsize/minsize.snap index 50f442a87b3c3..2d5a82d862848 100644 --- a/tasks/minsize/minsize.snap +++ b/tasks/minsize/minsize.snap @@ -13,15 +13,15 @@ Original | minified | minified | gzip | gzip | Fixture 555.77 kB | 271.20 kB | 270.13 kB | 88.30 kB | 90.80 kB | d3.js -1.01 MB | 440.93 kB | 458.89 kB | 122.52 kB | 126.71 kB | bundle.min.js +1.01 MB | 440.94 kB | 458.89 kB | 122.52 kB | 126.71 kB | bundle.min.js -1.25 MB | 650.33 kB | 646.76 kB | 160.96 kB | 163.73 kB | three.js +1.25 MB | 650.34 kB | 646.76 kB | 160.96 kB | 163.73 kB | three.js -2.14 MB | 717.02 kB | 724.14 kB | 162.02 kB | 181.07 kB | victory.js +2.14 MB | 717.04 kB | 724.14 kB | 162.02 kB | 181.07 kB | victory.js -3.20 MB | 1.01 MB | 1.01 MB | 324.33 kB | 331.56 kB | echarts.js +3.20 MB | 1.01 MB | 1.01 MB | 324.34 kB | 331.56 kB | echarts.js -6.69 MB | 2.28 MB | 2.31 MB | 467.74 kB | 488.28 kB | antd.js +6.69 MB | 2.28 MB | 2.31 MB | 467.77 kB | 488.28 kB | antd.js -10.95 MB | 3.36 MB | 3.49 MB | 861.78 kB | 915.50 kB | typescript.js +10.95 MB | 3.36 MB | 3.49 MB | 861.80 kB | 915.50 kB | typescript.js