Skip to content

Commit

Permalink
feat(minifier): arithmetic operations for infinity.
Browse files Browse the repository at this point in the history
  • Loading branch information
7086cmd committed Oct 9, 2024
1 parent eacde05 commit 3e45842
Showing 1 changed file with 60 additions and 4 deletions.
64 changes: 60 additions & 4 deletions crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,17 @@ impl<'a> PeepholeFoldConstants {
fn try_get_number_literal_value(&self, expr: &mut Expression<'a>) -> Option<f64> {
match expr {
Expression::NumericLiteral(n) => Some(n.value),
Expression::Identifier(id) if id.name.as_str() == "Infinity" => Some(f64::INFINITY),
Expression::UnaryExpression(unary)
if unary.operator == UnaryOperator::UnaryNegation =>
{
let Expression::NumericLiteral(arg) = &mut unary.argument else { return None };
Some(-arg.value)
match &mut unary.argument {
Expression::NumericLiteral(arg) => Some(-arg.value),
Expression::Identifier(id) if id.name.as_str() == "Infinity" => {
Some(f64::NEG_INFINITY)
}
_ => None,
}
}
_ => None,
}
Expand Down Expand Up @@ -517,7 +523,7 @@ impl<'a> PeepholeFoldConstants {
let left = self.try_get_number_literal_value(&mut operation.left)?;
let right = self.try_get_number_literal_value(&mut operation.right)?;
if !left.is_finite() || !right.is_finite() {
return None;
return self.try_fold_infinity_arithmetic(left, operation.operator, right, ctx);
}
let result = match operation.operator {
BinaryOperator::Addition => left + right,
Expand Down Expand Up @@ -562,6 +568,52 @@ impl<'a> PeepholeFoldConstants {
))
}

fn try_fold_infinity_arithmetic(
&self,
left: f64,
operator: BinaryOperator,
right: f64,
ctx: &mut TraverseCtx<'a>,
) -> Option<Expression<'a>> {
if left.is_finite() && right.is_finite() || !operator.is_arithmetic() {
return None;
}
let result = match operator {
BinaryOperator::Addition => left + right,
BinaryOperator::Subtraction => left - right,
BinaryOperator::Multiplication => left * right,
BinaryOperator::Division => {
if right == 0.0 {
return None;
}
left / right
}
BinaryOperator::Remainder => {
if right == 0.0 {
return None;
}
left % right
}
BinaryOperator::Exponential => left.powf(right),
_ => unreachable!(),
};
Some(match result {
f64::INFINITY => ctx.ast.expression_identifier_reference(SPAN, "Infinity"),
f64::NEG_INFINITY => ctx.ast.expression_unary(
SPAN,
UnaryOperator::UnaryNegation,
ctx.ast.expression_identifier_reference(SPAN, "Infinity"),
),
_ if result.is_nan() => ctx.ast.expression_identifier_reference(SPAN, "NaN"),
_ => ctx.ast.expression_numeric_literal(
SPAN,
result,
result.to_string(),
if is_exact_int64(result) { NumberBase::Decimal } else { NumberBase::Float },
),
})
}

fn try_fold_instanceof<'b>(
&self,
_span: Span,
Expand Down Expand Up @@ -1699,12 +1751,16 @@ mod test {
}

#[test]
#[ignore]
fn test_fold_arithmetic_infinity() {
test("x=-Infinity-2", "x=-Infinity");
test("x=Infinity-2", "x=Infinity");
test("x=Infinity*5", "x=Infinity");
test("x = Infinity ** 2", "x = Infinity");
test("x = Infinity ** -2", "x = 0");

test("x = Infinity / Infinity", "x = NaN");
test_same("x = Infinity % 0");
test_same("x = Infinity / 0");
test("x = Infinity % Infinity", "x = NaN");
}
}

0 comments on commit 3e45842

Please sign in to comment.