mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +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> {
|
fn try_get_number_literal_value(&self, expr: &mut Expression<'a>) -> Option<f64> {
|
||||||
match expr {
|
match expr {
|
||||||
Expression::NumericLiteral(n) => Some(n.value),
|
Expression::NumericLiteral(n) => Some(n.value),
|
||||||
|
Expression::Identifier(id) if id.name.as_str() == "Infinity" => Some(f64::INFINITY),
|
||||||
Expression::UnaryExpression(unary)
|
Expression::UnaryExpression(unary)
|
||||||
if unary.operator == UnaryOperator::UnaryNegation =>
|
if unary.operator == UnaryOperator::UnaryNegation =>
|
||||||
{
|
{
|
||||||
let Expression::NumericLiteral(arg) = &mut unary.argument else { return None };
|
match &mut unary.argument {
|
||||||
Some(-arg.value)
|
Expression::NumericLiteral(arg) => Some(-arg.value),
|
||||||
|
Expression::Identifier(id) if id.name.as_str() == "Infinity" => {
|
||||||
|
Some(f64::NEG_INFINITY)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
@ -517,7 +523,7 @@ impl<'a> PeepholeFoldConstants {
|
||||||
let left = self.try_get_number_literal_value(&mut operation.left)?;
|
let left = self.try_get_number_literal_value(&mut operation.left)?;
|
||||||
let right = self.try_get_number_literal_value(&mut operation.right)?;
|
let right = self.try_get_number_literal_value(&mut operation.right)?;
|
||||||
if !left.is_finite() || !right.is_finite() {
|
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 {
|
let result = match operation.operator {
|
||||||
BinaryOperator::Addition => left + right,
|
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>(
|
fn try_fold_instanceof<'b>(
|
||||||
&self,
|
&self,
|
||||||
_span: Span,
|
_span: Span,
|
||||||
|
|
@ -1699,12 +1751,16 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
fn test_fold_arithmetic_infinity() {
|
fn test_fold_arithmetic_infinity() {
|
||||||
test("x=-Infinity-2", "x=-Infinity");
|
test("x=-Infinity-2", "x=-Infinity");
|
||||||
test("x=Infinity-2", "x=Infinity");
|
test("x=Infinity-2", "x=Infinity");
|
||||||
test("x=Infinity*5", "x=Infinity");
|
test("x=Infinity*5", "x=Infinity");
|
||||||
test("x = Infinity ** 2", "x = Infinity");
|
test("x = Infinity ** 2", "x = Infinity");
|
||||||
test("x = Infinity ** -2", "x = 0");
|
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