diff --git a/ecmascript/base/typed_array_helper.cpp b/ecmascript/base/typed_array_helper.cpp index c2506b0b00de009d9c2d253f5695349affdeac4d..1a2a051307a453a77bb0766407b66395cde2b1a8 100644 --- a/ecmascript/base/typed_array_helper.cpp +++ b/ecmascript/base/typed_array_helper.cpp @@ -695,6 +695,22 @@ int32_t TypedArrayHelper::SortCompare(JSThread *thread, const JSHandle &thisHandle) +{ + if (thisHandle->IsJSArray()) { + return JSArray::Cast(thisHandle->GetTaggedObject())->GetArrayLength(); + } + if (thisHandle->IsTypedArray()) { + return JSHandle::Cast(thisHandle)->GetArrayLength(); + } + JSHandle lengthKey = thread->GlobalConstants()->GetHandledLengthString(); + JSHandle lenResult = JSTaggedValue::GetProperty(thread, thisHandle, lengthKey).GetValue(); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, 0); + JSTaggedNumber len = JSTaggedValue::ToLength(thread, lenResult); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, 0); + return len.GetNumber(); +} + int64_t TypedArrayHelper::GetTypedArrayLength(JSThread *thread, const JSHandle &thisHandle) { if (thisHandle->IsTypedArray()) { diff --git a/ecmascript/base/typed_array_helper.h b/ecmascript/base/typed_array_helper.h index 76f577aa8b43f227c2d762eb238b72e3712171ec..c520f700601ca8a4291875a73f9ac81e134ea4ad 100644 --- a/ecmascript/base/typed_array_helper.h +++ b/ecmascript/base/typed_array_helper.h @@ -63,6 +63,7 @@ public: static int32_t SortCompare(JSThread *thread, const JSHandle &callbackfnHandle, const JSHandle &buffer, const JSHandle &firstValue, const JSHandle &secondValue); + static int64_t GetLength(JSThread *thread, const JSHandle &thisHandle); static int64_t GetTypedArrayLength(JSThread *thread, const JSHandle &thisHandle); #define DEFINE_GET_ONHEAP_HCLASS_FROM_TYPE(Type) \ diff --git a/ecmascript/builtins/builtins_array.cpp b/ecmascript/builtins/builtins_array.cpp index 296ce34a82bd43d77f0bc334bf42255eb551b184..25a0f1a8b705757a589b1f23a907b1624c14b3f3 100644 --- a/ecmascript/builtins/builtins_array.cpp +++ b/ecmascript/builtins/builtins_array.cpp @@ -1017,7 +1017,7 @@ JSTaggedValue BuiltinsArray::FindIndex(EcmaRuntimeCallInfo *argv) JSHandle thisObjVal(thisObjHandle); // 3. Let len be ToLength(Get(O, "length")). - uint64_t len = static_cast(ArrayHelper::GetLength(thread, thisObjVal)); + uint64_t len = static_cast(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 37d19411ff52beec0c41107a72bd6a21c8105223..5c1fded8d7ca26db8e12478e323e7ac9ef8d2d94 100644 --- a/ecmascript/builtins/builtins_typedarray.cpp +++ b/ecmascript/builtins/builtins_typedarray.cpp @@ -675,7 +675,69 @@ JSTaggedValue BuiltinsTypedArray::FindIndex(EcmaRuntimeCallInfo *argv) if (!GetThis(argv)->IsTypedArray()) { THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception()); } - return BuiltinsArray::FindIndex(argv); + JSThread *thread = argv->GetThread(); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + + // 1. Let O be the 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 TypedArrayLength(taRecord). + uint64_t len = static_cast(TypedArrayHelper::GetLength(thread, thisObjVal)); + // 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 0. + // 8. Repeat, while k < len + // 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 k. + // g. Increase k by 1. + uint32_t k = 0; + JSTaggedValue callResult = GetTaggedBoolean(true); + if (thisObjVal->IsStableJSArray(thread)) { + callResult = JSStableArray::HandleFindIndexOfStable(thread, thisObjHandle, callbackFnHandle, thisArgHandle, k); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + if (callResult.ToBoolean()) { + return GetTaggedDouble(k); + } + } + JSMutableHandle key(thread, JSTaggedValue::Undefined()); + JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); + const uint32_t argsLength = 3; // 3: «kValue, k, O» + while (k < len) { + 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()); + callResult = JSFunction::Call(info); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + if (callResult.ToBoolean()) { + return GetTaggedDouble(k); + } + k++; + } + + // 9. Return -1. + return GetTaggedDouble(-1); } // 22.2.3.12