mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
feat(minifier): fold if(x >> y == 0){} -> if(!(x >> y)){} (#8277)
This commit is contained in:
parent
0e3b79a65b
commit
ecc789f163
1 changed files with 49 additions and 21 deletions
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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");
|
||||
|
|
|
|||
Loading…
Reference in a new issue