@@ -31,12 +31,13 @@ use crate::type_analysis::{is_array_expr, is_numeric_expr, is_string_expr, recei
3131use crate :: types:: { DOUBLE , I1 , I16 , I32 , I64 , I8 } ;
3232
3333use super :: {
34- array_kind_fact, buffer_access_materialization_reason, emit_typed_feedback_register_site,
35- expr_has_numeric_pointer_free_array_layout, int_range_expr, lower_buffer_load, lower_expr,
36- lower_expr_as_i32, lower_typed_array_load, materialize_js_value, raw_f64_layout_fact,
37- try_lower_flat_const_index_get, typed_feedback_emission_enabled, unbox_str_handle,
38- unbox_to_i64, BufferAccessSpec , FnCtx , PackedF64LoopFact , TypedFeedbackContract ,
39- TypedFeedbackKind ,
34+ array_kind_fact, attach_buffer_view_pointer_state_for_expr,
35+ buffer_access_materialization_reason, emit_typed_feedback_register_site,
36+ expr_has_numeric_pointer_free_array_layout, int_range_expr, invalidate_buffer_view_pointer,
37+ lower_buffer_load, lower_expr, lower_expr_as_i32, lower_typed_array_load, materialize_js_value,
38+ raw_f64_layout_fact, try_lower_flat_const_index_get, typed_feedback_emission_enabled,
39+ unbox_str_handle, unbox_to_i64, BufferAccessSpec , FnCtx , PackedF64LoopFact ,
40+ TypedFeedbackContract , TypedFeedbackKind ,
4041} ;
4142
4243mod guarded_array;
@@ -217,6 +218,40 @@ fn typed_array_index_needs_runtime_key(ctx: &FnCtx<'_>, object: &Expr, index: &E
217218 && !numeric_index_has_loop_array_index_proof ( ctx, object, index)
218219}
219220
221+ fn is_proven_canonical_numeric_string_literal ( key : & [ u8 ] ) -> bool {
222+ if matches ! ( key, b"-0" | b"NaN" | b"Infinity" | b"-Infinity" ) {
223+ return true ;
224+ }
225+
226+ let digits = key. strip_prefix ( b"-" ) . unwrap_or ( key) ;
227+ if digits. is_empty ( )
228+ || ( digits. len ( ) > 1 && digits[ 0 ] == b'0' )
229+ || !digits. iter ( ) . all ( u8:: is_ascii_digit)
230+ {
231+ return false ;
232+ }
233+
234+ // Decimal integers through Number.MAX_SAFE_INTEGER are exact, and this
235+ // range is below the threshold where JS Number#toString switches to
236+ // exponent notation. Their source spelling therefore proves
237+ // CanonicalNumericIndexString without invoking runtime conversion.
238+ digits
239+ . iter ( )
240+ . try_fold ( 0_u64 , |value, digit| {
241+ value. checked_mul ( 10 ) ?. checked_add ( u64:: from ( digit - b'0' ) )
242+ } )
243+ . is_some_and ( |value| value <= 9_007_199_254_740_991 )
244+ }
245+
246+ fn runtime_key_may_expose_typed_array_backing_buffer ( index : & Expr ) -> bool {
247+ match index {
248+ Expr :: String ( key) => !is_proven_canonical_numeric_string_literal ( key. as_bytes ( ) ) ,
249+ Expr :: WtfString ( key) => !is_proven_canonical_numeric_string_literal ( key) ,
250+ Expr :: Integer ( _) | Expr :: Number ( _) => false ,
251+ _ => true ,
252+ }
253+ }
254+
220255fn lower_array_index_get_via_runtime_key (
221256 ctx : & mut FnCtx < ' _ > ,
222257 arr_box : & str ,
@@ -825,6 +860,17 @@ pub(crate) fn lower(ctx: &mut FnCtx<'_>, expr: &Expr) -> Result<String> {
825860 return Ok ( v) ;
826861 }
827862 if typed_array_index_needs_runtime_key ( ctx, object. as_ref ( ) , index. as_ref ( ) ) {
863+ if runtime_key_may_expose_typed_array_backing_buffer ( index) {
864+ if let Expr :: LocalGet ( id) = object. as_ref ( ) {
865+ if ctx. buffer_view_slots . contains_key ( id) {
866+ invalidate_buffer_view_pointer (
867+ ctx,
868+ * id,
869+ MaterializationReason :: MutableAlias ,
870+ ) ;
871+ }
872+ }
873+ }
828874 let arr_box = lower_expr ( ctx, object) ?;
829875 let key_box = lower_expr ( ctx, index) ?;
830876 let blk = ctx. block ( ) ;
@@ -849,6 +895,7 @@ pub(crate) fn lower(ctx: &mut FnCtx<'_>, expr: &Expr) -> Result<String> {
849895 false ,
850896 vec ! [ "typed_array_fallback=untracked_or_unproven" . to_string( ) ] ,
851897 ) ;
898+ attach_buffer_view_pointer_state_for_expr ( ctx, object) ;
852899 return Ok ( result) ;
853900 }
854901
@@ -893,6 +940,7 @@ pub(crate) fn lower(ctx: &mut FnCtx<'_>, expr: &Expr) -> Result<String> {
893940 false ,
894941 vec ! [ "typed_array_fallback=untracked_or_unproven" . to_string( ) ] ,
895942 ) ;
943+ attach_buffer_view_pointer_state_for_expr ( ctx, object) ;
896944 return Ok ( result) ;
897945 }
898946 if is_uint8array_receiver ( ctx, object) && is_numeric_expr ( ctx, index) {
0 commit comments