@@ -60,6 +60,35 @@ const STRINGS = {
6060 }
6161} ;
6262
63+ // Pre-computed lookup tables for performance optimization
64+ const BINARY_POWERS = [
65+ 1 , // 2^0
66+ 1024 , // 2^10
67+ 1048576 , // 2^20
68+ 1073741824 , // 2^30
69+ 1099511627776 , // 2^40
70+ 1125899906842624 , // 2^50
71+ 1152921504606846976 , // 2^60
72+ 1180591620717411303424 , // 2^70
73+ 1208925819614629174706176 // 2^80
74+ ] ;
75+
76+ const DECIMAL_POWERS = [
77+ 1 , // 10^0
78+ 1000 , // 10^3
79+ 1000000 , // 10^6
80+ 1000000000 , // 10^9
81+ 1000000000000 , // 10^12
82+ 1000000000000000 , // 10^15
83+ 1000000000000000000 , // 10^18
84+ 1000000000000000000000 , // 10^21
85+ 1000000000000000000000000 // 10^24
86+ ] ;
87+
88+ // Pre-computed log values for faster exponent calculation
89+ const LOG_2_1024 = Math . log ( 1024 ) ;
90+ const LOG_10_1000 = Math . log ( 1000 ) ;
91+
6392/**
6493 * Converts a file size in bytes to a human-readable string with appropriate units
6594 * @param {number|string|bigint } arg - The file size in bytes to convert
@@ -111,21 +140,31 @@ function filesize (arg, {
111140 val = 0 ,
112141 u = EMPTY ;
113142
114- // Sync base & standard
143+ // Optimized base & standard synchronization with early returns
144+ let isDecimal , ceil , actualStandard ;
115145 if ( standard === SI ) {
116- base = 10 ;
117- standard = JEDEC ;
118- } else if ( standard === IEC || standard === JEDEC ) {
119- base = 2 ;
146+ isDecimal = true ;
147+ ceil = 1000 ;
148+ actualStandard = JEDEC ;
149+ } else if ( standard === IEC ) {
150+ isDecimal = false ;
151+ ceil = 1024 ;
152+ actualStandard = IEC ;
153+ } else if ( standard === JEDEC ) {
154+ isDecimal = false ; // JEDEC uses binary (1024) by default
155+ ceil = 1024 ;
156+ actualStandard = JEDEC ;
120157 } else if ( base === 2 ) {
121- standard = IEC ;
158+ isDecimal = false ;
159+ ceil = 1024 ;
160+ actualStandard = IEC ;
122161 } else {
123- base = 10 ;
124- standard = JEDEC ;
162+ isDecimal = true ;
163+ ceil = 1000 ;
164+ actualStandard = JEDEC ;
125165 }
126166
127- const ceil = base === 10 ? 1000 : 1024 ,
128- full = fullform === true ,
167+ const full = fullform === true ,
129168 neg = num < 0 ,
130169 roundingFunc = Math [ roundingMethod ] ;
131170
@@ -142,9 +181,39 @@ function filesize (arg, {
142181 num = - num ;
143182 }
144183
145- // Determining the exponent
184+ // Fast path for zero
185+ if ( num === 0 ) {
186+ result [ 0 ] = precision > 0 ? ( 0 ) . toPrecision ( precision ) : 0 ;
187+ u = result [ 1 ] = STRINGS . symbol [ actualStandard ] [ bits ? BITS : BYTES ] [ 0 ] ;
188+
189+ if ( output === EXPONENT ) {
190+ return 0 ;
191+ }
192+
193+ // Skip most processing for zero case
194+ if ( symbols [ result [ 1 ] ] ) {
195+ result [ 1 ] = symbols [ result [ 1 ] ] ;
196+ }
197+
198+ if ( full ) {
199+ result [ 1 ] = fullforms [ 0 ] || STRINGS . fullform [ actualStandard ] [ 0 ] + ( bits ? BIT : BYTE ) ;
200+ }
201+
202+ return output === ARRAY ? result : output === OBJECT ? {
203+ value : result [ 0 ] ,
204+ symbol : result [ 1 ] ,
205+ exponent : 0 ,
206+ unit : u
207+ } : result . join ( spacer ) ;
208+ }
209+
210+ // Optimized exponent calculation using pre-computed log values
146211 if ( e === - 1 || isNaN ( e ) ) {
147- e = Math . floor ( Math . log ( num ) / Math . log ( ceil ) ) ;
212+ if ( isDecimal ) {
213+ e = Math . floor ( Math . log ( num ) / LOG_10_1000 ) ;
214+ } else {
215+ e = Math . floor ( Math . log ( num ) / LOG_2_1024 ) ;
216+ }
148217
149218 if ( e < 0 ) {
150219 e = 0 ;
@@ -156,67 +225,73 @@ function filesize (arg, {
156225 if ( precision > 0 ) {
157226 precision += 8 - e ;
158227 }
159-
160228 e = 8 ;
161229 }
162230
163231 if ( output === EXPONENT ) {
164232 return e ;
165233 }
166234
167- // Zero is now a special case because bytes divide by 1
168- if ( num === 0 ) {
169- result [ 0 ] = 0 ;
170-
171- if ( precision > 0 ) {
172- result [ 0 ] = result [ 0 ] . toPrecision ( precision ) ;
173- }
174-
175- u = result [ 1 ] = STRINGS . symbol [ standard ] [ bits ? BITS : BYTES ] [ e ] ;
235+ // Use pre-computed lookup tables (e is always <= 8, arrays have 9 elements)
236+ let d ;
237+ if ( isDecimal ) {
238+ d = DECIMAL_POWERS [ e ] ;
176239 } else {
177- let d = base === 2 ? Math . pow ( 2 , e * 10 ) : Math . pow ( 1000 , e ) ;
178- val = num / d ;
240+ d = BINARY_POWERS [ e ] ;
241+ }
242+
243+ val = num / d ;
179244
180- if ( bits ) {
181- val = val * 8 ;
245+ if ( bits ) {
246+ val = val * 8 ;
182247
183- if ( val >= ceil && e < 8 ) {
184- val = val / ceil ;
185- e ++ ;
186- }
248+ if ( val >= ceil && e < 8 ) {
249+ val = val / ceil ;
250+ e ++ ;
187251 }
252+ }
188253
189- let p = Math . pow ( 10 , e > 0 ? round : 0 ) ;
190- result [ 0 ] = roundingFunc ( val * p ) / p ;
254+ // Optimize rounding calculation
255+ const p = e > 0 && round > 0 ? Math . pow ( 10 , round ) : 1 ;
256+ result [ 0 ] = p === 1 ? roundingFunc ( val ) : roundingFunc ( val * p ) / p ;
191257
192- if ( result [ 0 ] === ceil && e < 8 && exponent === - 1 ) {
193- result [ 0 ] = 1 ;
194- e ++ ;
195- }
258+ if ( result [ 0 ] === ceil && e < 8 && exponent === - 1 ) {
259+ result [ 0 ] = 1 ;
260+ e ++ ;
261+ }
196262
197- // Setting optional precision
198- if ( precision > 0 ) {
199- result [ 0 ] = result [ 0 ] . toPrecision ( precision ) ;
263+ // Setting optional precision
264+ if ( precision > 0 ) {
265+ result [ 0 ] = result [ 0 ] . toPrecision ( precision ) ;
200266
201- if ( result [ 0 ] . includes ( E ) && e < 8 ) {
202- e ++ ;
203- d = base === 2 ? Math . pow ( 2 , e * 10 ) : Math . pow ( 1000 , e ) ;
204- val = num / d ;
205- result [ 0 ] = ( roundingFunc ( val * p ) / p ) . toPrecision ( precision ) ;
267+ if ( result [ 0 ] . includes ( E ) && e < 8 ) {
268+ e ++ ;
269+ // Recalculate with new exponent (e is always <= 8)
270+ if ( isDecimal ) {
271+ d = DECIMAL_POWERS [ e ] ;
272+ } else {
273+ d = BINARY_POWERS [ e ] ;
206274 }
275+ val = num / d ;
276+ result [ 0 ] = ( p === 1 ? roundingFunc ( val ) : roundingFunc ( val * p ) / p ) . toPrecision ( precision ) ;
207277 }
208-
209- u = result [ 1 ] = base === 10 && e === 1 ? bits ? SI_KBIT : SI_KBYTE : STRINGS . symbol [ standard ] [ bits ? BITS : BYTES ] [ e ] ;
210278 }
211279
280+ // Cache symbol lookup
281+ const symbolTable = STRINGS . symbol [ actualStandard ] [ bits ? BITS : BYTES ] ;
282+ u = result [ 1 ] = ( isDecimal && e === 1 ) ? ( bits ? SI_KBIT : SI_KBYTE ) : symbolTable [ e ] ;
283+
212284 // Decorating a 'diff'
213285 if ( neg ) {
214286 result [ 0 ] = - result [ 0 ] ;
215287 }
216288
217289 // Applying custom symbol
218- result [ 1 ] = symbols [ result [ 1 ] ] || result [ 1 ] ;
290+ if ( symbols [ result [ 1 ] ] ) {
291+ result [ 1 ] = symbols [ result [ 1 ] ] ;
292+ }
219293
294+ // Optimized locale/separator handling
220295 if ( locale === true ) {
221296 result [ 0 ] = result [ 0 ] . toLocaleString ( ) ;
222297 } else if ( locale . length > 0 ) {
@@ -226,9 +301,9 @@ function filesize (arg, {
226301 }
227302
228303 if ( pad && round > 0 ) {
229- const i = result [ 0 ] . toString ( ) ,
230- x = separator || ( ( i . match ( / ( \D ) / g) || [ ] ) . pop ( ) || PERIOD ) ,
231- tmp = i . toString ( ) . split ( x ) ,
304+ const resultStr = result [ 0 ] . toString ( ) ,
305+ x = separator || ( ( resultStr . match ( / ( \D ) / g) || [ ] ) . pop ( ) || PERIOD ) ,
306+ tmp = resultStr . split ( x ) ,
232307 s = tmp [ 1 ] || EMPTY ,
233308 l = s . length ,
234309 n = round - l ;
@@ -237,16 +312,24 @@ function filesize (arg, {
237312 }
238313
239314 if ( full ) {
240- result [ 1 ] = fullforms [ e ] ? fullforms [ e ] : STRINGS . fullform [ standard ] [ e ] + ( bits ? BIT : BYTE ) + ( result [ 0 ] === 1 ? EMPTY : S ) ;
315+ result [ 1 ] = fullforms [ e ] || STRINGS . fullform [ actualStandard ] [ e ] + ( bits ? BIT : BYTE ) + ( result [ 0 ] === 1 ? EMPTY : S ) ;
241316 }
242317
243- // Returning Array, Object, or String (default)
244- return output === ARRAY ? result : output === OBJECT ? {
245- value : result [ 0 ] ,
246- symbol : result [ 1 ] ,
247- exponent : e ,
248- unit : u
249- } : result . join ( spacer ) ;
318+ // Optimized return logic
319+ if ( output === ARRAY ) {
320+ return result ;
321+ }
322+
323+ if ( output === OBJECT ) {
324+ return {
325+ value : result [ 0 ] ,
326+ symbol : result [ 1 ] ,
327+ exponent : e ,
328+ unit : u
329+ } ;
330+ }
331+
332+ return spacer === SPACE ? `${ result [ 0 ] } ${ result [ 1 ] } ` : result . join ( spacer ) ;
250333}
251334
252335/**
0 commit comments