From 94992a4a8c5294df05209f71ff5758df1cb34ae3 Mon Sep 17 00:00:00 2001 From: Kevin <46825870+nekevss@users.noreply.github.com> Date: Sun, 3 Oct 2021 05:05:45 -0400 Subject: [PATCH] Implement Array.prototype.at() (#1613) --- boa/src/builtins/array/mod.rs | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/boa/src/builtins/array/mod.rs b/boa/src/builtins/array/mod.rs index 99dedeb9ed..0b8f1a4a63 100644 --- a/boa/src/builtins/array/mod.rs +++ b/boa/src/builtins/array/mod.rs @@ -86,6 +86,7 @@ impl BuiltIn for Array { values_function, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, ) + .method(Self::at, "at", 1) .method(Self::concat, "concat", 1) .method(Self::push, "push", 1) .method(Self::index_of, "indexOf", 1) @@ -487,6 +488,43 @@ impl Array { Ok(a.into()) } + ///'Array.prototype.at(index)' + /// + /// The at() method takes an integer value and returns the item at that + /// index, allowing for positive and negative integers. Negative integers + /// count back from the last item in the array. + /// + /// More information: + /// - [ECMAScript reference][spec] + /// - [MDN documentation][mdn] + /// + /// [spec]: https://tc39.es/ecma262/#sec-array.prototype.at + /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at + pub(crate) fn at(this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult { + //1. let O be ? ToObject(this value) + let obj = this.to_object(context)?; + //2. let len be ? LengthOfArrayLike(O) + let len = obj.length_of_array_like(context)? as i64; + //3. let relativeIndex be ? ToIntegerOrInfinity(index) + let relative_index = args.get_or_undefined(0).to_integer_or_infinity(context)?; + let k = match relative_index { + //4. if relativeIndex >= 0, then let k be relativeIndex + //check if positive and if below length of array + IntegerOrInfinity::Integer(i) if i >= 0 && i < len => i, + //5. Else, let k be len + relativeIndex + //integer should be negative, so abs() and check if less than or equal to length of array + IntegerOrInfinity::Integer(i) if i < 0 && i.abs() <= len => len + i, + //handle most likely impossible case of + //IntegerOrInfinity::NegativeInfinity || IntegerOrInfinity::PositiveInfinity + //by returning undefined + _ => return Ok(JsValue::undefined()), + }; + //6. if k < 0 or k >= len, + //handled by the above match guards + //7. Return ? Get(O, !ToString(𝔽(k))) + obj.get(k, context) + } + /// `Array.prototype.concat(...arguments)` /// /// When the concat method is called with zero or more arguments, it returns an