Skip to content

Commit f1e4e28

Browse files
authored
feat(ecmascript): Array.prototype.reverse (#445)
1 parent 9a199b4 commit f1e4e28

File tree

3 files changed

+74
-16
lines changed

3 files changed

+74
-16
lines changed

nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_prototype.rs

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2088,8 +2088,77 @@ impl ArrayPrototype {
20882088
Ok(accumulator)
20892089
}
20902090

2091-
fn reverse(_agent: &mut Agent, _this_value: Value, _: ArgumentsList) -> JsResult<Value> {
2092-
todo!()
2091+
fn reverse(agent: &mut Agent, this_value: Value, _: ArgumentsList) -> JsResult<Value> {
2092+
if let Value::Array(array) = this_value {
2093+
// Fast path: Array is dense and contains no descriptors. No JS
2094+
// functions can thus be called by shift.
2095+
if array.is_trivial(agent) && array.is_dense(agent) {
2096+
array.as_mut_slice(agent).reverse();
2097+
return Ok(array.into_value());
2098+
}
2099+
}
2100+
2101+
// 1. Let O be ? ToObject(this value).
2102+
let o = to_object(agent, this_value)?;
2103+
// 2. Let len be ? LengthOfArrayLike(O).
2104+
let len = length_of_array_like(agent, o)?;
2105+
// 3. Let middle be floor(len / 2).
2106+
let middle = len / 2;
2107+
// 4. Let lower be 0.
2108+
let mut lower: i64 = 0;
2109+
// 5. Repeat, while lower ≠ middle,
2110+
while lower != middle {
2111+
// a. Let upper be len - lower - 1.
2112+
let upper = len - lower - 1;
2113+
// b. Let upperP be ! ToString(𝔽(upper)).
2114+
let upper_p = PropertyKey::Integer(upper.try_into().unwrap());
2115+
// c. Let lowerP be ! ToString(𝔽(lower)).
2116+
let lower_p = PropertyKey::Integer(lower.try_into().unwrap());
2117+
// d. Let lowerExists be ? HasProperty(O, lowerP).
2118+
// e. If lowerExists is true, then
2119+
// i. Let lowerValue be ? Get(O, lowerP).
2120+
let lower_exists = has_property(agent, o, lower_p)?;
2121+
// f. Let upperExists be ? HasProperty(O, upperP).
2122+
// g. If upperExists is true, then
2123+
// i. Let upperValue be ? Get(O, upperP).
2124+
let upper_exists = has_property(agent, o, upper_p)?;
2125+
2126+
// h. If lowerExists is true and upperExists is true, then
2127+
if lower_exists && upper_exists {
2128+
// i. Perform ? Set(O, lowerP, upperValue, true).
2129+
// ii. Perform ? Set(O, upperP, lowerValue, true).
2130+
let lower_value = get(agent, o, lower_p)?;
2131+
let upper_value = get(agent, o, upper_p)?;
2132+
set(agent, o, lower_p, upper_value, true)?;
2133+
set(agent, o, upper_p, lower_value, true)?;
2134+
}
2135+
// i. Else if lowerExists is false and upperExists is true, then
2136+
else if !lower_exists && upper_exists {
2137+
// i. Perform ? Set(O, lowerP, upperValue, true).
2138+
// ii. Perform ? DeletePropertyOrThrow(O, upperP).
2139+
let upper_value = get(agent, o, upper_p)?;
2140+
set(agent, o, lower_p, upper_value, true)?;
2141+
delete_property_or_throw(agent, o, upper_p)?;
2142+
}
2143+
// j. Else if lowerExists is true and upperExists is false, then
2144+
else if lower_exists && !upper_exists {
2145+
// i. Perform ? DeletePropertyOrThrow(O, lowerP).
2146+
// ii. Perform ? Set(O, upperP, lowerValue, true).
2147+
let lower_value = get(agent, o, lower_p)?;
2148+
delete_property_or_throw(agent, o, lower_p)?;
2149+
set(agent, o, upper_p, lower_value, true)?;
2150+
}
2151+
// k. Else,
2152+
else {
2153+
// i. Assert: lowerExists and upperExists are both false.
2154+
// ii. NOTE: No action is required.
2155+
assert!(!(lower_exists && upper_exists));
2156+
}
2157+
// l. Set lower to lower + 1.
2158+
lower += 1;
2159+
}
2160+
// 6. Return O.
2161+
Ok(o.into_value())
20932162
}
20942163

20952164
/// ### [23.1.3.27 Array.prototype.shift ( )](https://tc39.es/ecma262/#sec-array.prototype.shift)

tests/expectations.json

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -357,18 +357,7 @@
357357
"built-ins/Array/prototype/reduceRight/resizable-buffer-grow-mid-iteration.js": "CRASH",
358358
"built-ins/Array/prototype/reduceRight/resizable-buffer-shrink-mid-iteration.js": "CRASH",
359359
"built-ins/Array/prototype/reduceRight/resizable-buffer.js": "CRASH",
360-
"built-ins/Array/prototype/reverse/S15.4.4.8_A1_T1.js": "CRASH",
361-
"built-ins/Array/prototype/reverse/S15.4.4.8_A1_T2.js": "CRASH",
362-
"built-ins/Array/prototype/reverse/S15.4.4.8_A2_T1.js": "CRASH",
363-
"built-ins/Array/prototype/reverse/S15.4.4.8_A2_T2.js": "CRASH",
364-
"built-ins/Array/prototype/reverse/S15.4.4.8_A2_T3.js": "CRASH",
365-
"built-ins/Array/prototype/reverse/S15.4.4.8_A3_T3.js": "CRASH",
366-
"built-ins/Array/prototype/reverse/S15.4.4.8_A4_T1.js": "CRASH",
367-
"built-ins/Array/prototype/reverse/S15.4.4.8_A4_T2.js": "CRASH",
368-
"built-ins/Array/prototype/reverse/array-has-one-entry.js": "CRASH",
369-
"built-ins/Array/prototype/reverse/call-with-boolean.js": "CRASH",
370360
"built-ins/Array/prototype/reverse/get_if_present_with_delete.js": "CRASH",
371-
"built-ins/Array/prototype/reverse/length-exceeding-integer-limit-with-object.js": "CRASH",
372361
"built-ins/Array/prototype/reverse/length-exceeding-integer-limit-with-proxy.js": "CRASH",
373362
"built-ins/Array/prototype/reverse/resizable-buffer.js": "CRASH",
374363
"built-ins/Array/prototype/slice/coerced-start-end-grow.js": "CRASH",

tests/metrics.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"results": {
3-
"crash": 16297,
4-
"fail": 8261,
5-
"pass": 20690,
3+
"crash": 16285,
4+
"fail": 8262,
5+
"pass": 20701,
66
"skip": 40,
77
"timeout": 3,
88
"unresolved": 0

0 commit comments

Comments
 (0)