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 acff29127..18efdebb3 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_minimize_conditions.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_minimize_conditions.rs @@ -514,33 +514,52 @@ impl<'a> PeepholeMinimizeConditions { // `a instanceof b === true` -> `a instanceof b` // `a instanceof b === false` -> `!(a instanceof b)` // ^^^^^^^^^^^^^^ `ValueType::from(&e.left).is_boolean()` is `true`. + // `x >> y !== 0` -> `x >> y` + // ^^^^^^ ValueType::from(&e.left).is_number()` is `true`. fn try_minimize_binary( e: &mut BinaryExpression<'a>, ctx: &mut TraverseCtx<'a>, ) -> Option> { - 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; - b.value = !b.value; + match &mut e.right { + Expression::BooleanLiteral(b) if ValueType::from(&e.left).is_boolean() => { + match e.operator { + BinaryOperator::Inequality | BinaryOperator::StrictInequality => { + e.operator = BinaryOperator::Equality; + b.value = !b.value; + } + BinaryOperator::StrictEquality => { + e.operator = BinaryOperator::Equality; + } + BinaryOperator::Equality => {} + _ => return None, + } + Some(if b.value { + ctx.ast.move_expression(&mut e.left) + } else { + let argument = ctx.ast.move_expression(&mut e.left); + ctx.ast.expression_unary(e.span, UnaryOperator::LogicalNot, argument) + }) } - BinaryOperator::StrictEquality => { - e.operator = BinaryOperator::Equality; + Expression::NumericLiteral(lit) + if lit.value == 0.0 + && ValueType::from(&e.left).is_number() + && Self::is_in_boolean_context(ctx) => + { + match e.operator { + // `x >> y !== 0` -> `x >> y` + BinaryOperator::StrictInequality | BinaryOperator::Inequality => { + Some(ctx.ast.move_expression(&mut e.left)) + } + // `x >> y !== 0` -> `!(x >> y)` + BinaryOperator::StrictEquality | BinaryOperator::Equality => { + let argument = ctx.ast.move_expression(&mut e.left); + Some(ctx.ast.expression_unary(e.span, UnaryOperator::LogicalNot, argument)) + } + _ => None, + } } - BinaryOperator::Equality => {} - _ => return None, + _ => None, } - Some(if b.value { - ctx.ast.move_expression(&mut e.left) - } else { - let argument = ctx.ast.move_expression(&mut e.left); - ctx.ast.expression_unary(e.span, UnaryOperator::LogicalNot, argument) - }) } } @@ -1662,7 +1681,7 @@ mod test { } #[test] - fn compress_binary() { + fn compress_binary_boolean() { test("a instanceof b === true", "a instanceof b"); test("a instanceof b == true", "a instanceof b"); test("a instanceof b === false", "!(a instanceof b)"); @@ -1684,6 +1703,15 @@ mod test { test("delete x != false", "delete x"); } + #[test] + fn compress_binary_number() { + test("if(x >> y == 0){}", "if(!(x >> y)){}"); + test("if(x >> y === 0){}", "if(!(x >> y)){}"); + test("if(x >> y != 0){}", "if(x >> y){}"); + test("if(x >> y !== 0){}", "if(x >> y){}"); + test_same("foo(x >> y == 0)"); + } + #[test] fn minimize_duplicate_nots() { test("!!x", "x");