@@ -68,6 +68,7 @@ impl<'a> PeepholeOptimizations {
68
68
"abs" | "ceil" | "floor" | "round" | "fround" | "trunc" | "sign" => {
69
69
Self :: try_fold_math_unary ( * span, arguments, name, object, ctx)
70
70
}
71
+ "min" | "max" => Self :: try_fold_math_variadic ( * span, arguments, name, object, ctx) ,
71
72
_ => None ,
72
73
} ;
73
74
if let Some ( replacement) = replacement {
@@ -357,7 +358,7 @@ impl<'a> PeepholeOptimizations {
357
358
}
358
359
359
360
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)
361
362
}
362
363
363
364
/// `Math.pow(a, b)` -> `+(a) ** +b`
@@ -490,6 +491,32 @@ impl<'a> PeepholeOptimizations {
490
491
Some ( ctx. ast . expression_numeric_literal ( span, result, None , NumberBase :: Decimal ) )
491
492
}
492
493
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
+
493
520
/// `[].concat(a).concat(b)` -> `[].concat(a, b)`
494
521
/// `"".concat(a).concat(b)` -> `"".concat(a, b)`
495
522
fn try_fold_concat_chain ( & mut self , node : & mut Expression < ' a > , ctx : Ctx < ' a , ' _ > ) {
@@ -1289,25 +1316,27 @@ mod test {
1289
1316
}
1290
1317
1291
1318
#[ test]
1292
- #[ ignore]
1293
1319
fn test_fold_math_functions_max ( ) {
1294
- test_same ( "Math.max(Math.random(), 1)" ) ;
1320
+ test_same_value ( "Math.max(Math.random(), 1)" ) ;
1295
1321
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" ) ;
1300
1328
}
1301
1329
1302
1330
#[ test]
1303
- #[ ignore]
1304
1331
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" ) ;
1311
1340
}
1312
1341
1313
1342
#[ test]
0 commit comments