Skip to content

Commit

Permalink
feat(minifier): fold if(x >> y == 0){} -> if(!(x >> y)){}
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Jan 6, 2025
1 parent aea9551 commit 16688ff
Showing 1 changed file with 49 additions and 21 deletions.
70 changes: 49 additions & 21 deletions crates/oxc_minifier/src/ast_passes/peephole_minimize_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Expression<'a>> {
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)
})
}
}

Expand Down Expand Up @@ -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)");
Expand All @@ -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");
Expand Down

0 comments on commit 16688ff

Please sign in to comment.