@@ -9,7 +9,7 @@ use num_traits::Zero;
99use super :: {
1010 object:: typed_array_set_element, ContentType , TypedArray , TypedArrayKind , TypedArrayMarker ,
1111} ;
12- use crate :: value:: JsVariant ;
12+ use crate :: { builtins :: array_buffer :: utils :: memmove_naive , value:: JsVariant } ;
1313use crate :: {
1414 builtins:: {
1515 array:: { find_via_predicate, ArrayIterator , Direction } ,
@@ -2048,8 +2048,8 @@ impl BuiltinTypedArray {
20482048
20492049 // a. Set taRecord to MakeTypedArrayWithBufferWitnessRecord(O, seq-cst).
20502050 // b. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
2051- let src_buf_borrow = src_borrow. data . viewed_array_buffer ( ) . as_buffer ( ) ;
2052- let Some ( src_buf) = src_buf_borrow
2051+ let mut src_buf_borrow = src_borrow. data . viewed_array_buffer ( ) . as_buffer_mut ( ) ;
2052+ let Some ( mut src_buf) = src_buf_borrow
20532053 . bytes ( Ordering :: SeqCst )
20542054 . filter ( |s| !src_borrow. data . is_out_of_bounds ( s. len ( ) ) )
20552055 else {
@@ -2067,41 +2067,88 @@ impl BuiltinTypedArray {
20672067 // f. Let targetType be TypedArrayElementType(A).
20682068 let target_type = target_borrow. data . kind ( ) ;
20692069
2070+ if src_type != target_type {
2071+ // h. Else,
2072+ drop ( src_buf_borrow) ;
2073+ drop ( ( src_borrow, target_borrow) ) ;
2074+
2075+ // i. Let n be 0.
2076+ // ii. Let k be startIndex.
2077+ // iii. Repeat, while k < endIndex,
2078+ let src = src. upcast ( ) ;
2079+ let target = target. upcast ( ) ;
2080+ for ( n, k) in ( start_index..end_index) . enumerate ( ) {
2081+ // 1. Let Pk be ! ToString(𝔽(k)).
2082+ // 2. Let kValue be ! Get(O, Pk).
2083+ let k_value = src. get ( k, context) . expect ( "Get cannot fail here" ) ;
2084+
2085+ // 3. Perform ! Set(A, ! ToString(𝔽(n)), kValue, true).
2086+ target
2087+ . set ( n, k_value, true , context)
2088+ . expect ( "Set cannot fail here" ) ;
2089+
2090+ // 4. Set k to k + 1.
2091+ // 5. Set n to n + 1.
2092+ }
2093+
2094+ // 15. Return A.
2095+ return Ok ( target. into ( ) ) ;
2096+ }
2097+
20702098 // g. If srcType is targetType, then
2071- if src_type == target_type {
2072- {
2073- let byte_count = count * src_type. element_size ( ) as usize ;
2099+ {
2100+ let byte_count = count * src_type. element_size ( ) as usize ;
20742101
2075- // i. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
2076- // ii. Let srcBuffer be O.[[ViewedArrayBuffer]].
2077- // iii. Let targetBuffer be A.[[ViewedArrayBuffer]].
2078- let target_borrow = target_borrow;
2079- let mut target_buf = target_borrow. data . viewed_array_buffer ( ) . as_buffer_mut ( ) ;
2080- let mut target_buf = target_buf
2081- . bytes_with_len ( byte_count)
2082- . expect ( "newly created array cannot be detached" ) ;
2102+ // i. NOTE: The transfer must be performed in a manner that preserves the bit-level encoding of the source data.
2103+ // ii. Let srcBuffer be O.[[ViewedArrayBuffer]].
2104+ // iii. Let targetBuffer be A.[[ViewedArrayBuffer]].
2105+
2106+ // iv. Let elementSize be TypedArrayElementSize(O).
2107+ let element_size = src_type. element_size ( ) ;
20832108
2084- // iv . Let elementSize be TypedArrayElementSize(O) .
2085- let element_size = src_type . element_size ( ) ;
2109+ // v . Let srcByteOffset be O.[[ByteOffset]] .
2110+ let src_byte_offset = src_borrow . data . byte_offset ( ) ;
20862111
2087- // v . Let srcByteOffset be O.[[ByteOffset]] .
2088- let src_byte_offset = src_borrow . data . byte_offset ( ) ;
2112+ // vi . Let srcByteIndex be (startIndex × elementSize) + srcByteOffset .
2113+ let src_byte_index = ( start_index * element_size + src_byte_offset ) as usize ;
20892114
2090- // vi . Let srcByteIndex be (startIndex × elementSize) + srcByteOffset .
2091- let src_byte_index = ( start_index * element_size + src_byte_offset ) as usize ;
2115+ // vii . Let targetByteIndex be A.[[ByteOffset]] .
2116+ let target_byte_index = target_borrow . data . byte_offset ( ) as usize ;
20922117
2093- // vii . Let targetByteIndex be A.[[ByteOffset]] .
2094- let target_byte_index = target_borrow . data . byte_offset ( ) as usize ;
2118+ // viii . Let endByteIndex be targetByteIndex + (countBytes × elementSize) .
2119+ // Not needed by the impl.
20952120
2096- // viii. Let endByteIndex be targetByteIndex + (countBytes × elementSize).
2097- // Not needed by the impl.
2121+ // ix. Repeat, while targetByteIndex < endByteIndex,
2122+ // 1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered).
2123+ // 2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered).
2124+ // 3. Set srcByteIndex to srcByteIndex + 1.
2125+ // 4. Set targetByteIndex to targetByteIndex + 1.
2126+ if BufferObject :: equals (
2127+ src_borrow. data . viewed_array_buffer ( ) ,
2128+ target_borrow. data . viewed_array_buffer ( ) ,
2129+ ) {
2130+ // cannot borrow the target mutably (overlapping bytes), but we can move the data instead.
20982131
2099- // ix. Repeat, while targetByteIndex < endByteIndex,
2100- // 1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered).
2101- // 2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered).
2102- // 3. Set srcByteIndex to srcByteIndex + 1.
2103- // 4. Set targetByteIndex to targetByteIndex + 1.
2132+ # [ cfg ( debug_assertions ) ]
2133+ {
2134+ assert ! ( src_buf . subslice_mut ( src_byte_index.. ) . len ( ) >= byte_count ) ;
2135+ assert ! ( src_buf . subslice_mut ( target_byte_index.. ) . len ( ) >= byte_count ) ;
2136+ }
21042137
2138+ // SAFETY: All previous checks put the copied bytes at least within the bounds of `src_buf`.
2139+ unsafe {
2140+ memmove_naive (
2141+ src_buf. as_ptr ( ) ,
2142+ src_byte_index,
2143+ target_byte_index,
2144+ byte_count,
2145+ ) ;
2146+ }
2147+ } else {
2148+ let mut target_buf = target_borrow. data . viewed_array_buffer ( ) . as_buffer_mut ( ) ;
2149+ let mut target_buf = target_buf
2150+ . bytes ( Ordering :: SeqCst )
2151+ . expect ( "newly created array cannot be detached" ) ;
21052152 let src = src_buf. subslice ( src_byte_index..) ;
21062153 let mut target = target_buf. subslice_mut ( target_byte_index..) ;
21072154
@@ -2118,36 +2165,11 @@ impl BuiltinTypedArray {
21182165 memcpy ( src. as_ptr ( ) , target. as_ptr ( ) , byte_count) ;
21192166 }
21202167 }
2121-
2122- // 15. Return A.
2123- Ok ( target. upcast ( ) . into ( ) )
2124- } else {
2125- // h. Else,
2126- drop ( src_buf_borrow) ;
2127- drop ( ( src_borrow, target_borrow) ) ;
2128-
2129- // i. Let n be 0.
2130- // ii. Let k be startIndex.
2131- // iii. Repeat, while k < endIndex,
2132- let src = src. upcast ( ) ;
2133- let target = target. upcast ( ) ;
2134- for ( n, k) in ( start_index..end_index) . enumerate ( ) {
2135- // 1. Let Pk be ! ToString(𝔽(k)).
2136- // 2. Let kValue be ! Get(O, Pk).
2137- let k_value = src. get ( k, context) . expect ( "Get cannot fail here" ) ;
2138-
2139- // 3. Perform ! Set(A, ! ToString(𝔽(n)), kValue, true).
2140- target
2141- . set ( n, k_value, true , context)
2142- . expect ( "Set cannot fail here" ) ;
2143-
2144- // 4. Set k to k + 1.
2145- // 5. Set n to n + 1.
2146- }
2147-
2148- // 15. Return A.
2149- Ok ( target. into ( ) )
21502168 }
2169+
2170+ drop ( target_borrow) ;
2171+ // 15. Return A.
2172+ Ok ( target. upcast ( ) . into ( ) )
21512173 }
21522174
21532175 /// `%TypedArray%.prototype.some ( callbackfn [ , thisArg ] )`
0 commit comments