@@ -745,11 +745,7 @@ impl<'a> Codegen<'a> {
745745 self . print_str ( buffer. format ( num) ) ;
746746 self . need_space_before_dot = self . code_len ( ) ;
747747 } else {
748- let s = Self :: get_minified_number ( num, & mut buffer) ;
749- self . print_str ( & s) ;
750- if !s. bytes ( ) . any ( |b| matches ! ( b, b'.' | b'e' | b'x' ) ) {
751- self . need_space_before_dot = self . code_len ( ) ;
752- }
748+ self . print_minified_number ( num, & mut buffer) ;
753749 }
754750 }
755751
@@ -760,14 +756,18 @@ impl<'a> Codegen<'a> {
760756 }
761757 }
762758
763- // `get_minified_number` from terser
759+ // Optimized version of `get_minified_number` from terser
764760 // https://github.com/terser/terser/blob/c5315c3fd6321d6b2e076af35a70ef532f498505/lib/output.js#L2418
761+ // Instead of building all candidates and finding the shortest, we track the shortest as we go
762+ // and use self.print_str directly instead of returning intermediate strings
765763 #[ expect( clippy:: cast_possible_truncation, clippy:: cast_sign_loss, clippy:: cast_possible_wrap) ]
766- fn get_minified_number ( num : f64 , buffer : & mut dragonbox_ecma:: Buffer ) -> Cow < ' _ , str > {
764+ fn print_minified_number ( & mut self , num : f64 , buffer : & mut dragonbox_ecma:: Buffer ) {
767765 use cow_utils:: CowUtils ;
768766
769767 if num < 1000.0 && num. fract ( ) == 0.0 {
770- return Cow :: Borrowed ( buffer. format ( num) ) ;
768+ self . print_str ( buffer. format ( num) ) ;
769+ self . need_space_before_dot = self . code_len ( ) ;
770+ return ;
771771 }
772772
773773 let mut s = buffer. format ( num) ;
@@ -778,40 +778,66 @@ impl<'a> Codegen<'a> {
778778
779779 let s = s. cow_replacen ( "e+" , "e" , 1 ) ;
780780
781- let mut candidates = vec ! [ s. clone( ) ] ;
781+ // Track the best candidate found so far
782+ let mut best_candidate = s. clone ( ) ;
783+ let mut best_len = best_candidate. len ( ) ;
782784
785+ // Check hex format for integers
783786 if num. fract ( ) == 0.0 {
784- candidates. push ( Cow :: Owned ( format ! ( "0x{:x}" , num as u128 ) ) ) ;
787+ let hex_candidate = format ! ( "0x{:x}" , num as u128 ) ;
788+ if hex_candidate. len ( ) < best_len {
789+ best_candidate = hex_candidate. into ( ) ;
790+ best_len = best_candidate. len ( ) ;
791+ }
785792 }
786793
787- // create `1e-2`
788- if s. starts_with ( ".0" ) {
789- if let Some ( ( i, _) ) = s[ 1 ..] . bytes ( ) . enumerate ( ) . find ( |( _, c) | * c != b'0' ) {
794+ // Check for scientific notation optimizations for numbers starting with ".0"
795+ if best_candidate. starts_with ( ".0" ) {
796+ if let Some ( ( i, _) ) = best_candidate[ 1 ..] . bytes ( ) . enumerate ( ) . find ( |( _, c) | * c != b'0' )
797+ {
790798 let len = i + 1 ; // `+1` to include the dot.
791- let digits = & s[ len..] ;
792- candidates. push ( Cow :: Owned ( format ! ( "{digits}e-{}" , digits. len( ) + len - 1 ) ) ) ;
799+ let digits = & best_candidate[ len..] ;
800+ let scientific_candidate = format ! ( "{digits}e-{}" , digits. len( ) + len - 1 ) ;
801+ if scientific_candidate. len ( ) < best_len {
802+ best_candidate = scientific_candidate. into ( ) ;
803+ best_len = best_candidate. len ( ) ;
804+ }
793805 }
794806 }
795807
796- // create 1e2
797- if s. ends_with ( '0' ) {
798- if let Some ( ( len, _) ) = s. bytes ( ) . rev ( ) . enumerate ( ) . find ( |( _, c) | * c != b'0' ) {
799- candidates. push ( Cow :: Owned ( format ! ( "{}e{len}" , & s[ 0 ..s. len( ) - len] ) ) ) ;
808+ // Check for numbers ending with zeros (but not hex numbers)
809+ if best_candidate. ends_with ( '0' ) && !best_candidate. starts_with ( "0x" ) {
810+ if let Some ( ( len, _) ) =
811+ best_candidate. bytes ( ) . rev ( ) . enumerate ( ) . find ( |( _, c) | * c != b'0' )
812+ {
813+ let base = & best_candidate[ 0 ..best_candidate. len ( ) - len] ;
814+ let scientific_candidate = format ! ( "{base}e{len}" ) ;
815+ if scientific_candidate. len ( ) < best_len {
816+ best_candidate = scientific_candidate. into ( ) ;
817+ best_len = best_candidate. len ( ) ;
818+ }
800819 }
801820 }
802821
803- // `1.2e101` -> ("1", "2", "101")
804- // `1.3415205933077406e300` -> `13415205933077406e284;`
805- if let Some ( ( integer , point , exponent ) ) =
806- s . split_once ( '.' ) . and_then ( |( a, b) | b. split_once ( 'e' ) . map ( |e| ( a, e. 0 , e. 1 ) ) )
822+ // Check for scientific notation optimization: `1.2e101` -> `12e100`
823+ if let Some ( ( integer , point , exponent ) ) = best_candidate
824+ . split_once ( '.' )
825+ . and_then ( |( a, b) | b. split_once ( 'e' ) . map ( |e| ( a, e. 0 , e. 1 ) ) )
807826 {
808- candidates. push ( Cow :: Owned ( format ! (
809- "{integer}{point}e{}" ,
810- exponent. parse:: <isize >( ) . unwrap( ) - point. len( ) as isize
811- ) ) ) ;
827+ let new_exp = exponent. parse :: < isize > ( ) . unwrap ( ) - point. len ( ) as isize ;
828+ let optimized_candidate = format ! ( "{integer}{point}e{new_exp}" ) ;
829+ if optimized_candidate. len ( ) < best_len {
830+ best_candidate = optimized_candidate. into ( ) ;
831+ }
812832 }
813833
814- candidates. into_iter ( ) . min_by_key ( |c| c. len ( ) ) . unwrap ( )
834+ // Print the best candidate
835+ self . print_str ( & best_candidate) ;
836+
837+ // Update need_space_before_dot based on the final output
838+ if !best_candidate. bytes ( ) . any ( |b| matches ! ( b, b'.' | b'e' | b'x' ) ) {
839+ self . need_space_before_dot = self . code_len ( ) ;
840+ }
815841 }
816842
817843 fn add_source_mapping ( & mut self , span : Span ) {
0 commit comments