diff --git a/crates/oxc_minifier/src/peephole/fold_constants.rs b/crates/oxc_minifier/src/peephole/fold_constants.rs index e9c5ffb1d14d9..ae7d969c4a6e0 100644 --- a/crates/oxc_minifier/src/peephole/fold_constants.rs +++ b/crates/oxc_minifier/src/peephole/fold_constants.rs @@ -1277,6 +1277,8 @@ mod test { fold_same("a=+foo()"); fold_same("a=+f"); fold("a=+(f?true:false)", "a=+!!f"); + fold("a=+(f?!0:!1)", "a=+!!f"); + fold_same("a=+(f?(foo, !0):(bar, !1))"); fold("a=+0", "a=0"); fold("a=+Infinity", "a=Infinity"); fold("a=+NaN", "a=NaN"); diff --git a/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs b/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs index d8f597a929935..20a598895672f 100644 --- a/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs +++ b/crates/oxc_minifier/src/peephole/minimize_conditional_expression.rs @@ -1,6 +1,9 @@ use oxc_allocator::TakeIn; use oxc_ast::{NONE, ast::*}; -use oxc_ecmascript::side_effects::MayHaveSideEffects; +use oxc_ecmascript::{ + constant_evaluation::{ConstantEvaluation, ConstantValue}, + side_effects::MayHaveSideEffects, +}; use oxc_span::{ContentEq, GetSpan}; use oxc_syntax::es_target::ESTarget; @@ -103,27 +106,6 @@ impl<'a> PeepholeOptimizations { _ => {} } - // "a ? true : false" => "!!a" - // "a ? false : true" => "!a" - if let (Expression::BooleanLiteral(left), Expression::BooleanLiteral(right)) = - (&expr.consequent, &expr.alternate) - { - match (left.value, right.value) { - (true, false) => { - let test = expr.test.take_in(ctx.ast); - let test = self.minimize_not(expr.span, test, ctx); - let test = self.minimize_not(expr.span, test, ctx); - return Some(test); - } - (false, true) => { - let test = expr.test.take_in(ctx.ast); - let test = self.minimize_not(expr.span, test, ctx); - return Some(test); - } - _ => {} - } - } - // "a ? b ? c : d : d" => "a && b ? c : d" if let Expression::ConditionalExpression(consequent) = &mut expr.consequent { if ctx.expr_eq(&consequent.alternate, &expr.alternate) { @@ -389,6 +371,32 @@ impl<'a> PeepholeOptimizations { } } + // "a ? true : false" => "!!a" + // "a ? false : true" => "!a" + match ( + expr.consequent + .evaluate_value(ctx) + .and_then(ConstantValue::into_boolean) + .filter(|_| !expr.consequent.may_have_side_effects(ctx)), + expr.alternate + .evaluate_value(ctx) + .and_then(ConstantValue::into_boolean) + .filter(|_| !expr.alternate.may_have_side_effects(ctx)), + ) { + (Some(true), Some(false)) => { + let test = expr.test.take_in(ctx.ast); + let test = self.minimize_not(expr.span, test, ctx); + let test = self.minimize_not(expr.span, test, ctx); + return Some(test); + } + (Some(false), Some(true)) => { + let test = expr.test.take_in(ctx.ast); + let test = self.minimize_not(expr.span, test, ctx); + return Some(test); + } + _ => {} + } + if ctx.expr_eq(&expr.alternate, &expr.consequent) { // "/* @__PURE__ */ a() ? b : b" => "b" if !expr.test.may_have_side_effects(ctx) {