diff --git a/crates/oxc_minifier/src/ast_passes/peephole_minimize_conditions.rs b/crates/oxc_minifier/src/ast_passes/peephole_minimize_conditions.rs index 077020cd510e9..efcfeaa86607f 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_minimize_conditions.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_minimize_conditions.rs @@ -83,6 +83,15 @@ impl<'a> PeepholeMinimizeConditions { if !expr.operator.is_not() { return None; } + if let Expression::UnaryExpression(e1) = &mut expr.argument { + if e1.operator.is_not() { + if let Expression::UnaryExpression(e2) = &mut e1.argument { + if e2.operator.is_not() { + expr.argument = ctx.ast.move_expression(&mut e2.argument); + } + } + } + } let Expression::BinaryExpression(binary_expr) = &mut expr.argument else { return None }; let new_op = binary_expr.operator.equality_inverse_operator()?; binary_expr.operator = new_op; @@ -345,7 +354,10 @@ impl<'a> PeepholeMinimizeConditions { // `!a ? b() : c()` -> `a ? c() : b()` if let Expression::UnaryExpression(test_expr) = &mut expr.test { - if test_expr.operator.is_not() { + if test_expr.operator.is_not() + // Skip `!!!a` + && !matches!(test_expr.argument, Expression::UnaryExpression(_)) + { let test = ctx.ast.move_expression(&mut test_expr.argument); let consequent = ctx.ast.move_expression(&mut expr.consequent); let alternate = ctx.ast.move_expression(&mut expr.alternate); @@ -489,13 +501,12 @@ impl<'a> PeepholeMinimizeConditions { e: &mut BinaryExpression<'a>, ctx: &mut TraverseCtx<'a>, ) -> Option> { - // let ctx = Ctx(ctx); - if !ValueType::from(&e.left).is_boolean() { - return None; - } let Expression::BooleanLiteral(b) = &mut e.right else { return None; }; + if !ValueType::from(&e.left).is_boolean() { + return None; + } match e.operator { BinaryOperator::Inequality | BinaryOperator::StrictInequality => { e.operator = BinaryOperator::Equality; @@ -504,7 +515,8 @@ impl<'a> PeepholeMinimizeConditions { BinaryOperator::StrictEquality => { e.operator = BinaryOperator::Equality; } - _ => {} + BinaryOperator::Equality => {} + _ => return None, } Some(if b.value { ctx.ast.move_expression(&mut e.left) @@ -810,6 +822,11 @@ mod test { fold("x = !true", "x = !1"); } + #[test] + fn test_fold_triple_not() { + fold("!!!foo ? bar : baz", "foo ? baz : bar"); + } + #[test] fn test_minimize_expr_condition() { fold("(x ? true : false) && y()", "x && y()"); diff --git a/tasks/minsize/minsize.snap b/tasks/minsize/minsize.snap index df7827166f3f5..5431c35f83656 100644 --- a/tasks/minsize/minsize.snap +++ b/tasks/minsize/minsize.snap @@ -23,5 +23,5 @@ Original | minified | minified | gzip | gzip | Fixture 6.69 MB | 2.32 MB | 2.31 MB | 492.86 kB | 488.28 kB | antd.js -10.95 MB | 3.50 MB | 3.49 MB | 909.33 kB | 915.50 kB | typescript.js +10.95 MB | 3.50 MB | 3.49 MB | 909.32 kB | 915.50 kB | typescript.js