@@ -2470,6 +2470,7 @@ impl BuiltinTypedArray {
24702470 ///
24712471 /// [spec]: https://tc39.es/ecma262/#sec-%typedarray%.prototype.tolocalestring
24722472 /// [spec-402]: https://402.ecma-international.org/10.0/#sup-array.prototype.tolocalestring
2473+ #[ allow( clippy:: used_underscore_binding) ]
24732474 pub ( crate ) fn to_locale_string (
24742475 this : & JsValue ,
24752476 args : & [ JsValue ] ,
@@ -2482,7 +2483,7 @@ impl BuiltinTypedArray {
24822483 JsNativeError :: typ ( ) . with_message ( "Value is not a typed array object" )
24832484 } ) ?;
24842485
2485- let ( len, is_bigint ) = {
2486+ let ( len, _is_bigint ) = {
24862487 let o = array. downcast_ref :: < TypedArray > ( ) . ok_or_else ( || {
24872488 JsNativeError :: typ ( ) . with_message ( "Value is not a typed array object" )
24882489 } ) ?;
@@ -2511,7 +2512,7 @@ impl BuiltinTypedArray {
25112512 let options = args. get_or_undefined ( 1 ) . clone ( ) ;
25122513
25132514 #[ cfg( feature = "intl" ) ]
2514- let number_format = if is_bigint {
2515+ let number_format = if _is_bigint {
25152516 None
25162517 } else {
25172518 use crate :: builtins:: intl:: number_format:: NumberFormat ;
@@ -2523,6 +2524,22 @@ impl BuiltinTypedArray {
25232524
25242525 let call_args = [ locales, options] ;
25252526
2527+ #[ cfg( feature = "intl" ) ]
2528+ let is_unmodified = {
2529+ let number_proto = context. intrinsics ( ) . constructors ( ) . number ( ) . prototype ( ) ;
2530+
2531+ let current_tls = number_proto. get ( js_string ! ( "toLocaleString" ) , context) ?;
2532+
2533+ let builtin_tls = context
2534+ . intrinsics ( )
2535+ . objects ( )
2536+ . number_prototype_to_locale_string ( ) ;
2537+
2538+ current_tls
2539+ . as_object ( )
2540+ . is_some_and ( |o| JsObject :: equals ( & o, & builtin_tls. into ( ) ) )
2541+ } ;
2542+
25262543 // 5. Let k be 0.
25272544 // 6. Repeat, while k < len,
25282545 for k in 0 ..len {
@@ -2537,21 +2554,35 @@ impl BuiltinTypedArray {
25372554 }
25382555
25392556 #[ cfg( feature = "intl" ) ]
2540- if is_bigint {
2541- let s = next_element
2542- . invoke ( js_string ! ( "toLocaleString" ) , & call_args, context) ?
2543- . to_string ( context) ?;
2544- r. push ( s) ;
2545- } else {
2546- use crate :: builtins:: intl:: number_format:: to_intl_mathematical_value;
2547- let mut x = to_intl_mathematical_value ( & next_element, context) ?;
2548- r. push ( js_string ! (
2549- number_format
2550- . as_ref( )
2551- . expect( "number_format should be initialized for numeric typed arrays" )
2552- . format( & mut x)
2553- . to_string( )
2554- ) ) ;
2557+ {
2558+ use crate :: {
2559+ builtins:: intl:: number_format:: to_intl_mathematical_value, value:: JsVariant ,
2560+ } ;
2561+
2562+ // Fast path: finite primitive numbers only
2563+ let use_fast_path = is_unmodified
2564+ && match next_element. variant ( ) {
2565+ JsVariant :: Integer32 ( _) => !_is_bigint,
2566+ JsVariant :: Float64 ( f) => !_is_bigint && f. is_finite ( ) ,
2567+ _ => false ,
2568+ } ;
2569+
2570+ if use_fast_path {
2571+ let mut x = to_intl_mathematical_value ( & next_element, context) ?;
2572+ r. push ( js_string ! (
2573+ number_format
2574+ . as_ref( )
2575+ . expect( "number_format is Some for numeric typed arrays" )
2576+ . format( & mut x)
2577+ . to_string( )
2578+ ) ) ;
2579+ } else {
2580+ // Slow path: delegate to element.toLocaleString()
2581+ let s = next_element
2582+ . invoke ( js_string ! ( "toLocaleString" ) , & call_args, context) ?
2583+ . to_string ( context) ?;
2584+ r. push ( s) ;
2585+ }
25552586 }
25562587
25572588 #[ cfg( not( feature = "intl" ) ) ]
@@ -2566,7 +2597,7 @@ impl BuiltinTypedArray {
25662597 // 7. Return R.
25672598 let separator = js_string ! ( ", " ) ;
25682599 let mut result = Vec :: with_capacity (
2569- r. iter ( ) . map ( boa_string :: JsString :: len) . sum :: < usize > ( )
2600+ r. iter ( ) . map ( JsString :: len) . sum :: < usize > ( )
25702601 + separator. len ( ) * ( len. saturating_sub ( 1 ) as usize ) ,
25712602 ) ;
25722603 for ( i, s) in r. into_iter ( ) . enumerate ( ) {
0 commit comments