diff --git a/ecmascript/builtins/builtins_array.cpp b/ecmascript/builtins/builtins_array.cpp index 389f9b7a5ffc8cb8e58123e7d8ae551277aef9d7..1630d268cbb1aad862bed6c3abf01e67376ff5f9 100644 --- a/ecmascript/builtins/builtins_array.cpp +++ b/ecmascript/builtins/builtins_array.cpp @@ -3290,7 +3290,7 @@ JSTaggedValue BuiltinsArray::FindLast(EcmaRuntimeCallInfo *argv) JSHandle thisObjVal(thisObjHandle); // 3. Let len be ToLength(Get(O, "length")). - int64_t len = ArrayHelper::GetLength(thread, thisObjVal); + int64_t len = ArrayHelper::GetArrayLength(thread, thisObjVal); // 4. ReturnIfAbrupt(len). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); diff --git a/ecmascript/builtins/builtins_typedarray.cpp b/ecmascript/builtins/builtins_typedarray.cpp index d99865c0caaf997ed586984dc6403dcdbf151abd..781a0f6c8a3f0ec259a4f92bce72cfb47e903037 100644 --- a/ecmascript/builtins/builtins_typedarray.cpp +++ b/ecmascript/builtins/builtins_typedarray.cpp @@ -2084,11 +2084,64 @@ JSTaggedValue BuiltinsTypedArray::ToReversed(EcmaRuntimeCallInfo *argv) JSTaggedValue BuiltinsTypedArray::FindLast(EcmaRuntimeCallInfo *argv) { ASSERT(argv); - BUILTINS_API_TRACE(argv->GetThread(), TypedArray, FindLast); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, TypedArray, FindLast); if (!GetThis(argv)->IsTypedArray()) { - THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception()); + THROW_TYPE_ERROR_AND_RETURN(thread, "This is not a TypedArray.", JSTaggedValue::Exception()); + } + + // 1. Let O be ToObject(this value). + JSHandle thisHandle = GetThis(argv); + JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); + // 2. ReturnIfAbrupt(O). + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + JSHandle thisObjVal(thisObjHandle); + + // 3. Let len be ToLength(Get(O, "length")). + int64_t len = JSHandle::Cast(thisHandle)->GetArrayLength(); + // 4. ReturnIfAbrupt(len). + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + // 5. If IsCallable(predicate) is false, throw a TypeError exception. + JSHandle callbackFnHandle = GetCallArg(argv, 0); + if (!callbackFnHandle->IsCallable()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "the predicate is not callable.", JSTaggedValue::Exception()); + } + + // 6. If thisArg was supplied, let T be thisArg; else let T be undefined. + JSHandle thisArgHandle = GetCallArg(argv, 1); + + // 7. Let k be (len - 1). + // 8. Repeat, while k >= 0 + // a. Let Pk be ToString(k). + // b. Let kValue be Get(O, Pk). + // c. ReturnIfAbrupt(kValue). + // d. Let testResult be ToBoolean(Call(predicate, T, «kValue, k, O»)). + // e. ReturnIfAbrupt(testResult). + // f. If testResult is true, return kValue. + // g. Decrease k by 1. + JSMutableHandle key(thread, JSTaggedValue::Undefined()); + int64_t k = len - 1; + JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); + const uint32_t argsLength = 3; // 3: «kValue, k, O» + while (k >= 0) { + JSHandle kValue = JSArray::FastGetPropertyByValue(thread, thisObjVal, k); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + key.Update(JSTaggedValue(k)); + EcmaRuntimeCallInfo *info = + EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisObjVal.GetTaggedValue()); + JSTaggedValue callResult = JSFunction::Call(info); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + if (callResult.ToBoolean()) { + return kValue.GetTaggedValue(); + } + k--; } - return BuiltinsArray::FindLast(argv); + + // 9. Return undefined. + return JSTaggedValue::Undefined(); } // 23.2.3.14