diff --git a/ecmascript/builtins/builtins_array.cpp b/ecmascript/builtins/builtins_array.cpp index ebc838c025..ceb366ce84 100644 --- a/ecmascript/builtins/builtins_array.cpp +++ b/ecmascript/builtins/builtins_array.cpp @@ -2936,6 +2936,9 @@ JSTaggedValue BuiltinsArray::At(EcmaRuntimeCallInfo *argv) // 1. Let O be ToObject(this value). JSHandle thisHandle = GetThis(argv); + if (thisHandle->IsStableJSArray(thread)) { + return JSStableArray::At(JSHandle::Cast(thisHandle), argv); + } JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); // ReturnIfAbrupt(O). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); diff --git a/ecmascript/js_stable_array.cpp b/ecmascript/js_stable_array.cpp index 94f85eb807..526960e160 100644 --- a/ecmascript/js_stable_array.cpp +++ b/ecmascript/js_stable_array.cpp @@ -658,4 +658,30 @@ JSTaggedValue JSStableArray::FastCopyFromArrayToTypedArray(JSThread *thread, JSH } return JSTaggedValue::Undefined(); } + +JSTaggedValue JSStableArray::At(JSHandle receiver, EcmaRuntimeCallInfo *argv) +{ + JSThread *thread = argv->GetThread(); + uint32_t thisLen = receiver->GetArrayLength(); + if (thisLen == 0) { + return JSTaggedValue::Undefined(); + } + JSTaggedNumber index = JSTaggedValue::ToInteger(thread, base::BuiltinsBase::GetCallArg(argv, 0)); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + int64_t relativeIndex = index.GetNumber(); + int64_t k = 0; + if (relativeIndex >= 0) { + k = relativeIndex; + } else { + k = thisLen + relativeIndex; + } + if (k < 0 || k >= thisLen) { + return JSTaggedValue::Undefined(); + } + + TaggedArray *elements = TaggedArray::Cast(receiver->GetElements().GetTaggedObject()); + auto result = JSTaggedValue::Hole(); + result = elements->Get(k); + return result.IsHole() ? JSTaggedValue::Undefined() : result; +} } // namespace panda::ecmascript diff --git a/ecmascript/js_stable_array.h b/ecmascript/js_stable_array.h index 48da8cb0ff..96e59ffc95 100644 --- a/ecmascript/js_stable_array.h +++ b/ecmascript/js_stable_array.h @@ -53,6 +53,7 @@ public: static JSTaggedValue FastCopyFromArrayToTypedArray(JSThread *thread, JSHandle &target, DataViewType targetType, uint32_t targetOffset, uint32_t srcLength, JSHandle &elements); + static JSTaggedValue At(JSHandle receiver, EcmaRuntimeCallInfo *argv); }; } // namespace panda::ecmascript #endif // ECMASCRIPT_JS_STABLE_ARRAY_H diff --git a/ecmascript/tests/js_stable_array_test.cpp b/ecmascript/tests/js_stable_array_test.cpp index f9edeccf32..93dade9590 100644 --- a/ecmascript/tests/js_stable_array_test.cpp +++ b/ecmascript/tests/js_stable_array_test.cpp @@ -342,4 +342,67 @@ HWTEST_F_L0(JSStableArrayTest, Join_StringElements_DefinedSep) EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString().c_str(), "a <> a <> a <> a <> a <> a <> a <> a <> a <> a"); } + +/** + * @tc.name: At + * @tc.desc: Create a source Array whose elements are Numbers and an EcmaRuntimeCallInfo, define the first arg of the + EcmaRuntimeCallInfo an number as the index, check whether the element returned through calling + At function with the source Array and the EcmaRuntimeCallInfo is within expectations. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(JSStableArrayTest, At_NUMBER_INDEX) +{ + ObjectFactory *objFactory = thread->GetEcmaVM()->GetFactory(); + + int32_t lengthArr = 10; + JSHandle handleTagArr(objFactory->NewTaggedArray(lengthArr)); + for (int i = 0; i < lengthArr; i++) { + handleTagArr->Set(thread, i, JSTaggedValue(i)); + } + JSHandle handleArr(JSArray::CreateArrayFromList(thread, handleTagArr)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(0)); + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); + + JSTaggedValue thisTagValue = JSStableArray::At(handleArr, ecmaRuntimeCallInfo); + TestHelper::TearDownFrame(thread, prev); + + EXPECT_EQ(thisTagValue.GetNumber(), 0); + + ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(9)); + prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); + + thisTagValue = JSStableArray::At(handleArr, ecmaRuntimeCallInfo); + TestHelper::TearDownFrame(thread, prev); + + EXPECT_EQ(thisTagValue.GetNumber(), 9); + + ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(-1)); + prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); + + thisTagValue = JSStableArray::At(handleArr, ecmaRuntimeCallInfo); + TestHelper::TearDownFrame(thread, prev); + + EXPECT_EQ(thisTagValue.GetNumber(), 9); + + ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(10)); + prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); + + thisTagValue = JSStableArray::At(handleArr, ecmaRuntimeCallInfo); + TestHelper::TearDownFrame(thread, prev); + + EXPECT_EQ(thisTagValue, JSTaggedValue::Undefined()); +} } // namespace panda::test \ No newline at end of file diff --git a/test/moduletest/array/array.js b/test/moduletest/array/array.js index 7fbe3e64d3..2ce9c3b5b1 100644 --- a/test/moduletest/array/array.js +++ b/test/moduletest/array/array.js @@ -134,4 +134,12 @@ try { print(v21); } catch (error) { -} \ No newline at end of file +} + +var arr21 = [1,2,3,4,,6]; +print(arr21.at(0)); +print(arr21.at(5)); +print(arr21.at(-1)); +print(arr21.at(6)); +print(arr21.at('1.9')); +print(arr21.at(true)); \ No newline at end of file diff --git a/test/moduletest/array/expect_output.txt b/test/moduletest/array/expect_output.txt index 9a11f2ddea..7f6652897b 100644 --- a/test/moduletest/array/expect_output.txt +++ b/test/moduletest/array/expect_output.txt @@ -69,3 +69,9 @@ undefined -1 The NewTarget is undefined undefined +1 +6 +6 +undefined +2 +2