Skip to content

Commit d185e77

Browse files
authored
feat(ecmascript): %TypedArray%.prototype.reverse (#593)
1 parent 5c89d6a commit d185e77

File tree

3 files changed

+97
-23
lines changed

3 files changed

+97
-23
lines changed

nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/typed_array_intrinsic_object.rs

+95-4
Original file line numberDiff line numberDiff line change
@@ -1780,13 +1780,69 @@ impl TypedArrayPrototype {
17801780
todo!()
17811781
}
17821782

1783+
/// ### [23.2.3.25 %TypedArray%.prototype.reverse ( )](https://tc39.es/ecma262/multipage/indexed-collections.html#sec-%typedarray%.prototype.map)
1784+
/// 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.
17831785
fn reverse<'gc>(
1784-
_agent: &mut Agent,
1785-
_this_value: Value,
1786+
agent: &mut Agent,
1787+
this_value: Value,
17861788
_: ArgumentsList,
1787-
_gc: GcScope<'gc, '_>,
1789+
gc: GcScope<'gc, '_>,
17881790
) -> JsResult<Value<'gc>> {
1789-
todo!()
1791+
let gc = gc.nogc();
1792+
// 1. Let O be the this value.
1793+
let o = this_value;
1794+
// 2. Let taRecord be ? ValidateTypedArray(O, seq-cst).
1795+
let ta_record = validate_typed_array(agent, o, Ordering::SeqCst, gc)?;
1796+
// 3. Let len be TypedArrayLength(taRecord).
1797+
let o = ta_record.object;
1798+
let len = match o {
1799+
TypedArray::Int8Array(_)
1800+
| TypedArray::Uint8Array(_)
1801+
| TypedArray::Uint8ClampedArray(_) => typed_array_length::<u8>(agent, &ta_record, gc),
1802+
#[cfg(feature = "proposal-float16array")]
1803+
TypedArray::Float16Array(_) => typed_array_length::<f16>(agent, &ta_record, gc),
1804+
TypedArray::Int16Array(_) | TypedArray::Uint16Array(_) => {
1805+
typed_array_length::<u16>(agent, &ta_record, gc)
1806+
}
1807+
TypedArray::Int32Array(_)
1808+
| TypedArray::Uint32Array(_)
1809+
| TypedArray::Float32Array(_) => typed_array_length::<u32>(agent, &ta_record, gc),
1810+
TypedArray::BigInt64Array(_)
1811+
| TypedArray::BigUint64Array(_)
1812+
| TypedArray::Float64Array(_) => typed_array_length::<u64>(agent, &ta_record, gc),
1813+
} as i64;
1814+
// 4. Let middle be floor(len / 2).
1815+
// 5. Let lower be 0.
1816+
let len = len as usize;
1817+
let o = o.scope(agent, gc).get(agent);
1818+
// 6. Repeat, while lower ≠ middle,
1819+
// a. Let upper be len - lower - 1.
1820+
// b. Let upperP be ! ToString(𝔽(upper)).
1821+
// c. Let lowerP be ! ToString(𝔽(lower)).
1822+
// d. Let lowerValue be ! Get(O, lowerP).
1823+
// e. Let upperValue be ! Get(O, upperP).
1824+
// f. Perform ! Set(O, lowerP, upperValue, true).
1825+
// g. Perform ! Set(O, upperP, lowerValue, true).
1826+
// h. Set lower to lower + 1.
1827+
match o {
1828+
TypedArray::Int8Array(_) => reverse_typed_array::<i8>(agent, o, len, gc)?,
1829+
TypedArray::Uint8Array(_) => reverse_typed_array::<u8>(agent, o, len, gc)?,
1830+
TypedArray::Uint8ClampedArray(_) => {
1831+
reverse_typed_array::<U8Clamped>(agent, o, len, gc)?
1832+
}
1833+
TypedArray::Int16Array(_) => reverse_typed_array::<i16>(agent, o, len, gc)?,
1834+
TypedArray::Uint16Array(_) => reverse_typed_array::<u16>(agent, o, len, gc)?,
1835+
TypedArray::Int32Array(_) => reverse_typed_array::<i32>(agent, o, len, gc)?,
1836+
TypedArray::Uint32Array(_) => reverse_typed_array::<u32>(agent, o, len, gc)?,
1837+
TypedArray::BigInt64Array(_) => reverse_typed_array::<i64>(agent, o, len, gc)?,
1838+
TypedArray::BigUint64Array(_) => reverse_typed_array::<u64>(agent, o, len, gc)?,
1839+
#[cfg(feature = "proposal-float16array")]
1840+
TypedArray::Float16Array(_) => reverse_typed_array::<f16>(agent, o, len, gc)?,
1841+
TypedArray::Float32Array(_) => reverse_typed_array::<f32>(agent, o, len, gc)?,
1842+
TypedArray::Float64Array(_) => reverse_typed_array::<f64>(agent, o, len, gc)?,
1843+
};
1844+
// 7. Return O.
1845+
Ok(o.into_value())
17901846
}
17911847

