|
1 | 1 | use oxc_allocator::TakeIn; |
2 | 2 | use oxc_ast::ast::*; |
3 | | -use oxc_ecmascript::constant_evaluation::{ConstantEvaluation, ConstantValue, DetermineValueType}; |
| 3 | +use oxc_ecmascript::{ |
| 4 | + constant_evaluation::{ConstantEvaluation, ConstantValue, DetermineValueType}, |
| 5 | + side_effects::MayHaveSideEffects, |
| 6 | +}; |
4 | 7 | use oxc_span::GetSpan; |
5 | 8 | use oxc_syntax::es_target::ESTarget; |
6 | 9 |
|
@@ -135,28 +138,30 @@ impl<'a> PeepholeOptimizations { |
135 | 138 | _ => {} |
136 | 139 | } |
137 | 140 | } |
138 | | - match &mut e.right { |
139 | | - Expression::BooleanLiteral(b) if left.is_boolean() => { |
140 | | - match e.operator { |
141 | | - BinaryOperator::Inequality | BinaryOperator::StrictInequality => { |
142 | | - e.operator = BinaryOperator::Equality; |
143 | | - b.value = !b.value; |
144 | | - } |
145 | | - BinaryOperator::StrictEquality => { |
146 | | - e.operator = BinaryOperator::Equality; |
147 | | - } |
148 | | - BinaryOperator::Equality => {} |
149 | | - _ => return None, |
150 | | - } |
151 | | - Some(if b.value { |
152 | | - e.left.take_in(ctx.ast) |
153 | | - } else { |
154 | | - let argument = e.left.take_in(ctx.ast); |
155 | | - ctx.ast.expression_unary(e.span, UnaryOperator::LogicalNot, argument) |
156 | | - }) |
| 141 | + if !left.is_boolean() { |
| 142 | + return None; |
| 143 | + } |
| 144 | + if e.right.may_have_side_effects(ctx) { |
| 145 | + return None; |
| 146 | + } |
| 147 | + let mut b = e.right.evaluate_value(ctx).and_then(ConstantValue::into_boolean)?; |
| 148 | + match e.operator { |
| 149 | + BinaryOperator::Inequality | BinaryOperator::StrictInequality => { |
| 150 | + e.operator = BinaryOperator::Equality; |
| 151 | + b = !b; |
157 | 152 | } |
158 | | - _ => None, |
| 153 | + BinaryOperator::StrictEquality => { |
| 154 | + e.operator = BinaryOperator::Equality; |
| 155 | + } |
| 156 | + BinaryOperator::Equality => {} |
| 157 | + _ => return None, |
159 | 158 | } |
| 159 | + Some(if b { |
| 160 | + e.left.take_in(ctx.ast) |
| 161 | + } else { |
| 162 | + let argument = e.left.take_in(ctx.ast); |
| 163 | + ctx.ast.expression_unary(e.span, UnaryOperator::LogicalNot, argument) |
| 164 | + }) |
160 | 165 | } |
161 | 166 |
|
162 | 167 | /// Compress `foo == true` into `foo == 1`. |
@@ -1468,4 +1473,12 @@ mod test { |
1468 | 1473 | test("v = x == !1", "v = x == 0"); |
1469 | 1474 | test("v = x != !1", "v = x != 0"); |
1470 | 1475 | } |
| 1476 | + |
| 1477 | + #[test] |
| 1478 | + fn try_minimize_binary() { |
| 1479 | + test("f(!a === !0)", "f(!a)"); |
| 1480 | + test("f(!a === !1)", "f(!!a)"); |
| 1481 | + test("f(!a === true)", "f(!a)"); |
| 1482 | + test("f(!a === false)", "f(!!a)"); |
| 1483 | + } |
1471 | 1484 | } |
0 commit comments