diff --git a/include/hermes/VM/NativeFunctions.def b/include/hermes/VM/NativeFunctions.def index 3e605b6a5df..d35e363b81a 100644 --- a/include/hermes/VM/NativeFunctions.def +++ b/include/hermes/VM/NativeFunctions.def @@ -392,6 +392,7 @@ NATIVE_FUNCTION(typedArrayPrototypeSort) NATIVE_FUNCTION(typedArrayPrototypeSubarray) NATIVE_FUNCTION(typedArrayPrototypeSymbolToStringTag) NATIVE_FUNCTION(typedArrayPrototypeToLocaleString) +NATIVE_FUNCTION(typedArrayPrototypeToReversed) NATIVE_FUNCTION(unescape) NATIVE_FUNCTION(weakMapConstructor) NATIVE_FUNCTION(weakMapPrototypeDelete) diff --git a/lib/VM/JSLib/TypedArray.cpp b/lib/VM/JSLib/TypedArray.cpp index f491f5bf2b7..ac2dd307a82 100644 --- a/lib/VM/JSLib/TypedArray.cpp +++ b/lib/VM/JSLib/TypedArray.cpp @@ -1746,6 +1746,60 @@ typedArrayPrototypeToLocaleString(void *, Runtime &runtime, NativeArgs args) { return HermesValue::encodeStringValue(*builder->getStringPrimitive()); } +/// ES14.0 23.2.3.32 +CallResult +typedArrayPrototypeToReversed(void *, Runtime &runtime, NativeArgs args) { + GCScope gcScope{runtime}; + + // 2. Perform ? ValidateTypedArray(O). + if (JSTypedArrayBase::validateTypedArray(runtime, args.getThisHandle()) == + ExecutionStatus::EXCEPTION) { + return ExecutionStatus::EXCEPTION; + } + + // 1. Let O be this value + auto self = args.vmcastThis(); + + // 3. Let len be O.[[ArrayLength]]. + double len = self->getLength(); + + // 4. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »). + auto aRes = JSTypedArrayBase::allocateSpecies(runtime, self, len); + if (LLVM_UNLIKELY(aRes == ExecutionStatus::EXCEPTION)) { + return ExecutionStatus::EXCEPTION; + } + auto A = aRes.getValue(); + + // 5. Let k be 0. + double k = 0; + MutableHandle<> fromValueHandle{runtime}; + + auto marker = gcScope.createMarker(); + // 6. Repeat, while k < len, + while (k < len) { + gcScope.flushToMarker(marker); + + // 6a. Let from be ! ToString(𝔽(length - k - 1)). + double from = len - k - 1; + + // 6c. Let fromValue be ? Get(O, from). + fromValueHandle = + JSObject::getOwnIndexed(createPseudoHandle(self.get()), runtime, from); + + // 6d. Perform ! Set(A, Pk, fromValue, true). + if (LLVM_UNLIKELY( + A->setOwnIndexed(A, runtime, k, fromValueHandle) == + ExecutionStatus::EXCEPTION)) { + return ExecutionStatus::EXCEPTION; + } + + // 6e. Set k to k + 1. + ++k; + } + + return A.getHermesValue(); +} + Handle createTypedArrayBaseConstructor(Runtime &runtime) { auto proto = Handle::vmcast(&runtime.typedArrayBasePrototype); @@ -2044,6 +2098,14 @@ Handle createTypedArrayBaseConstructor(Runtime &runtime) { typedArrayPrototypeToLocaleString, 0); + defineMethod( + runtime, + proto, + Predefined::getSymbolID(Predefined::toReversed), + nullptr, + typedArrayPrototypeToReversed, + 0); + // TypedArrayBase.xxx defineMethod( runtime, diff --git a/test/hermes/TypedArray.js b/test/hermes/TypedArray.js index 4955e420cad..6d53106637e 100644 --- a/test/hermes/TypedArray.js +++ b/test/hermes/TypedArray.js @@ -1438,6 +1438,16 @@ cons.forEach(function(TypedArray) { }); /// @} +/// @name TypedArray.prototype.toReversed +/// @{ +cons.forEach(function(TypedArray) { + var arr = new TypedArray([ 0, 1, 2, 3 ]); + + assert.arrayEqual(arr.toReversed(), [ 3, 2, 1, 0 ]); + assert.arrayEqual(new TypedArray([]).toReversed(), []); +}); +/// @} + /// @name Exception cases /// @{