diff --git a/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/typed_array_intrinsic_object.rs b/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/typed_array_intrinsic_object.rs index a38a6092..fa4c1172 100644 --- a/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/typed_array_intrinsic_object.rs +++ b/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/typed_array_intrinsic_object.rs @@ -1780,13 +1780,69 @@ impl TypedArrayPrototype { todo!() } + /// ### [23.2.3.25 %TypedArray%.prototype.reverse ( )](https://tc39.es/ecma262/multipage/indexed-collections.html#sec-%typedarray%.prototype.map) + /// The interpretation and use of the arguments of this method are the same as for Array.prototype.reverse as defined in 23.1.3.26. fn reverse<'gc>( - _agent: &mut Agent, - _this_value: Value, + agent: &mut Agent, + this_value: Value, _: ArgumentsList, - _gc: GcScope<'gc, '_>, + gc: GcScope<'gc, '_>, ) -> JsResult> { - todo!() + let gc = gc.nogc(); + // 1. Let O be the this value. + let o = this_value; + // 2. Let taRecord be ? ValidateTypedArray(O, seq-cst). + let ta_record = validate_typed_array(agent, o, Ordering::SeqCst, gc)?; + // 3. Let len be TypedArrayLength(taRecord). + let o = ta_record.object; + let len = match o { + TypedArray::Int8Array(_) + | TypedArray::Uint8Array(_) + | TypedArray::Uint8ClampedArray(_) => typed_array_length::(agent, &ta_record, gc), + #[cfg(feature = "proposal-float16array")] + TypedArray::Float16Array(_) => typed_array_length::(agent, &ta_record, gc), + TypedArray::Int16Array(_) | TypedArray::Uint16Array(_) => { + typed_array_length::(agent, &ta_record, gc) + } + TypedArray::Int32Array(_) + | TypedArray::Uint32Array(_) + | TypedArray::Float32Array(_) => typed_array_length::(agent, &ta_record, gc), + TypedArray::BigInt64Array(_) + | TypedArray::BigUint64Array(_) + | TypedArray::Float64Array(_) => typed_array_length::(agent, &ta_record, gc), + } as i64; + // 4. Let middle be floor(len / 2). + // 5. Let lower be 0. + let len = len as usize; + let o = o.scope(agent, gc).get(agent); + // 6. Repeat, while lower ≠ middle, + // a. Let upper be len - lower - 1. + // b. Let upperP be ! ToString(𝔽(upper)). + // c. Let lowerP be ! ToString(𝔽(lower)). + // d. Let lowerValue be ! Get(O, lowerP). + // e. Let upperValue be ! Get(O, upperP). + // f. Perform ! Set(O, lowerP, upperValue, true). + // g. Perform ! Set(O, upperP, lowerValue, true). + // h. Set lower to lower + 1. + match o { + TypedArray::Int8Array(_) => reverse_typed_array::(agent, o, len, gc)?, + TypedArray::Uint8Array(_) => reverse_typed_array::(agent, o, len, gc)?, + TypedArray::Uint8ClampedArray(_) => { + reverse_typed_array::(agent, o, len, gc)? + } + TypedArray::Int16Array(_) => reverse_typed_array::(agent, o, len, gc)?, + TypedArray::Uint16Array(_) => reverse_typed_array::(agent, o, len, gc)?, + TypedArray::Int32Array(_) => reverse_typed_array::(agent, o, len, gc)?, + TypedArray::Uint32Array(_) => reverse_typed_array::(agent, o, len, gc)?, + TypedArray::BigInt64Array(_) => reverse_typed_array::(agent, o, len, gc)?, + TypedArray::BigUint64Array(_) => reverse_typed_array::(agent, o, len, gc)?, + #[cfg(feature = "proposal-float16array")] + TypedArray::Float16Array(_) => reverse_typed_array::(agent, o, len, gc)?, + TypedArray::Float32Array(_) => reverse_typed_array::(agent, o, len, gc)?, + TypedArray::Float64Array(_) => reverse_typed_array::(agent, o, len, gc)?, + }; + // 7. Return O. + Ok(o.into_value()) } fn set<'gc>( @@ -2150,3 +2206,38 @@ fn search_typed_element( Ok(slice[..=k].iter().rposition(|&r| r == search_element)) } } + +fn reverse_typed_array( + agent: &mut Agent, + ta: TypedArray, + len: usize, + gc: NoGcScope, +) -> JsResult<()> { + let array_buffer = ta.get_viewed_array_buffer(agent, gc); + let byte_offset = ta.byte_offset(agent); + let byte_length = ta.byte_length(agent); + let byte_slice = array_buffer.as_mut_slice(agent); + if byte_slice.is_empty() { + return Ok(()); + } + let byte_slice = if let Some(byte_length) = byte_length { + let end_index = byte_offset + byte_length; + if end_index > byte_slice.len() { + return Ok(()); + } + &mut byte_slice[byte_offset..end_index] + } else { + &mut byte_slice[byte_offset..] + }; + let (head, slice, _) = unsafe { byte_slice.align_to_mut::() }; + if !head.is_empty() { + return Err(agent.throw_exception_with_static_message( + ExceptionType::TypeError, + "TypedArray is not properly aligned", + gc, + )); + } + let slice = &mut slice[..len]; + slice.reverse(); + Ok(()) +} diff --git a/tests/expectations.json b/tests/expectations.json index 671647b9..3ed352c0 100644 --- a/tests/expectations.json +++ b/tests/expectations.json @@ -9166,23 +9166,6 @@ "built-ins/TypedArray/prototype/reduceRight/this-is-not-object.js": "CRASH", "built-ins/TypedArray/prototype/reduceRight/this-is-not-typedarray-instance.js": "CRASH", "built-ins/TypedArray/prototype/reduceRight/values-are-not-cached.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/BigInt/detached-buffer.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/BigInt/get-length-uses-internal-arraylength.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/BigInt/preserves-non-numeric-properties.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/BigInt/return-abrupt-from-this-out-of-bounds.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/BigInt/returns-original-object.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/BigInt/reverts.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/detached-buffer.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/get-length-uses-internal-arraylength.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/invoked-as-func.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/invoked-as-method.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/preserves-non-numeric-properties.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/resizable-buffer.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/return-abrupt-from-this-out-of-bounds.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/returns-original-object.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/reverts.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/this-is-not-object.js": "CRASH", - "built-ins/TypedArray/prototype/reverse/this-is-not-typedarray-instance.js": "CRASH", "built-ins/TypedArray/prototype/set/BigInt/array-arg-negative-integer-offset-throws.js": "CRASH", "built-ins/TypedArray/prototype/set/BigInt/array-arg-offset-tointeger.js": "CRASH", "built-ins/TypedArray/prototype/set/BigInt/array-arg-primitive-toobject.js": "CRASH", diff --git a/tests/metrics.json b/tests/metrics.json index 027df201..52aa70e6 100644 --- a/tests/metrics.json +++ b/tests/metrics.json @@ -1,8 +1,8 @@ { "results": { - "crash": 12117, + "crash": 12100, "fail": 7466, - "pass": 27153, + "pass": 27170, "skip": 65, "timeout": 0, "unresolved": 0