17921848
fn set<'gc>(
@@ -2150,3 +2206,38 @@ fn search_typed_element<T: Viewable + std::fmt::Debug, const ASCENDING: bool>(
21502206
Ok(slice[..=k].iter().rposition(|&r| r == search_element))
21512207
}
21522208
}
2209+
2210+
fn reverse_typed_array<T: Viewable + Copy + std::fmt::Debug>(
2211+
agent: &mut Agent,
2212+
ta: TypedArray,
2213+
len: usize,
2214+
gc: NoGcScope,
2215+
) -> JsResult<()> {
2216+
let array_buffer = ta.get_viewed_array_buffer(agent, gc);
2217+
let byte_offset = ta.byte_offset(agent);
2218+
let byte_length = ta.byte_length(agent);
2219+
let byte_slice = array_buffer.as_mut_slice(agent);
2220+
if byte_slice.is_empty() {
2221+
return Ok(());
2222+
}
2223+
let byte_slice = if let Some(byte_length) = byte_length {
2224+
let end_index = byte_offset + byte_length;
2225+
if end_index > byte_slice.len() {
2226+
return Ok(());
2227+
}
2228+
&mut byte_slice[byte_offset..end_index]
2229+
} else {
2230+
&mut byte_slice[byte_offset..]
2231+
};
2232+
let (head, slice, _) = unsafe { byte_slice.align_to_mut::<T>() };
2233+
if !head.is_empty() {
2234+
return Err(agent.throw_exception_with_static_message(
2235+
ExceptionType::TypeError,
2236+
"TypedArray is not properly aligned",
2237+
gc,
2238+
));
2239+
}
2240+
let slice = &mut slice[..len];
2241+
slice.reverse();
2242+
Ok(())
2243+
}

tests/expectations.json

-17
Original file line numberDiff line numberDiff line change
@@ -9166,23 +9166,6 @@
91669166
"built-ins/TypedArray/prototype/reduceRight/this-is-not-object.js": "CRASH",
91679167
"built-ins/TypedArray/prototype/reduceRight/this-is-not-typedarray-instance.js": "CRASH",
91689168
"built-ins/TypedArray/prototype/reduceRight/values-are-not-cached.js": "CRASH",
9169-
"built-ins/TypedArray/prototype/reverse/BigInt/detached-buffer.js": "CRASH",
9170-
"built-ins/TypedArray/prototype/reverse/BigInt/get-length-uses-internal-arraylength.js": "CRASH",
9171-
"built-ins/TypedArray/prototype/reverse/BigInt/preserves-non-numeric-properties.js": "CRASH",
9172-
"built-ins/TypedArray/prototype/reverse/BigInt/return-abrupt-from-this-out-of-bounds.js": "CRASH",
9173-
"built-ins/TypedArray/prototype/reverse/BigInt/returns-original-object.js": "CRASH",
9174-
"built-ins/TypedArray/prototype/reverse/BigInt/reverts.js": "CRASH",
9175-
"built-ins/TypedArray/prototype/reverse/detached-buffer.js": "CRASH",
9176-
"built-ins/TypedArray/prototype/reverse/get-length-uses-internal-arraylength.js": "CRASH",
9177-
"built-ins/TypedArray/prototype/reverse/invoked-as-func.js": "CRASH",
9178-
"built-ins/TypedArray/prototype/reverse/invoked-as-method.js": "CRASH",
9179-
"built-ins/TypedArray/prototype/reverse/preserves-non-numeric-properties.js": "CRASH",
9180-
"built-ins/TypedArray/prototype/reverse/resizable-buffer.js": "CRASH",
9181-
"built-ins/TypedArray/prototype/reverse/return-abrupt-from-this-out-of-bounds.js": "CRASH",
9182-
"built-ins/TypedArray/prototype/reverse/returns-original-object.js": "CRASH",
9183-
"built-ins/TypedArray/prototype/reverse/reverts.js": "CRASH",
9184-
"built-ins/TypedArray/prototype/reverse/this-is-not-object.js": "CRASH",
9185-
"built-ins/TypedArray/prototype/reverse/this-is-not-typedarray-instance.js": "CRASH",
91869169
"built-ins/TypedArray/prototype/set/BigInt/array-arg-negative-integer-offset-throws.js": "CRASH",
91879170
"built-ins/TypedArray/prototype/set/BigInt/array-arg-offset-tointeger.js": "CRASH",
91889171
"built-ins/TypedArray/prototype/set/BigInt/array-arg-primitive-toobject.js": "CRASH",

tests/metrics.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"results": {
3-
"crash": 12117,
3+
"crash": 12100,
44
"fail": 7466,
5-
"pass": 27153,
5+
"pass": 27170,
66
"skip": 65,
77
"timeout": 0,
88
"unresolved": 0

0 commit comments

Comments
 (0)