diff --git a/ecmascript/js_object.cpp b/ecmascript/js_object.cpp index c8cf291d7c..9d14db5c36 100644 --- a/ecmascript/js_object.cpp +++ b/ecmascript/js_object.cpp @@ -252,7 +252,7 @@ bool JSObject::AddElementInternal(JSThread *thread, const JSHandle &re } } } - thread->NotifyStableArrayElementsGuardians(receiver); + thread->NotifyStableArrayElementsGuardians(receiver, StableArrayChangeKind::NOT_PROTO); TaggedArray *elements = TaggedArray::Cast(receiver->GetElements().GetTaggedObject()); if (isDictionary) { @@ -1203,7 +1203,7 @@ bool JSObject::SetPrototype(JSThread *thread, const JSHandle &obj, con JSHandle newClass = JSHClass::TransitionProto(thread, hclass, proto); JSHClass::NotifyHclassChanged(thread, hclass, newClass); obj->SynchronizedSetClass(*newClass); - thread->NotifyStableArrayElementsGuardians(obj); + thread->NotifyStableArrayElementsGuardians(obj, StableArrayChangeKind::PROTO); return true; } diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index d978b6bacc..f4ced7efec 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -361,18 +361,22 @@ void JSThread::ShrinkHandleStorage(int prevIndex) GetCurrentEcmaContext()->ShrinkHandleStorage(prevIndex); } -void JSThread::NotifyStableArrayElementsGuardians(JSHandle receiver) +void JSThread::NotifyStableArrayElementsGuardians(JSHandle receiver, StableArrayChangeKind changeKind) { if (!glueData_.stableArrayElementsGuardians_) { return; } - if (!receiver->GetJSHClass()->IsPrototype()) { + if (!receiver->GetJSHClass()->IsPrototype() && !receiver->IsJSArray()) { return; } auto env = GetEcmaVM()->GetGlobalEnv(); if (receiver.GetTaggedValue() == env->GetObjectFunctionPrototype().GetTaggedValue() || receiver.GetTaggedValue() == env->GetArrayPrototype().GetTaggedValue()) { glueData_.stableArrayElementsGuardians_ = false; + return; + } + if (changeKind == StableArrayChangeKind::PROTO && receiver->IsJSArray()) { + glueData_.stableArrayElementsGuardians_ = false; } } diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 3e1a6c87c4..7c74d905e4 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -59,6 +59,8 @@ enum class BCStubStatus: uint8_t { PROFILE_BC_STUB, }; +enum class StableArrayChangeKind { PROTO, NOT_PROTO }; + struct BCStubEntries { static constexpr size_t EXISTING_BC_HANDLER_STUB_ENTRIES_COUNT = kungfu::BytecodeStubCSigns::NUM_OF_ALL_NORMAL_STUBS; @@ -329,7 +331,7 @@ public: return arrayHClassIndexMap_; } - void NotifyStableArrayElementsGuardians(JSHandle receiver); + void NotifyStableArrayElementsGuardians(JSHandle receiver, StableArrayChangeKind changeKind); bool IsStableArrayElementsGuardiansInvalid() const { diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn index 1e53156f85..d94c1371d9 100644 --- a/test/moduletest/BUILD.gn +++ b/test/moduletest/BUILD.gn @@ -20,6 +20,7 @@ group("ark_js_moduletest") { "arrayfindlast", "arrayforeach", "arrayjoin", + "arrayprotochange", "assignproxy", "async", "asyncgenerator", @@ -141,6 +142,7 @@ group("ark_asm_test") { "arrayfindlast", "arrayforeach", "arrayjoin", + "arrayprotochange", "asmstackoverflow", "assignproxy", "async", @@ -243,6 +245,7 @@ group("ark_asm_single_step_test") { "arrayfindlast", "arrayforeach", "arrayjoin", + "arrayprotochange", "asmstackoverflow", "assignproxy", "async", diff --git a/test/moduletest/arrayprotochange/BUILD.gn b/test/moduletest/arrayprotochange/BUILD.gn new file mode 100755 index 0000000000..68f61dffc2 --- /dev/null +++ b/test/moduletest/arrayprotochange/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_moduletest_action("arrayprotochange") { + deps = [] +} diff --git a/test/moduletest/arrayprotochange/arrayprotochange.js b/test/moduletest/arrayprotochange/arrayprotochange.js new file mode 100644 index 0000000000..01e695fd51 --- /dev/null +++ b/test/moduletest/arrayprotochange/arrayprotochange.js @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @tc.name:arrayprotochange + * @tc.desc:test Array function when prototype changes + * @tc.type: FUNC + * @tc.require: issueI7O616 + */ + +var arr = [0, 1, 2, 3, 4]; +var arr2 = [0, , , 3, 4]; +arr2.__proto__ = arr; +print(arr2[1]); +print(arr2.at(1)); \ No newline at end of file diff --git a/test/moduletest/arrayprotochange/expect_output.txt b/test/moduletest/arrayprotochange/expect_output.txt new file mode 100755 index 0000000000..a45895c8a7 --- /dev/null +++ b/test/moduletest/arrayprotochange/expect_output.txt @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +1 +1