mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
feat(minifier): arithmetic operations for infinity. (#6332)
I do not anticipate that this will be utilized in production 😂 .
This commit is contained in:
parent
b9c94bbc44
commit
97ac179320
1 changed files with 60 additions and 4 deletions
|
|
@ -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,
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
@ -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,
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue