@@ -73,6 +73,9 @@ impl<'a> PeepholeOptimizations {
7373 "fromCharCode" => Self :: try_fold_string_from_char_code ( * span, arguments, object, ctx) ,
7474 "toString" => Self :: try_fold_to_string ( * span, arguments, object, ctx) ,
7575 "pow" => self . try_fold_pow ( * span, arguments, object, ctx) ,
76+ "isFinite" | "isNaN" | "isInteger" | "isSafeInteger" => {
77+ Self :: try_fold_number_methods ( * span, arguments, object, name, ctx)
78+ }
7679 "sqrt" | "cbrt" => Self :: try_fold_roots ( * span, arguments, name, object, ctx) ,
7780 "abs" | "ceil" | "floor" | "round" | "fround" | "trunc" | "sign" => {
7881 Self :: try_fold_math_unary ( * span, arguments, name, object, ctx)
@@ -1025,6 +1028,38 @@ impl<'a> PeepholeOptimizations {
10251028 _ => None ,
10261029 }
10271030 }
1031+
1032+ fn try_fold_number_methods (
1033+ span : Span ,
1034+ args : & mut Arguments < ' a > ,
1035+ object : & Expression < ' a > ,
1036+ name : & str ,
1037+ ctx : & mut Ctx < ' a , ' _ > ,
1038+ ) -> Option < Expression < ' a > > {
1039+ if !Self :: validate_global_reference ( object, "Number" , ctx) {
1040+ return None ;
1041+ }
1042+ if args. len ( ) != 1 {
1043+ return None ;
1044+ }
1045+ let extracted_expr = args. first ( ) ?. as_expression ( ) ?;
1046+ if !extracted_expr. is_number_literal ( ) {
1047+ return None ;
1048+ }
1049+ let extracted = extracted_expr. get_side_free_number_value ( ctx) ?;
1050+ let result = match name {
1051+ "isFinite" => Some ( extracted. is_finite ( ) ) ,
1052+ "isInteger" => Some ( extracted. fract ( ) . abs ( ) < f64:: EPSILON ) ,
1053+ "isNaN" => Some ( extracted. is_nan ( ) ) ,
1054+ "isSafeInteger" => {
1055+ let integer = extracted. fract ( ) . abs ( ) < f64:: EPSILON ;
1056+ let safe = extracted. abs ( ) <= 2f64 . powi ( 53 ) - 1.0 ;
1057+ Some ( safe && integer)
1058+ }
1059+ _ => None ,
1060+ } ;
1061+ result. map ( |value| ctx. ast . expression_boolean_literal ( span, value) )
1062+ }
10281063}
10291064
10301065/// Port from: <https://github.com/google/closure-compiler/blob/v20240609/test/com/google/javascript/jscomp/PeepholeReplaceKnownMethodsTest.java>
@@ -1650,36 +1685,33 @@ mod test {
16501685 }
16511686
16521687 #[ test]
1653- #[ ignore]
16541688 fn test_fold_number_functions_is_safe_integer ( ) {
1655- test ( "Number.isSafeInteger(1)" , "true " ) ;
1656- test ( "Number.isSafeInteger(1.5)" , "false " ) ;
1657- test ( "Number.isSafeInteger(9007199254740991)" , "true " ) ;
1658- test ( "Number.isSafeInteger(9007199254740992)" , "false " ) ;
1659- test ( "Number.isSafeInteger(-9007199254740991)" , "true " ) ;
1660- test ( "Number.isSafeInteger(-9007199254740992)" , "false " ) ;
1689+ test_value ( "Number.isSafeInteger(1)" , "!0 " ) ;
1690+ test_value ( "Number.isSafeInteger(1.5)" , "!1 " ) ;
1691+ test_value ( "Number.isSafeInteger(9007199254740991)" , "!0 " ) ;
1692+ test_value ( "Number.isSafeInteger(9007199254740992)" , "!1 " ) ;
1693+ test_value ( "Number.isSafeInteger(-9007199254740991)" , "!0 " ) ;
1694+ test_value ( "Number.isSafeInteger(-9007199254740992)" , "!1 " ) ;
16611695 }
16621696
16631697 #[ test]
1664- #[ ignore]
16651698 fn test_fold_number_functions_is_finite ( ) {
1666- test ( "Number.isFinite(1)" , "true " ) ;
1667- test ( "Number.isFinite(1.5)" , "true " ) ;
1668- test ( "Number.isFinite(NaN)" , "false " ) ;
1669- test ( "Number.isFinite(Infinity)" , "false " ) ;
1670- test ( "Number.isFinite(-Infinity)" , "false " ) ;
1671- test_same ( "Number.isFinite('a')" ) ;
1699+ test_value ( "Number.isFinite(1)" , "!0 " ) ;
1700+ test_value ( "Number.isFinite(1.5)" , "!0 " ) ;
1701+ test_value ( "Number.isFinite(NaN)" , "!1 " ) ;
1702+ test_value ( "Number.isFinite(Infinity)" , "!1 " ) ;
1703+ test_value ( "Number.isFinite(-Infinity)" , "!1 " ) ;
1704+ test_same_value ( "Number.isFinite('a')" ) ;
16721705 }
16731706
16741707 #[ test]
1675- #[ ignore]
16761708 fn test_fold_number_functions_is_nan ( ) {
1677- test ( "Number.isNaN(1)" , "false " ) ;
1678- test ( "Number.isNaN(1.5)" , "false " ) ;
1679- test ( "Number.isNaN(NaN)" , "true " ) ;
1680- test_same ( "Number.isNaN('a')" ) ;
1709+ test_value ( "Number.isNaN(1)" , "!1 " ) ;
1710+ test_value ( "Number.isNaN(1.5)" , "!1 " ) ;
1711+ test_value ( "Number.isNaN(NaN)" , "!0 " ) ;
1712+ test_same_value ( "Number.isNaN('a')" ) ;
16811713 // unknown function may have side effects
1682- test_same ( "Number.isNaN(+(void unknown()))" ) ;
1714+ test_same_value ( "Number.isNaN(+(void unknown()))" ) ;
16831715 }
16841716
16851717 #[ test]
0 commit comments