/* * Copyright (c) 2022 Huawei Device 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. */ #include "ecmascript/object_operator.h" #include "ecmascript/ecma_string.h" #include "ecmascript/global_env.h" #include "ecmascript/global_dictionary-inl.h" #include "ecmascript/js_array.h" #include "ecmascript/property_attributes.h" #include "ecmascript/tagged_array.h" #include "ecmascript/tagged_dictionary.h" #include "ecmascript/tests/test_helper.h" using namespace panda::ecmascript; namespace panda::test { class ObjectOperatorTest : public testing::Test { public: static void SetUpTestCase() { GTEST_LOG_(INFO) << "SetUpTestCase"; } static void TearDownTestCase() { GTEST_LOG_(INFO) << "TearDownCase"; } void SetUp() override { TestHelper::CreateEcmaVMWithScope(instance, thread, scope); } void TearDown() override { TestHelper::DestroyEcmaVMWithScope(instance, scope); } EcmaVM *instance {nullptr}; ecmascript::EcmaHandleScope *scope {nullptr}; JSThread *thread {nullptr}; }; HWTEST_F_L0(ObjectOperatorTest, SetAttr) { JSHandle handleValue1(thread, JSTaggedValue(1)); JSHandle handleValue2(thread, JSTaggedValue(2)); ObjectOperator objectOperator1(thread, handleValue1); ObjectOperator objectOperator2(thread, handleValue2); uint32_t handleAttr1 = 2; objectOperator1.SetAttr(handleAttr1); EXPECT_EQ(objectOperator1.GetAttr().GetPropertyMetaData(), 2); EXPECT_FALSE(objectOperator1.IsPrimitiveAttr()); PropertyAttributes handleAttr2(JSTaggedValue(0)); objectOperator2.SetAttr(handleAttr2); EXPECT_TRUE(objectOperator2.IsPrimitiveAttr()); } HWTEST_F_L0(ObjectOperatorTest, SetFastMode) { JSHandle handleValue(thread, JSTaggedValue(1)); ObjectOperator objectOperator(thread, handleValue); EXPECT_FALSE(objectOperator.IsFastMode()); objectOperator.SetFastMode(false); EXPECT_FALSE(objectOperator.IsFastMode()); objectOperator.SetFastMode(true); EXPECT_TRUE(objectOperator.IsFastMode()); } HWTEST_F_L0(ObjectOperatorTest, SetIsOnPrototype) { JSHandle handleValue(thread, JSTaggedValue(1)); ObjectOperator objectOperator(thread, handleValue); EXPECT_TRUE(objectOperator.IsOnPrototype()); objectOperator.SetIsOnPrototype(true); EXPECT_TRUE(objectOperator.IsOnPrototype()); objectOperator.SetIsOnPrototype(false); EXPECT_FALSE(objectOperator.IsOnPrototype()); } HWTEST_F_L0(ObjectOperatorTest, SetHasReceiver) { JSHandle handleValue(thread, JSTaggedValue(1)); ObjectOperator objectOperator(thread, handleValue); EXPECT_FALSE(objectOperator.HasReceiver()); objectOperator.SetHasReceiver(true); EXPECT_TRUE(objectOperator.HasReceiver()); objectOperator.SetHasReceiver(false); EXPECT_FALSE(objectOperator.HasReceiver()); } HWTEST_F_L0(ObjectOperatorTest, SetIsTransition) { JSHandle handleValue(thread, JSTaggedValue(1)); ObjectOperator objectOperator(thread, handleValue); EXPECT_FALSE(objectOperator.IsTransition()); objectOperator.SetIsTransition(true); EXPECT_TRUE(objectOperator.IsTransition()); objectOperator.SetIsTransition(false); EXPECT_FALSE(objectOperator.IsTransition()); } HWTEST_F_L0(ObjectOperatorTest, SetIndex) { JSHandle handleValue(thread, JSTaggedValue(1)); ObjectOperator objectOperator(thread, handleValue); uint32_t index = 1; objectOperator.SetIndex(index); EXPECT_EQ(objectOperator.GetIndex(), 1U); EXPECT_TRUE(objectOperator.IsFound()); objectOperator.SetIndex(ObjectOperator::NOT_FOUND_INDEX); EXPECT_FALSE(objectOperator.IsFound()); } HWTEST_F_L0(ObjectOperatorTest, SetValue) { JSHandle handleKey(thread, JSTaggedValue(1)); JSHandle handleValue1(thread, JSTaggedValue(2)); JSHandle handleValue2(thread, JSTaggedValue(3)); ObjectOperator objectOperator(thread, handleKey); EXPECT_TRUE(objectOperator.GetValue().IsUndefined()); objectOperator.SetValue(handleValue1.GetTaggedValue()); EXPECT_EQ(objectOperator.GetValue().GetInt(), 2); objectOperator.SetValue(handleValue2.GetTaggedValue()); EXPECT_EQ(objectOperator.GetValue().GetInt(), 3); } HWTEST_F_L0(ObjectOperatorTest, SetAsDefaultAttr) { JSHandle handleKey(thread, JSTaggedValue(1)); ObjectOperator objectOperator(thread, handleKey); objectOperator.SetAsDefaultAttr(); EXPECT_EQ(objectOperator.GetIndex(), ObjectOperator::NOT_FOUND_INDEX); EXPECT_TRUE(objectOperator.GetValue().IsUndefined()); EXPECT_FALSE(objectOperator.IsFastMode()); EXPECT_FALSE(objectOperator.IsTransition()); EXPECT_EQ(objectOperator.GetAttr().GetPropertyMetaData(), 7); } HWTEST_F_L0(ObjectOperatorTest, GetHolder) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle handleHolder = factory->NewEmptyJSObject(); JSHandle handleKey(thread, JSTaggedValue(1)); ObjectOperator objectOperator(thread, handleHolder, handleKey); EXPECT_TRUE(objectOperator.HasHolder()); EXPECT_TRUE(objectOperator.GetHolder().GetTaggedValue().IsECMAObject()); } HWTEST_F_L0(ObjectOperatorTest, GetReceiver) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle handleNameString = factory->NewFromASCII("name"); JSHandle handleReceiver(thread, JSTaggedValue(1)); ObjectOperator objectOperator(thread, handleReceiver.GetTaggedValue(), handleNameString.GetTaggedValue()); EXPECT_EQ(objectOperator.GetReceiver()->GetInt(), 1); } HWTEST_F_L0(ObjectOperatorTest, GetElementIndex) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle handleKey1(thread, JSTaggedValue(1)); JSHandle handleKey2(thread, JSTaggedValue(2.0)); JSHandle handleKey3(factory->NewFromASCII("2")); ObjectOperator objectOperator1(thread, handleKey1); ObjectOperator objectOperator2(thread, handleKey2); ObjectOperator objectOperator3(thread, handleKey3); EXPECT_EQ(objectOperator1.GetElementIndex(), 1U); EXPECT_EQ(objectOperator2.GetElementIndex(), 2U); EXPECT_EQ(objectOperator3.GetElementIndex(), 2U); } HWTEST_F_L0(ObjectOperatorTest, GetKey) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle handleKey1(thread, JSTaggedValue(1)); JSHandle handleKey2(factory->NewFromASCII("name")); ObjectOperator objectOperator1(thread, handleKey1); ObjectOperator objectOperator2(thread, handleKey2); EXPECT_TRUE(objectOperator1.GetKey()->IsUndefined()); EXPECT_TRUE(objectOperator1.IsElement()); EXPECT_FALSE(objectOperator2.GetKey()->IsUndefined()); EXPECT_FALSE(objectOperator2.IsElement()); } HWTEST_F_L0(ObjectOperatorTest, GetThread) { JSHandle handleKey(thread, JSTaggedValue(1)); ObjectOperator objectOperator(thread, handleKey); EXPECT_TRUE(objectOperator.GetThread() != nullptr); } JSTaggedValue TestDefinedGetter([[maybe_unused]] EcmaRuntimeCallInfo *argv) { // 12 : test case return JSTaggedValue(12); } JSTaggedValue TestDefinedSetter([[maybe_unused]] EcmaRuntimeCallInfo *argv) { // 12 : test case return JSTaggedValue(12); } bool TestBoolSetter([[maybe_unused]] JSThread *thread, [[maybe_unused]] JSHandle &jsObject, [[maybe_unused]] JSHandle &value, [[maybe_unused]] bool success) { return true; } static JSFunction *JSObjectTestCreate(JSThread *thread) { JSHandle globalEnv = thread->GetEcmaVM()->GetGlobalEnv(); return globalEnv->GetObjectFunction().GetObject(); } HWTEST_F_L0(ObjectOperatorTest, ToPropertyDescriptor) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle handleKey(factory->NewFromASCII("property")); JSHandle handleValue(thread, JSTaggedValue(1)); JSHandle handleAccessor = factory->NewAccessorData(); JSHandle handleInternalAccessor = factory->NewInternalAccessor(nullptr, reinterpret_cast(TestDefinedGetter)); JSHandle handleHolder(factory->NewEmptyJSObject()); PropertyDescriptor handleDesc(thread); handleDesc.SetGetter(handleValue); handleDesc.SetSetter(handleValue); PropertyDescriptor handleDesc1(thread); handleDesc1.SetWritable(true); PropertyDescriptor handleDesc2(thread); handleDesc2.SetConfigurable(true); handleDesc2.SetEnumerable(true); PropertyDescriptor handleDesc3(thread); PropertyAttributes handleAttr(handleDesc); ObjectOperator objectOperator(thread, handleHolder, handleKey); objectOperator.SetIndex(1); // object is not IsAccessorDescriptor objectOperator.ToPropertyDescriptor(handleDesc1); EXPECT_TRUE(!handleDesc1.IsWritable()); EXPECT_TRUE(handleDesc1.GetValue()->IsUndefined()); // object is IsAccessorDescriptor objectOperator.SetAttr(handleAttr); objectOperator.SetValue(handleAccessor.GetTaggedValue()); objectOperator.ToPropertyDescriptor(handleDesc2); EXPECT_FALSE(handleDesc2.IsEnumerable()); EXPECT_FALSE(handleDesc2.IsConfigurable()); EXPECT_TRUE(handleDesc2.GetGetter()->IsUndefined()); EXPECT_TRUE(handleDesc2.GetSetter()->IsUndefined()); objectOperator.SetValue(handleInternalAccessor.GetTaggedValue()); objectOperator.ToPropertyDescriptor(handleDesc3); EXPECT_EQ(handleDesc3.GetValue()->GetInt(), 12); } HWTEST_F_L0(ObjectOperatorTest, handleKey) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle handleString(factory->NewFromASCII("key")); JSHandle handleObject(factory->NewEmptyJSObject()); JSHandle handleSymbol(factory->NewJSSymbol()); JSHandle handleKey1(thread, JSTaggedValue(-1)); JSHandle handleKey2(thread, JSTaggedValue(-1.11)); JSHandle handleKey3(thread, handleString.GetTaggedValue()); JSHandle handleKey4(thread, handleSymbol.GetTaggedValue()); JSHandle handleKey5(thread, handleObject.GetTaggedValue()); JSHandle handleKey6(thread, JSTaggedValue(1.11)); ObjectOperator objectOperator1(thread, handleKey1); ObjectOperator objectOperator2(thread, handleKey2); ObjectOperator objectOperator3(thread, handleKey3); ObjectOperator objectOperator4(thread, handleKey4); ObjectOperator objectOperator5(thread, handleKey5); ObjectOperator objectOperator6(thread, handleKey6); JSHandle handleEcmaStrTo1(objectOperator1.GetKey()); EXPECT_STREQ("-1", EcmaStringAccessor(handleEcmaStrTo1).ToCString().c_str()); JSHandle handleEcmaStrTo2(objectOperator2.GetKey()); EXPECT_STREQ("-1.11", EcmaStringAccessor(handleEcmaStrTo2).ToCString().c_str()); EcmaString *str1 = EcmaString::Cast(objectOperator3.GetKey()->GetTaggedObject()); EXPECT_TRUE(EcmaStringAccessor(str1).IsInternString()); EXPECT_TRUE(objectOperator4.GetKey()->IsSymbol()); EcmaString *str2 = EcmaString::Cast(objectOperator5.GetKey()->GetTaggedObject()); EXPECT_TRUE(EcmaStringAccessor(str2).IsInternString()); JSHandle handleEcmaStrTo3(objectOperator6.GetKey()); EXPECT_STREQ("1.11", EcmaStringAccessor(handleEcmaStrTo3).ToCString().c_str()); } HWTEST_F_L0(ObjectOperatorTest, FastGetValue) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle handleNameString = factory->NewFromASCII("name"); JSHandle handleAccessorData = factory->NewAccessorData(); JSHandle handleReceiver(thread, JSTaggedValue(123)); JSHandle handleValue1(factory->NewPropertyBox(handleReceiver)); JSHandle handleValue2(handleAccessorData); JSHandle handleValue3(thread, JSTaggedValue(1)); ObjectOperator objectOperator1(thread, handleValue3); objectOperator1.SetIndex(1); objectOperator1.SetValue(handleValue1.GetTaggedValue()); EXPECT_EQ(objectOperator1.FastGetValue()->GetInt(), 123); // op for fast path ObjectOperator objectOperator2(thread, handleReceiver.GetTaggedValue(), handleNameString.GetTaggedValue()); objectOperator2.SetIndex(1); objectOperator2.SetValue(handleValue2.GetTaggedValue()); PropertyDescriptor handleDesc(thread); handleDesc.SetGetter(handleValue2); handleDesc.SetSetter(handleValue2); objectOperator2.SetAttr(PropertyAttributes(handleDesc)); EXPECT_TRUE(objectOperator2.FastGetValue()->IsUndefined()); JSHandle handleGetter = factory->NewJSFunction(env, reinterpret_cast(TestDefinedGetter)); handleAccessorData->SetGetter(thread, handleGetter.GetTaggedValue()); EXPECT_EQ(objectOperator2.FastGetValue()->GetInt(), 12); } HWTEST_F_L0(ObjectOperatorTest, ReLookupPropertyInReceiver_001) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleKey(thread, JSTaggedValue(2)); JSHandle handleName(factory->NewFromASCII("123")); JSHandle handleHolder(factory->NewFromASCII("12")); JSHandle handleReceiver(factory->NewJSString(handleName)); // Receiver is string ObjectOperator objectOperator1(thread, handleHolder, handleReceiver, handleKey); objectOperator1.ReLookupPropertyInReceiver(); EXPECT_EQ(objectOperator1.GetIndex(), 2U); EXPECT_TRUE(objectOperator1.GetValue().IsString()); EXPECT_EQ(objectOperator1.GetAttr().GetPropertyMetaData(), 2); EXPECT_TRUE(objectOperator1.IsFastMode()); // Receiver is not DictionaryMode JSHandle handleObject = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); for (int i = 0; i< 3; i++) { JSHandle newKey(thread, JSTaggedValue(i)); JSObject::SetProperty(thread, JSHandle(handleObject), newKey, newKey); } ObjectOperator objectOperator2(thread, handleHolder, JSHandle(handleObject), handleKey); objectOperator2.ReLookupPropertyInReceiver(); EXPECT_EQ(objectOperator2.GetIndex(), 2U); EXPECT_EQ(objectOperator2.GetValue().GetInt(), 2); EXPECT_EQ(objectOperator2.GetAttr().GetPropertyMetaData(), 7); EXPECT_TRUE(objectOperator2.IsFastMode()); // Receiver is DictionaryMode JSObject::DeleteProperty(thread, (handleObject), handleKey); ObjectOperator objectOperator3(thread, handleHolder, JSHandle(handleObject), handleKey); objectOperator3.ReLookupPropertyInReceiver(); // no key find EXPECT_EQ(objectOperator3.GetIndex(), ObjectOperator::NOT_FOUND_INDEX); EXPECT_TRUE(objectOperator3.GetValue().IsUndefined()); EXPECT_EQ(objectOperator3.GetAttr().GetPropertyMetaData(), 0); EXPECT_FALSE(objectOperator3.IsFastMode()); } HWTEST_F_L0(ObjectOperatorTest, ReLookupPropertyInReceiver_002) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle handleKey(factory->NewFromASCII("key")); JSHandle handleKey1(thread, JSTaggedValue(0)); JSHandle handleKey2(thread, JSTaggedValue(1)); JSHandle handleHolder(factory->NewFromASCII("12")); JSHandle globalObj = env->GetJSGlobalObject(); JSHandle handleReceiver(globalObj); PropertyAttributes handleAttr(4); // Receiver is JSGlobalObject(no properties) ObjectOperator objectOperator1(thread, handleHolder, JSHandle(handleReceiver), handleKey); objectOperator1.ReLookupPropertyInReceiver(); EXPECT_EQ(objectOperator1.GetIndex(), ObjectOperator::NOT_FOUND_INDEX); EXPECT_TRUE(objectOperator1.GetValue().IsUndefined()); EXPECT_EQ(objectOperator1.GetAttr().GetPropertyMetaData(), 0); EXPECT_FALSE(objectOperator1.IsFastMode()); // Receiver is JSGlobalObject(properties) JSMutableHandle receiverDict(thread, handleReceiver->GetProperties()); JSHandle handleDict = GlobalDictionary::Create(thread, 4); // numberofElements = 4 receiverDict.Update(handleDict.GetTaggedValue()); JSHandle cellHandle = factory->NewPropertyBox(handleKey); cellHandle->SetValue(thread, JSTaggedValue(4)); JSHandle handleProperties = GlobalDictionary::PutIfAbsent(thread, receiverDict, handleKey, JSHandle(cellHandle), handleAttr); handleReceiver->SetProperties(thread, handleProperties.GetTaggedValue()); int keyEntry = handleProperties->FindEntry(handleKey.GetTaggedValue()); ObjectOperator objectOperator2(thread, handleHolder, JSHandle(handleReceiver), handleKey); objectOperator2.ReLookupPropertyInReceiver(); EXPECT_EQ(objectOperator2.GetIndex(), static_cast(keyEntry)); EXPECT_TRUE(objectOperator2.GetValue().IsPropertyBox()); EXPECT_EQ(objectOperator2.GetAttr().GetPropertyMetaData(), handleAttr.GetPropertyMetaData()); EXPECT_TRUE(objectOperator2.IsFastMode()); } HWTEST_F_L0(ObjectOperatorTest, ReLookupPropertyInReceiver_003) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleHolder(factory->NewFromASCII("12")); JSHandle handleKey(factory->NewFromASCII("key")); JSHandle handleKey1(thread, JSTaggedValue(1)); JSHandle handleObject = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); JSObject::SetProperty(thread, JSHandle(handleObject), handleKey, handleKey1); JSObject::SetProperty(thread, JSHandle(handleObject), handleKey1, handleKey1); // Receiver is not DictionaryMode ObjectOperator objectOperator1(thread, handleHolder, JSHandle(handleObject), handleKey); objectOperator1.ReLookupPropertyInReceiver(); EXPECT_EQ(objectOperator1.GetIndex(), 0U); EXPECT_EQ(objectOperator1.GetValue().GetInt(), 1); EXPECT_EQ(objectOperator1.GetAttr().GetPropertyMetaData(), 7); // default attribute EXPECT_TRUE(objectOperator1.IsFastMode()); // Receiver is DictionaryMode JSObject::DeleteProperty(thread, (handleObject), handleKey); ObjectOperator objectOperator2(thread, handleHolder, JSHandle(handleObject), handleKey); objectOperator2.ReLookupPropertyInReceiver(); EXPECT_EQ(objectOperator2.GetIndex(), ObjectOperator::NOT_FOUND_INDEX); EXPECT_TRUE(objectOperator2.GetValue().IsUndefined()); EXPECT_EQ(objectOperator2.GetAttr().GetPropertyMetaData(), 0); // default attribute EXPECT_FALSE(objectOperator2.IsFastMode()); } HWTEST_F_L0(ObjectOperatorTest, LookupProperty) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle handleKey(thread, JSTaggedValue(1)); JSHandle handleValue(thread, JSTaggedValue(2)); JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleObject = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); JSObject::SetProperty(thread, JSHandle(handleObject), handleKey, handleValue); JSHandle handleObject1 = JSObject::ObjectCreate(thread, handleObject); ObjectOperator objectOperator(thread, handleObject1, handleKey); objectOperator.LookupProperty(); EXPECT_TRUE(objectOperator.IsOnPrototype()); EXPECT_EQ(objectOperator.GetIndex(), 1U); EXPECT_EQ(objectOperator.GetAttr().GetPropertyMetaData(), 7); EXPECT_EQ(objectOperator.GetValue().GetInt(), 2); EXPECT_TRUE(objectOperator.IsFastMode()); } HWTEST_F_L0(ObjectOperatorTest, GlobalLookupProperty) { JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle handleKey(thread, JSTaggedValue(1)); JSHandle handleValue(thread, JSTaggedValue(2)); JSHandle globalObj = env->GetJSGlobalObject(); JSHandle handleGlobalObject(globalObj); JSObject::SetProperty(thread, JSHandle(handleGlobalObject), handleKey, handleValue); JSHandle handleObject = JSObject::ObjectCreate(thread, handleGlobalObject); JSHandle handleGlobalObj(JSHandle::Cast(handleObject)); ObjectOperator objectOperator(thread, handleGlobalObj, handleKey); objectOperator.GlobalLookupProperty(); EXPECT_TRUE(objectOperator.IsOnPrototype()); EXPECT_EQ(objectOperator.GetIndex(), 1U); EXPECT_EQ(objectOperator.GetAttr().GetPropertyMetaData(), 7); EXPECT_EQ(objectOperator.GetValue().GetInt(), 2); EXPECT_TRUE(objectOperator.IsFastMode()); } HWTEST_F_L0(ObjectOperatorTest, ObjectOperator_Constructor1) { JSHandle handleKey(thread, JSTaggedValue(1)); OperatorType type = OperatorType::PROTOTYPE_CHAIN; // ObjectOperator(thread, JSHandle(), type) ObjectOperator objectOperator1(thread, handleKey, type); EXPECT_TRUE(objectOperator1.IsOnPrototype()); EXPECT_TRUE(objectOperator1.GetReceiver()->IsJSGlobalObject()); EXPECT_FALSE(objectOperator1.GetHolder()->IsJSGlobalObject()); type = OperatorType::OWN; ObjectOperator objectOperator2(thread, handleKey, type); EXPECT_FALSE(objectOperator2.IsOnPrototype()); EXPECT_TRUE(objectOperator2.GetReceiver()->IsJSGlobalObject()); EXPECT_TRUE(objectOperator2.GetHolder()->IsJSGlobalObject()); } HWTEST_F_L0(ObjectOperatorTest, ObjectOperator_Constructor2) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleHolder = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); JSHandle handleKey(factory->NewFromASCII("key")); OperatorType type = OperatorType::PROTOTYPE_CHAIN; // ObjectOperator(thread, JSHandle(), JSHandle(), type) ObjectOperator objectOperator1(thread, handleHolder, handleKey, type); EXPECT_TRUE(objectOperator1.IsOnPrototype()); type = OperatorType::OWN; ObjectOperator objectOperator2(thread, handleHolder, handleKey, type); EXPECT_FALSE(objectOperator2.IsOnPrototype()); } HWTEST_F_L0(ObjectOperatorTest, ObjectOperator_Constructor3) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle symbolFunc = env->GetSymbolFunction(); JSHandle handleHolder(thread, symbolFunc.GetTaggedValue()); JSHandle handleReceiver(thread, symbolFunc.GetTaggedValue()); JSHandle handleKey(factory->NewFromASCII("key")); OperatorType type = OperatorType::PROTOTYPE_CHAIN; // ObjectOperator(thread, JSHandle(), JSHandle(), type) ObjectOperator objectOperator1(thread, handleHolder, handleKey, type); EXPECT_TRUE(objectOperator1.IsOnPrototype()); type = OperatorType::OWN; ObjectOperator objectOperator2(thread, handleHolder, handleKey, type); EXPECT_FALSE(objectOperator2.IsOnPrototype()); } HWTEST_F_L0(ObjectOperatorTest, ObjectOperator_Constructor4) { JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle stringFunc = env->GetStringFunction(); JSHandle handleHolder(thread, stringFunc.GetTaggedValue()); JSHandle handleReceiver(thread, stringFunc.GetTaggedValue()); OperatorType type = OperatorType::PROTOTYPE_CHAIN; // ObjectOperator(thread, JSHandle(), JSHandle(), type) ObjectOperator objectOperator1(thread, handleHolder, handleReceiver, type); EXPECT_TRUE(objectOperator1.IsOnPrototype()); type = OperatorType::OWN; ObjectOperator objectOperator2(thread, handleHolder, handleReceiver, type); EXPECT_FALSE(objectOperator2.IsOnPrototype()); } HWTEST_F_L0(ObjectOperatorTest, ObjectOperator_Constructor5) { JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle boolFunc = env->GetBooleanFunction(); JSHandle handleHolder(thread, boolFunc.GetTaggedValue()); uint32_t index = 1; OperatorType type = OperatorType::PROTOTYPE_CHAIN; // ObjectOperator(thread, JSHandle(), index, type) ObjectOperator objectOperator1(thread, handleHolder, index, type); EXPECT_TRUE(objectOperator1.IsOnPrototype()); type = OperatorType::OWN; ObjectOperator objectOperator2(thread, handleHolder, index, type); EXPECT_FALSE(objectOperator2.IsOnPrototype()); } HWTEST_F_L0(ObjectOperatorTest, ObjectOperator_Constructor6) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle numFunc = env->GetNumberFunction(); JSHandle handleReceiver(thread, numFunc.GetTaggedValue()); JSHandle handleName(factory->NewFromASCII("name")); OperatorType type = OperatorType::PROTOTYPE_CHAIN; // ObjectOperator(thread, JSTaggedVale(), JSTaggedValue(), type) ObjectOperator objectOperator1(thread, handleReceiver.GetTaggedValue(), handleName.GetTaggedValue(), type); EXPECT_FALSE(objectOperator1.IsOnPrototype()); type = OperatorType::OWN; ObjectOperator objectOperator2(thread, handleReceiver.GetTaggedValue(), handleName.GetTaggedValue(), type); EXPECT_FALSE(objectOperator2.IsOnPrototype()); } HWTEST_F_L0(ObjectOperatorTest, ObjectOperator_Constructor7) { JSHandle handleReceiver(thread, JSTaggedValue(1)); JSHandle handleName(thread, JSTaggedValue(2)); PropertyAttributes handleAttr(4); // ObjectOperator(thread, JSTaggedVale(), JSTaggedValue(), PropertyAttributes()) ObjectOperator objectOperator(thread, handleReceiver.GetTaggedValue(), handleName.GetTaggedValue(), handleAttr); EXPECT_EQ(objectOperator.GetReceiver()->GetInt(), 1); EXPECT_EQ(objectOperator.GetAttr().GetPropertyMetaData(), 4); EXPECT_EQ(objectOperator.GetKey()->GetInt(), 2); } HWTEST_F_L0(ObjectOperatorTest, UpdateDateValue_001) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleKey(factory->NewFromASCII("key")); JSHandle handleKey2(thread, JSTaggedValue(2)); JSHandle handleValue(thread, JSTaggedValue(4)); JSHandle handleValue1(thread, JSTaggedValue(5)); ObjectOperator objectOperator1(thread, handleValue); objectOperator1.SetIndex(1); // object is not DictionaryMode JSHandle handleObject = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); for (int i = 0; i< 3; i++) { JSHandle newKey(thread, JSTaggedValue(i)); JSObject::SetProperty(thread, JSHandle(handleObject), newKey, newKey); } EXPECT_TRUE(objectOperator1.UpdateDataValue(handleObject, handleValue, false)); auto *resultElements =TaggedArray::Cast(handleObject->GetElements().GetTaggedObject()); EXPECT_EQ(resultElements->Get(objectOperator1.GetIndex()).GetInt(), 4); // object is DictionaryMode JSObject::DeleteProperty(thread, handleObject, handleKey2); EXPECT_TRUE(objectOperator1.UpdateDataValue(handleObject, handleValue1, false)); auto *resultDict = NumberDictionary::Cast(handleObject->GetElements().GetTaggedObject()); EXPECT_EQ(resultDict->GetValue(objectOperator1.GetIndex()).GetInt(), 5); // objcet value is InternalAccessor JSHandle handleAccessorData = factory->NewAccessorData(); JSHandle handleSetter = factory->NewJSNativePointer(reinterpret_cast(TestBoolSetter)); handleAccessorData->SetSetter(thread, handleSetter.GetTaggedValue()); JSHandle handleValue2(handleAccessorData); ObjectOperator objectOperator2(thread, handleKey); objectOperator2.SetValue(handleAccessorData.GetTaggedValue()); objectOperator2.SetIndex(1); EXPECT_TRUE(objectOperator2.UpdateDataValue(handleObject, handleValue, true)); } HWTEST_F_L0(ObjectOperatorTest, UpdateDataValue_002) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleKey(factory->NewFromASCII("key")); JSHandle handleValue(thread, JSTaggedValue(100)); // object is JSGlobalObject JSHandle globalObj = env->GetJSGlobalObject(); JSHandle handleGlobalObject(globalObj); JSMutableHandle holderDict(thread, handleGlobalObject->GetProperties()); JSHandle handleDict = GlobalDictionary::Create(thread, 4); // numberofElements = 4 holderDict.Update(handleDict.GetTaggedValue()); JSHandle cellHandle = factory->NewPropertyBox(handleKey); cellHandle->SetValue(thread, JSTaggedValue(4)); JSHandle handleProperties = GlobalDictionary::PutIfAbsent(thread, holderDict, handleKey, JSHandle(cellHandle), PropertyAttributes(4)); handleGlobalObject->SetProperties(thread, handleProperties.GetTaggedValue()); // Set Properties int keyEntry = handleProperties->FindEntry(handleKey.GetTaggedValue()); ObjectOperator objectOperator(thread, handleGlobalObject, handleKey); objectOperator.SetIndex(keyEntry); EXPECT_TRUE(objectOperator.UpdateDataValue(handleGlobalObject, handleValue, false)); auto *resultDict = GlobalDictionary::Cast(handleGlobalObject->GetProperties().GetTaggedObject()); PropertyBox *resultCell = resultDict->GetBox(objectOperator.GetIndex()); EXPECT_EQ(resultCell->GetValue().GetInt(), 100); } HWTEST_F_L0(ObjectOperatorTest, UpdateDataValue_003) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleValue(thread, JSTaggedValue(4)); JSHandle handleValue1(thread, JSTaggedValue(3)); JSHandle handleKey(factory->NewFromASCII("key")); JSHandle handleKey1 = factory->NewFromASCII("value"); JSHandle handleKey2(factory->NewFromASCII("value1")); ObjectOperator objectOperator(thread, handleKey); objectOperator.SetIndex(1); PropertyDescriptor handleDesc(thread); PropertyAttributes handleAttr(handleDesc); handleAttr.SetIsInlinedProps(true); objectOperator.SetAttr(PropertyAttributes(handleDesc)); // object is not DictionaryMode JSHandle handleObject = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); for (int i = 0; i < 10; i++) { JSHandle newValue(thread, JSTaggedValue(i)); JSHandle newString = factory->ConcatFromString(handleKey1, JSTaggedValue::ToString(thread, newValue)); JSHandle newKey(thread, newString.GetTaggedValue()); JSObject::SetProperty(thread, JSHandle(handleObject), newKey, newValue); } EXPECT_TRUE(objectOperator.UpdateDataValue(handleObject, handleValue1, false)); TaggedArray *resultElements1 = TaggedArray::Cast(handleObject->GetProperties().GetTaggedObject()); EXPECT_EQ(resultElements1->Get(objectOperator.GetIndex()).GetInt(), 3); // object is DictionaryMode JSObject::DeleteProperty(thread, handleObject, handleKey2); EXPECT_TRUE(objectOperator.UpdateDataValue(handleObject, handleValue, false)); TaggedArray *resultElements2 = TaggedArray::Cast(handleObject->GetProperties().GetTaggedObject()); auto *resultDict = NumberDictionary::Cast(resultElements2); EXPECT_EQ(resultDict->GetValue(objectOperator.GetIndex()).GetInt(), 4); } HWTEST_F_L0(ObjectOperatorTest, WriteDataProperty_001) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleKey(thread, JSTaggedValue(2)); JSHandle handleValue(thread, JSTaggedValue(4)); uint32_t index = 1; PropertyDescriptor handleDesc(thread); ObjectOperator objectOperator(thread, handleKey); PropertyAttributes handleAttr(4); handleDesc.SetConfigurable(true); // Desc Set Configurable objectOperator.SetAttr(PropertyAttributes(3)); objectOperator.SetIndex(index); // object class is not DictionaryElement and object is Element JSHandle handleObject = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); for (int i = 0; i< 3; i++) { JSHandle newKey(thread, JSTaggedValue(i)); JSObject::SetProperty(thread, JSHandle(handleObject), newKey, newKey); } EXPECT_TRUE(objectOperator.WriteDataProperty(handleObject, handleDesc)); auto resultDict = NumberDictionary::Cast(handleObject->GetElements().GetTaggedObject()); int resultEntry = resultDict->FindEntry(JSTaggedValue(index)); int resultAttrValue = resultDict->GetAttributes(resultEntry).GetPropertyMetaData(); EXPECT_EQ(objectOperator.GetAttr().GetPropertyMetaData(), resultAttrValue); EXPECT_EQ(objectOperator.GetAttr().GetDictionaryOrder(), 1U); EXPECT_TRUE(objectOperator.GetAttr().IsConfigurable()); EXPECT_EQ(objectOperator.GetIndex(), static_cast(resultEntry)); EXPECT_FALSE(objectOperator.IsFastMode()); EXPECT_TRUE(objectOperator.IsTransition()); } HWTEST_F_L0(ObjectOperatorTest, WriteDataProperty_002) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle handleKey(factory->NewFromASCII("key")); JSHandle handleValue1(thread, JSTaggedValue(1)); JSHandle handleValue2(thread, JSTaggedValue(2)); JSHandle cellHandle1 = factory->NewPropertyBox(handleValue1); JSHandle cellHandle2 = factory->NewPropertyBox(handleValue2); PropertyDescriptor handleDesc(thread); handleDesc.SetConfigurable(true); PropertyAttributes handleAttr(2); handleAttr.SetConfigurable(true); // object is JSGlobalObject and not Element JSHandle globalObj = env->GetJSGlobalObject(); JSHandle handleGlobalObject(globalObj); ObjectOperator objectOperator(thread, handleGlobalObject, handleKey); JSMutableHandle globalDict(thread, handleGlobalObject->GetProperties()); JSHandle handleDict = GlobalDictionary::Create(thread, 4); globalDict.Update(handleDict.GetTaggedValue()); JSHandle handleProperties = GlobalDictionary::PutIfAbsent( thread, globalDict, handleKey, JSHandle(cellHandle1), PropertyAttributes(4)); handleProperties->SetAttributes(thread, handleAttr.GetDictionaryOrder(), handleAttr); handleProperties->SetValue(thread, handleAttr.GetDictionaryOrder(), cellHandle2.GetTaggedValue()); handleGlobalObject->SetProperties(thread, handleProperties.GetTaggedValue()); objectOperator.SetIndex(handleProperties->FindEntry(handleKey.GetTaggedValue())); EXPECT_TRUE(objectOperator.WriteDataProperty(handleGlobalObject, handleDesc)); auto resultDict = GlobalDictionary::Cast(handleGlobalObject->GetProperties().GetTaggedObject()); EXPECT_EQ(resultDict->GetAttributes(objectOperator.GetIndex()).GetPropertyMetaData(), 4); EXPECT_TRUE(resultDict->GetAttributes(objectOperator.GetIndex()).IsConfigurable()); int resultEntry = resultDict->GetAttributes(objectOperator.GetIndex()).GetDictionaryOrder(); EXPECT_EQ(resultDict->GetAttributes(resultEntry).GetBoxType(), PropertyBoxType::MUTABLE); EXPECT_EQ(resultDict->GetValue(resultEntry).GetInt(), 1); } HWTEST_F_L0(ObjectOperatorTest, WriteDataProperty_003) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleKey(factory->NewFromASCII("key")); JSHandle handleValue(thread, JSTaggedValue(2)); PropertyDescriptor handleDesc(thread, handleValue); handleDesc.SetSetter(handleValue); // Desc is AccessorDescriptor handleDesc.SetGetter(handleValue); // object is not DictionaryMode and not Element JSHandle handleObject = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); for (int i = 0; i< 3; i++) { JSHandle newKey(thread, JSTaggedValue(i)); JSObject::SetProperty(thread, JSHandle(handleObject), newKey, newKey); } JSObject::SetProperty(thread, JSHandle(handleObject), handleKey, handleValue); ObjectOperator objectOperator1(thread, handleKey); objectOperator1.SetAttr(PropertyAttributes(1)); EXPECT_TRUE(objectOperator1.WriteDataProperty(handleObject, handleDesc)); auto resultDict = NameDictionary::Cast(handleObject->GetProperties().GetTaggedObject()); int resultEntry = resultDict->FindEntry(handleKey.GetTaggedValue()); EXPECT_TRUE(resultDict->GetValue(resultEntry).IsAccessorData()); EXPECT_EQ(resultDict->GetAttributes(resultEntry).GetValue(), objectOperator1.GetAttr().GetValue()); // object is DictionaryMode and not Element JSObject::DeleteProperty(thread, (handleObject), handleKey); JSHandle handleSetter(factory->NewJSNativePointer(reinterpret_cast(TestDefinedSetter))); JSHandle handleAccessorData = factory->NewAccessorData(); handleDesc.SetSetter(handleSetter); ObjectOperator objectOperator2(thread, handleKey); objectOperator2.SetAttr(PropertyAttributes(handleDesc)); objectOperator2.SetValue(handleAccessorData.GetTaggedValue()); EXPECT_TRUE(objectOperator2.WriteDataProperty(handleObject, handleDesc)); JSHandle resultAccessorData(thread, objectOperator2.GetValue()); EXPECT_EQ(resultAccessorData->GetGetter().GetInt(), 2); EXPECT_TRUE(resultAccessorData->GetSetter().IsJSNativePointer()); } HWTEST_F_L0(ObjectOperatorTest, Property_Add_001) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleKey(thread, JSTaggedValue(2)); JSHandle handleValue(thread, JSTaggedValue(3)); int32_t elementIndex = 2; PropertyAttributes handleAttr(elementIndex); // object is JSArray and Element JSHandle handleArr = factory->NewJSArray(); handleArr->SetArrayLength(thread, (elementIndex - 1)); JSHandle handleArrObj(thread, handleArr.GetTaggedValue()); ObjectOperator objectOperator1(thread, handleArrObj, elementIndex); EXPECT_TRUE(objectOperator1.AddProperty(JSHandle(handleArrObj), handleValue, handleAttr)); EXPECT_EQ(handleArr->GetArrayLength(), 3U); // (elementIndex - 1) + 2 // object is DictionaryElement and Element JSHandle handleObject = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); for (int i = 0; i< 3; i++) { JSHandle newKey(thread, JSTaggedValue(i)); JSObject::SetProperty(thread, JSHandle(handleObject), newKey, newKey); } JSObject::DeleteProperty(thread, (handleObject), handleKey); // Delete key2 ObjectOperator objectOperator2(thread, JSHandle(handleObject), elementIndex); EXPECT_TRUE(objectOperator2.AddProperty(handleObject, handleValue, handleAttr)); auto resultDict = NumberDictionary::Cast(handleObject->GetElements().GetTaggedObject()); int resultEntry = resultDict->FindEntry(JSTaggedValue(static_cast(elementIndex))); EXPECT_EQ(resultDict->GetKey(resultEntry).GetInt(), elementIndex); EXPECT_EQ(resultDict->GetValue(resultEntry).GetInt(), 3); } HWTEST_F_L0(ObjectOperatorTest, Property_Add_002) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleString(factory->NewFromASCII("key")); JSHandle handleValue(thread, JSTaggedValue(3)); int32_t elementIndex = 4; PropertyAttributes handleDefaultAttr(elementIndex); PropertyAttributes handleAttr(elementIndex); handleDefaultAttr.SetDefaultAttributes(); // object is not DictionaryMode and DefaultAttr JSHandle handleObject1 = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); for (int i = 0; i< 3; i++) { JSHandle newKey(thread, JSTaggedValue(i)); JSObject::SetProperty(thread, JSHandle(handleObject1), newKey, newKey); } ObjectOperator objectOperator(thread, JSHandle(handleObject1), elementIndex); EXPECT_TRUE(objectOperator.AddProperty(handleObject1, handleValue, handleDefaultAttr)); TaggedArray *resultArray = TaggedArray::Cast(handleObject1->GetElements().GetTaggedObject()); EXPECT_EQ(resultArray->Get(elementIndex).GetInt(), 3); EXPECT_EQ(resultArray->GetLength(), 7U); EXPECT_EQ(handleObject1->GetJSHClass()->GetElementRepresentation(), Representation::INT); // object is not DictionaryMode and not DefaultAttr JSHandle handleObject2 = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); for (int i = 0; i< 4; i++) { JSHandle newKey(thread, JSTaggedValue(i)); JSObject::SetProperty(thread, JSHandle(handleObject2), newKey, newKey); } EXPECT_TRUE(objectOperator.AddProperty(handleObject2, handleString, handleAttr)); auto resultDict = NumberDictionary::Cast(handleObject2->GetElements().GetTaggedObject()); int resultEntry = resultDict->FindEntry(JSTaggedValue(static_cast(elementIndex))); EXPECT_EQ(resultDict->GetKey(resultEntry).GetInt(), elementIndex); EXPECT_TRUE(resultDict->GetValue(resultEntry).IsString()); } HWTEST_F_L0(ObjectOperatorTest, Property_Add_003) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleKey(factory->NewFromASCII("key")); JSHandle handleValue(thread, JSTaggedValue(4)); int32_t handleAttrOffset = 4; PropertyAttributes handleAttr(handleAttrOffset); handleAttr.SetOffset(handleAttrOffset); // object is JSGlobalObject and not Element JSHandle globalObj = env->GetJSGlobalObject(); JSHandle handleGlobalObject(globalObj); // no properties ObjectOperator objectOperator(thread, handleGlobalObject, handleKey); EXPECT_TRUE(objectOperator.AddProperty(handleGlobalObject, handleValue, handleAttr)); EXPECT_EQ(objectOperator.GetAttr().GetBoxType(), PropertyBoxType::CONSTANT); EXPECT_EQ(objectOperator.FastGetValue()->GetInt(), 4); EXPECT_EQ(objectOperator.GetIndex(), 0U); EXPECT_TRUE(objectOperator.IsFastMode()); EXPECT_FALSE(objectOperator.IsTransition()); } HWTEST_F_L0(ObjectOperatorTest, Property_Add_004) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleKey(factory->NewFromASCII("key")); JSHandle handleKey1(thread, JSTaggedValue(1)); JSHandle handleValue(thread, JSTaggedValue(4)); JSHandle handledUndefinedVal(thread, JSTaggedValue::Undefined()); int32_t handleAttrOffset = 4; PropertyAttributes handleAttr(handleAttrOffset); handleAttr.SetOffset(handleAttrOffset); // object is not DictionaryMode and not Element JSHandle handleObject = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); for (int i = 0; i< 4; i++) { JSHandle newKey(thread, JSTaggedValue(i)); JSObject::SetProperty(thread, JSHandle(handleObject), newKey, newKey); } EXPECT_EQ(handleObject->GetJSHClass()->GetInlinedProperties(), 4U); ObjectOperator objectOperator(thread, handleObject, handleKey); EXPECT_TRUE(objectOperator.AddProperty(handleObject, handleValue, handleAttr)); EXPECT_EQ(objectOperator.GetAttr().GetPropertyMetaData(), 4); EXPECT_EQ(objectOperator.GetValue().GetInt(), 4); EXPECT_EQ(objectOperator.GetIndex(), 0U); // 0 = 4 - 4 EXPECT_TRUE(objectOperator.IsFastMode()); EXPECT_TRUE(objectOperator.IsTransition()); // object is DictionaryMode and not Element JSObject::DeleteProperty(thread, (handleObject), handleKey); EXPECT_TRUE(objectOperator.AddProperty(handleObject, handledUndefinedVal, handleAttr)); EXPECT_EQ(objectOperator.GetAttr().GetPropertyMetaData(), 4); EXPECT_TRUE(objectOperator.GetValue().IsUndefined()); EXPECT_EQ(objectOperator.GetIndex(), 0U); EXPECT_FALSE(objectOperator.IsFastMode()); EXPECT_FALSE(objectOperator.IsTransition()); } HWTEST_F_L0(ObjectOperatorTest, Property_DeleteElement1) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle handleKey0(thread, JSTaggedValue(0)); JSHandle handleKey1(thread, JSTaggedValue(1)); JSHandle handleValue(thread, JSTaggedValue(2)); uint32_t index = 1; // key value PropertyAttributes handleAttr(index); // object is not DictionaryMode JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleObject1 = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); JSObject::SetProperty(thread, JSHandle(handleObject1), handleKey0, handleKey0); JSObject::SetProperty(thread, JSHandle(handleObject1), handleKey1, handleKey1); TaggedArray *handleElements = TaggedArray::Cast(handleObject1->GetElements().GetTaggedObject()); EXPECT_EQ(handleElements->Get(index).GetInt(), 1); ObjectOperator objectOperator1(thread, JSHandle(handleObject1), index); objectOperator1.DeletePropertyInHolder(); TaggedArray *resultElements = TaggedArray::Cast(handleObject1->GetElements().GetTaggedObject()); EXPECT_EQ(resultElements->Get(index).GetInt(), 0); auto resultDict1 = NumberDictionary::Cast(handleObject1->GetElements().GetTaggedObject()); EXPECT_TRUE(resultDict1->IsDictionaryMode()); EXPECT_TRUE(JSObject::GetProperty(thread, handleObject1, handleKey1).GetValue()->IsUndefined()); // object is DictionaryMode JSHandle handleObject2 = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); JSObject::SetProperty(thread, JSHandle(handleObject2), handleKey0, handleKey0); JSObject::SetProperty(thread, JSHandle(handleObject2), handleKey1, handleKey1); JSObject::DeleteProperty(thread, (handleObject2), handleKey1); ObjectOperator objectOperator2(thread, JSHandle(handleObject2), index - 1); objectOperator2.DeletePropertyInHolder(); auto resultDict2 = NumberDictionary::Cast(handleObject2->GetElements().GetTaggedObject()); EXPECT_TRUE(resultDict2->GetKey(index - 1U).IsUndefined()); EXPECT_TRUE(resultDict2->GetValue(index - 1U).IsUndefined()); EXPECT_TRUE(JSObject::GetProperty(thread, handleObject2, handleKey0).GetValue()->IsUndefined()); EXPECT_TRUE(JSObject::GetProperty(thread, handleObject2, handleKey1).GetValue()->IsUndefined()); } HWTEST_F_L0(ObjectOperatorTest, Property_DeleteElement2) { JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle globalObj = env->GetJSGlobalObject(); JSHandle handleGlobalObject(globalObj); JSHandle handleDict = NumberDictionary::Create(thread, 4); handleGlobalObject->SetElements(thread, handleDict.GetTaggedValue()); handleGlobalObject->GetClass()->SetIsDictionaryElement(true); for (int i = 0; i < 10000; i++) { JSHandle handleKey(thread, JSTaggedValue(i)); JSHandle handleValue(thread, JSTaggedValue(i)); JSObject::SetProperty(thread, globalObj, handleKey, handleValue); JSObject::DeleteProperty(thread, handleGlobalObject, handleKey); } auto resultDict = NumberDictionary::Cast(handleGlobalObject->GetElements().GetTaggedObject()); EXPECT_EQ(resultDict->Size(), 4); } HWTEST_F_L0(ObjectOperatorTest, Property_DeleteProperty) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleKey(factory->NewFromASCII("key")); JSHandle handleKey0(thread, JSTaggedValue(0)); JSHandle handleKey1(thread, JSTaggedValue(1)); JSHandle handleValue(thread, JSTaggedValue(33)); // object is JSGlobalObject JSHandle globalObj = env->GetJSGlobalObject(); JSHandle handleGlobalObject(globalObj); JSMutableHandle globalDict(thread, handleGlobalObject->GetProperties()); JSHandle handleDict = GlobalDictionary::Create(thread, 4); globalDict.Update(handleDict.GetTaggedValue()); JSHandle cellHandle = factory->NewPropertyBox(handleKey); cellHandle->SetValue(thread, handleValue.GetTaggedValue()); JSHandle handleProperties = GlobalDictionary::PutIfAbsent( thread, globalDict, handleKey, JSHandle(cellHandle), PropertyAttributes(12)); handleGlobalObject->SetProperties(thread, handleProperties.GetTaggedValue()); ObjectOperator objectOperator1(thread, handleGlobalObject, handleKey); objectOperator1.DeletePropertyInHolder(); auto resultDict = GlobalDictionary::Cast(handleGlobalObject->GetProperties().GetTaggedObject()); // key not found EXPECT_EQ(resultDict->FindEntry(handleKey.GetTaggedValue()), -1); EXPECT_EQ(resultDict->GetAttributes(objectOperator1.GetIndex()).GetValue(), 0U); // object is not DictionaryMode JSHandle handleObject = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); JSObject::SetProperty(thread, JSHandle(handleObject), handleKey, handleKey1); JSObject::SetProperty(thread, JSHandle(handleObject), handleKey0, handleKey0); JSObject::SetProperty(thread, JSHandle(handleObject), handleKey1, handleKey1); ObjectOperator objectOperator2(thread, handleObject, handleKey); objectOperator2.DeletePropertyInHolder(); auto resultDict1 = NameDictionary::Cast(handleObject->GetProperties().GetTaggedObject()); // key not found EXPECT_EQ(resultDict1->FindEntry(handleKey.GetTaggedValue()), -1); } HWTEST_F_L0(ObjectOperatorTest, Define_SetterAndGettetr) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle handleAccessorData = factory->NewAccessorData(); JSHandle handleValue(thread, JSTaggedValue(0)); JSHandle handleValue1(thread, JSTaggedValue(2)); JSHandle handleKey(factory->NewFromASCII("value")); JSHandle handleKey1(factory->NewFromASCII("key")); JSHandle handleKey2(factory->NewFromASCII("value1")); // object is not DictionaryMode JSHandle objFunc(thread, JSObjectTestCreate(thread)); JSHandle handleObject = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); for (int i = 0; i < 10; i++) { JSHandle newValue(thread, JSTaggedValue(i)); JSHandle newString = factory->ConcatFromString(handleKey, JSTaggedValue::ToString(thread, newValue)); JSHandle newKey(thread, newString.GetTaggedValue()); JSObject::SetProperty(thread, JSHandle(handleObject), newKey, newValue); } // object is not Element ObjectOperator objectOperator(thread, handleObject, handleKey1); objectOperator.SetIndex(1); objectOperator.SetValue(handleAccessorData.GetTaggedValue()); PropertyDescriptor handleDesc(thread, handleValue); handleDesc.SetSetter(handleValue); handleDesc.SetGetter(handleValue); objectOperator.SetAttr(PropertyAttributes(handleDesc)); objectOperator.DefineSetter(handleValue1); objectOperator.DefineGetter(handleValue); JSHandle resultObj1(objectOperator.GetReceiver()); TaggedArray *properties = TaggedArray::Cast(resultObj1->GetProperties().GetTaggedObject()); JSHandle resultAccessorData1(thread, properties->Get(objectOperator.GetIndex())); EXPECT_EQ(resultAccessorData1->GetGetter().GetInt(), 0); EXPECT_EQ(resultAccessorData1->GetSetter().GetInt(), 2); // object is DictionaryMode JSObject::DeleteProperty(thread, handleObject, handleKey2); objectOperator.DefineSetter(handleValue); objectOperator.DefineGetter(handleValue1); JSHandle resultObj2(objectOperator.GetReceiver()); auto resultDict = NameDictionary::Cast(resultObj2->GetProperties().GetTaggedObject()); JSHandle resultAccessorData2(thread, resultDict->GetValue(objectOperator.GetIndex())); EXPECT_EQ(resultAccessorData2->GetGetter().GetInt(), 2); EXPECT_EQ(resultAccessorData2->GetSetter().GetInt(), 0); } } // namespace panda::test