Skip to content

Commit ef16e27

Browse files
committed
feat(minifier): implement variadic Math methods in known methods
1 parent 6893b32 commit ef16e27

File tree

1 file changed

+43
-14
lines changed

1 file changed

+43
-14
lines changed

crates/oxc_minifier/src/peephole/replace_known_methods.rs

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ impl<'a> PeepholeOptimizations {
6868
"abs" | "ceil" | "floor" | "round" | "fround" | "trunc" | "sign" => {
6969
Self::try_fold_math_unary(*span, arguments, name, object, ctx)
7070
}
71+
"min" | "max" => Self::try_fold_math_variadic(*span, arguments, name, object, ctx),
7172
_ => None,
7273
};
7374
if let Some(replacement) = replacement {
@@ -357,7 +358,7 @@ impl<'a> PeepholeOptimizations {
357358
}
358359

359360
fn validate_arguments(args: &Arguments, expected_len: usize) -> bool {
360-
args.len() == expected_len && args.iter().all(Argument::is_expression)
361+
(args.len() == expected_len) && args.iter().all(Argument::is_expression)
361362
}
362363

363364
/// `Math.pow(a, b)` -> `+(a) ** +b`
@@ -490,6 +491,32 @@ impl<'a> PeepholeOptimizations {
490491
Some(ctx.ast.expression_numeric_literal(span, result, None, NumberBase::Decimal))
491492
}
492493

494+
fn try_fold_math_variadic(
495+
span: Span,
496+
arguments: &Arguments,
497+
name: &str,
498+
object: &Expression<'a>,
499+
ctx: Ctx<'a, '_>,
500+
) -> Option<Expression<'a>> {
501+
if !Self::validate_global_reference(object, "Math", ctx) {
502+
return None;
503+
}
504+
let numbers = arguments
505+
.iter()
506+
.map(|arg| arg.as_expression().map(|e| ctx.get_side_free_number_value(e))?)
507+
.collect::<Option<Vec<_>>>()?;
508+
let result = if numbers.iter().any(|n| n.is_nan()) {
509+
f64::NAN
510+
} else {
511+
match name {
512+
"min" => numbers.iter().copied().fold(f64::INFINITY, f64::min),
513+
"max" => numbers.iter().copied().fold(f64::NEG_INFINITY, f64::max),
514+
_ => return None,
515+
}
516+
};
517+
Some(ctx.ast.expression_numeric_literal(span, result, None, NumberBase::Decimal))
518+
}
519+
493520
/// `[].concat(a).concat(b)` -> `[].concat(a, b)`
494521
/// `"".concat(a).concat(b)` -> `"".concat(a, b)`
495522
fn try_fold_concat_chain(&mut self, node: &mut Expression<'a>, ctx: Ctx<'a, '_>) {
@@ -1289,25 +1316,27 @@ mod test {
12891316
}
12901317

12911318
#[test]
1292-
#[ignore]
12931319
fn test_fold_math_functions_max() {
1294-
test_same("Math.max(Math.random(), 1)");
1320+
test_same_value("Math.max(Math.random(), 1)");
12951321

1296-
test("Math.max()", "-Infinity");
1297-
test("Math.max(0)", "0");
1298-
test("Math.max(0, 1)", "1");
1299-
test("Math.max(0, 1, -1, 200)", "200");
1322+
test_value("Math.max()", "-Infinity");
1323+
test_value("Math.max(0)", "0");
1324+
test_value("Math.max(0, 1)", "1");
1325+
test_value("Math.max(0, 1, -1, 200)", "200");
1326+
test_value("Math.max(0, -1, -Infinity)", "0");
1327+
test_value("Math.max(0, -1, -Infinity, NaN)", "NaN");
13001328
}
13011329

13021330
#[test]
1303-
#[ignore]
13041331
fn test_fold_math_functions_min() {
1305-
test_same("Math.min(Math.random(), 1)");
1306-
1307-
test("Math.min()", "Infinity");
1308-
test("Math.min(3)", "3");
1309-
test("Math.min(0, 1)", "0");
1310-
test("Math.min(0, 1, -1, 200)", "-1");
1332+
test_same_value("Math.min(Math.random(), 1)");
1333+
1334+
test_value("Math.min()", "Infinity");
1335+
test_value("Math.min(3)", "3");
1336+
test_value("Math.min(0, 1)", "0");
1337+
test_value("Math.min(0, 1, -1, 200)", "-1");
1338+
test_value("Math.min(0, -1, -Infinity)", "-Infinity");
1339+
test_value("Math.min(0, -1, -Infinity, NaN)", "NaN");
13111340
}
13121341

13131342
#[test]

0 commit comments

Comments
 (0)