• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/object_operator.h"
17 #include "ecmascript/ecma_string.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/global_dictionary-inl.h"
20 #include "ecmascript/js_array.h"
21 #include "ecmascript/js_object-inl.h"
22 #include "ecmascript/property_attributes.h"
23 #include "ecmascript/tagged_array.h"
24 #include "ecmascript/tagged_dictionary.h"
25 #include "ecmascript/tests/test_helper.h"
26 
27 using namespace panda::ecmascript;
28 
29 namespace panda::test {
30 class ObjectOperatorTest : public BaseTestWithScope<false> {
31 };
32 
TestDefinedSetter(EcmaRuntimeCallInfo * argv)33 JSTaggedValue TestDefinedSetter([[maybe_unused]] EcmaRuntimeCallInfo *argv)
34 {
35     // 12 : test case
36     return JSTaggedValue(12);
37 }
38 
JSObjectTestCreate(JSThread * thread)39 static JSFunction *JSObjectTestCreate(JSThread *thread)
40 {
41     JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
42     return globalEnv->GetObjectFunction().GetObject<JSFunction>();
43 }
44 
TestBoolSetter(JSThread * thread,const JSHandle<JSObject> & jsObject,const JSHandle<JSTaggedValue> & value,bool success)45 bool TestBoolSetter([[maybe_unused]] JSThread *thread,
46                     [[maybe_unused]] const JSHandle<JSObject> &jsObject,
47                     [[maybe_unused]] const JSHandle<JSTaggedValue> &value,
48                     [[maybe_unused]] bool success)
49 {
50     return true;
51 }
52 
HWTEST_F_L0(ObjectOperatorTest,ObjectOperator_Constructor1)53 HWTEST_F_L0(ObjectOperatorTest, ObjectOperator_Constructor1)
54 {
55     JSHandle<JSTaggedValue> handleKey(thread, JSTaggedValue(1));
56     OperatorType type = OperatorType::PROTOTYPE_CHAIN;
57     // ObjectOperator(thread, JSHandle<JSTaggedVale>(), type)
58     ObjectOperator objectOperator1(thread, handleKey, type);
59     EXPECT_TRUE(objectOperator1.IsOnPrototype());
60     EXPECT_TRUE(objectOperator1.GetReceiver()->IsJSGlobalObject());
61     EXPECT_FALSE(objectOperator1.GetHolder()->IsJSGlobalObject());
62     type = OperatorType::OWN;
63     ObjectOperator objectOperator2(thread, handleKey, type);
64     EXPECT_FALSE(objectOperator2.IsOnPrototype());
65     EXPECT_TRUE(objectOperator2.GetReceiver()->IsJSGlobalObject());
66     EXPECT_TRUE(objectOperator2.GetHolder()->IsJSGlobalObject());
67 }
68 
HWTEST_F_L0(ObjectOperatorTest,ObjectOperator_Constructor2)69 HWTEST_F_L0(ObjectOperatorTest, ObjectOperator_Constructor2)
70 {
71     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
72     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
73     JSHandle<JSObject> handleHolder = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
74     JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
75     OperatorType type = OperatorType::PROTOTYPE_CHAIN;
76     // ObjectOperator(thread, JSHandle<JSObject>(), JSHandle<JSTaggedVale>(), type)
77     ObjectOperator objectOperator1(thread, handleHolder, handleKey, type);
78     EXPECT_TRUE(objectOperator1.IsOnPrototype());
79     type = OperatorType::OWN;
80     ObjectOperator objectOperator2(thread, handleHolder, handleKey, type);
81     EXPECT_FALSE(objectOperator2.IsOnPrototype());
82 }
83 
HWTEST_F_L0(ObjectOperatorTest,ObjectOperator_Constructor3)84 HWTEST_F_L0(ObjectOperatorTest, ObjectOperator_Constructor3)
85 {
86     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
87     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
88     JSHandle<JSTaggedValue> symbolFunc = env->GetSymbolFunction();
89     JSHandle<JSTaggedValue> handleHolder(thread, symbolFunc.GetTaggedValue());
90     JSHandle<JSTaggedValue> handleReceiver(thread, symbolFunc.GetTaggedValue());
91     JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
92     OperatorType type = OperatorType::PROTOTYPE_CHAIN;
93     // ObjectOperator(thread, JSHandle<JSTaggedVale>(), JSHandle<JSTaggedVale>(), type)
94     ObjectOperator objectOperator1(thread, handleHolder, handleKey, type);
95     EXPECT_TRUE(objectOperator1.IsOnPrototype());
96     type = OperatorType::OWN;
97     ObjectOperator objectOperator2(thread, handleHolder, handleKey, type);
98     EXPECT_FALSE(objectOperator2.IsOnPrototype());
99 }
100 
HWTEST_F_L0(ObjectOperatorTest,ObjectOperator_Constructor4)101 HWTEST_F_L0(ObjectOperatorTest, ObjectOperator_Constructor4)
102 {
103     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
104     JSHandle<JSTaggedValue> stringFunc = env->GetStringFunction();
105     JSHandle<JSTaggedValue> handleHolder(thread, stringFunc.GetTaggedValue());
106     JSHandle<JSTaggedValue> handleReceiver(thread, stringFunc.GetTaggedValue());
107     OperatorType type = OperatorType::PROTOTYPE_CHAIN;
108     // ObjectOperator(thread, JSHandle<JSTaggedVale>(), JSHandle<JSTaggedVale>(), type)
109     ObjectOperator objectOperator1(thread, handleHolder, handleReceiver, type);
110     EXPECT_TRUE(objectOperator1.IsOnPrototype());
111     type = OperatorType::OWN;
112     ObjectOperator objectOperator2(thread, handleHolder, handleReceiver, type);
113     EXPECT_FALSE(objectOperator2.IsOnPrototype());
114 }
115 
HWTEST_F_L0(ObjectOperatorTest,ObjectOperator_Constructor5)116 HWTEST_F_L0(ObjectOperatorTest, ObjectOperator_Constructor5)
117 {
118     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
119     JSHandle<JSTaggedValue> boolFunc = env->GetBooleanFunction();
120     JSHandle<JSTaggedValue> handleHolder(thread, boolFunc.GetTaggedValue());
121     uint32_t index = 1;
122     OperatorType type = OperatorType::PROTOTYPE_CHAIN;
123     // ObjectOperator(thread, JSHandle<JSTaggedVale>(), index, type)
124     ObjectOperator objectOperator1(thread, handleHolder, index, type);
125     EXPECT_TRUE(objectOperator1.IsOnPrototype());
126     type = OperatorType::OWN;
127     ObjectOperator objectOperator2(thread, handleHolder, index, type);
128     EXPECT_FALSE(objectOperator2.IsOnPrototype());
129 }
130 
HWTEST_F_L0(ObjectOperatorTest,ObjectOperator_Constructor6)131 HWTEST_F_L0(ObjectOperatorTest, ObjectOperator_Constructor6)
132 {
133     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
134     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
135     JSHandle<JSTaggedValue> numFunc = env->GetNumberFunction();
136     JSHandle<JSTaggedValue> handleReceiver(thread, numFunc.GetTaggedValue());
137     JSHandle<JSTaggedValue> handleName(factory->NewFromASCII("name"));
138     OperatorType type = OperatorType::PROTOTYPE_CHAIN;
139     // ObjectOperator(thread, JSTaggedVale(), JSTaggedValue(), type)
140     ObjectOperator objectOperator1(thread, handleReceiver.GetTaggedValue(), handleName.GetTaggedValue(), type);
141     EXPECT_FALSE(objectOperator1.IsOnPrototype());
142     type = OperatorType::OWN;
143     ObjectOperator objectOperator2(thread, handleReceiver.GetTaggedValue(), handleName.GetTaggedValue(), type);
144     EXPECT_FALSE(objectOperator2.IsOnPrototype());
145 }
146 
HWTEST_F_L0(ObjectOperatorTest,ObjectOperator_Constructor7)147 HWTEST_F_L0(ObjectOperatorTest, ObjectOperator_Constructor7)
148 {
149     JSHandle<JSTaggedValue> handleReceiver(thread, JSTaggedValue(1));
150     JSHandle<JSTaggedValue> handleName(thread, JSTaggedValue(2));
151     PropertyAttributes handleAttr(4);
152     // ObjectOperator(thread, JSTaggedVale(), JSTaggedValue(), PropertyAttributes())
153     ObjectOperator objectOperator(thread, handleReceiver.GetTaggedValue(), handleName.GetTaggedValue(), handleAttr);
154     EXPECT_EQ(objectOperator.GetReceiver()->GetInt(), 1);
155     EXPECT_EQ(objectOperator.GetAttr().GetPropertyMetaData(), 4);
156     EXPECT_EQ(objectOperator.GetKey()->GetInt(), 2);
157 }
158 
HWTEST_F_L0(ObjectOperatorTest,UpdateDateValue_001)159 HWTEST_F_L0(ObjectOperatorTest, UpdateDateValue_001)
160 {
161     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
162     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
163     JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
164     JSHandle<JSTaggedValue> handleKey2(thread, JSTaggedValue(2));
165     JSHandle<JSTaggedValue> handleKey3(thread, JSTaggedValue(102400));
166     JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(4));
167     JSHandle<JSTaggedValue> handleValue1(thread, JSTaggedValue(5));
168     ObjectOperator objectOperator1(thread, handleValue);
169     objectOperator1.SetIndex(1);
170 
171     // object is not DictionaryMode
172     JSHandle<JSObject> handleObject = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
173     for (int i = 0; i < 3; i++) {
174         JSHandle<JSTaggedValue> newKey(thread, JSTaggedValue(i));
175         JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handleObject), newKey, newKey);
176     }
177     EXPECT_TRUE(objectOperator1.UpdateDataValue(handleObject, handleValue, false));
178     auto *resultElements =TaggedArray::Cast(handleObject->GetElements().GetTaggedObject());
179     EXPECT_EQ(resultElements->Get(objectOperator1.GetIndex()).GetInt(), 4);
180 
181     // object is DictionaryMode
182     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handleObject), handleKey3, handleKey);
183     JSObject::DeleteProperty(thread, handleObject, handleKey3);
184     EXPECT_TRUE(objectOperator1.UpdateDataValue(handleObject, handleValue1, false));
185     auto *resultDict = NumberDictionary::Cast(handleObject->GetElements().GetTaggedObject());
186     EXPECT_EQ(resultDict->GetValue(objectOperator1.GetIndex()).GetInt(), 5);
187 
188     // object value is InternalAccessor
189     JSHandle<AccessorData> handleAccessorData = factory->NewInternalAccessor(
190         reinterpret_cast<void*>(TestBoolSetter), nullptr);
191     JSHandle<JSTaggedValue> handleValue2(handleAccessorData);
192     ObjectOperator objectOperator2(thread, handleKey);
193     objectOperator2.SetValue(handleAccessorData.GetTaggedValue());
194     objectOperator2.SetIndex(1);
195     EXPECT_TRUE(objectOperator2.UpdateDataValue(handleObject, handleValue, true));
196 }
197 
HWTEST_F_L0(ObjectOperatorTest,UpdateDataValue_002)198 HWTEST_F_L0(ObjectOperatorTest, UpdateDataValue_002)
199 {
200     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
201     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
202     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
203     JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
204     JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(100));
205     // object is JSGlobalObject
206     JSHandle<JSTaggedValue> globalObj = env->GetJSGlobalObject();
207     JSHandle<JSObject> handleGlobalObject(globalObj);
208 
209     JSMutableHandle<GlobalDictionary> holderDict(thread, handleGlobalObject->GetProperties());
210     JSHandle<GlobalDictionary> handleDict = GlobalDictionary::Create(thread, 4); // numberofElements = 4
211     holderDict.Update(handleDict.GetTaggedValue());
212     JSHandle<PropertyBox> cellHandle = factory->NewPropertyBox(handleKey);
213     cellHandle->SetValue(thread, JSTaggedValue(4));
214     JSHandle<GlobalDictionary> handleProperties =
215         GlobalDictionary::PutIfAbsent(thread, holderDict, handleKey,
216                                       JSHandle<JSTaggedValue>(cellHandle), PropertyAttributes(4));
217     handleGlobalObject->SetProperties(thread, handleProperties.GetTaggedValue()); // Set Properties
218     int keyEntry = handleProperties->FindEntry(handleKey.GetTaggedValue());
219 
220     ObjectOperator objectOperator(thread, handleGlobalObject, handleKey);
221     objectOperator.SetIndex(keyEntry);
222     EXPECT_TRUE(objectOperator.UpdateDataValue(handleGlobalObject, handleValue, false));
223     auto *resultDict = GlobalDictionary::Cast(handleGlobalObject->GetProperties().GetTaggedObject());
224     PropertyBox *resultCell = resultDict->GetBox(objectOperator.GetIndex());
225     EXPECT_EQ(resultCell->GetValue().GetInt(), 100);
226 }
227 
HWTEST_F_L0(ObjectOperatorTest,UpdateDataValue_003)228 HWTEST_F_L0(ObjectOperatorTest, UpdateDataValue_003)
229 {
230     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
231     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
232     JSHandle<JSTaggedValue> handleValue(thread, JSTaggedValue(4));
233     JSHandle<JSTaggedValue> handleValue1(thread, JSTaggedValue(3));
234     JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
235     JSHandle<EcmaString> handleKey1 = factory->NewFromASCII("value");
236     JSHandle<JSTaggedValue> handleKey2(factory->NewFromASCII("value1"));
237 
238     ObjectOperator objectOperator(thread, handleKey);
239     objectOperator.SetIndex(1);
240     PropertyDescriptor handleDesc(thread);
241     PropertyAttributes handleAttr(handleDesc);
242     handleAttr.SetIsInlinedProps(true);
243     objectOperator.SetAttr(PropertyAttributes(handleDesc));
244 
245     // object is not DictionaryMode
246     JSHandle<JSObject> handleObject = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
247     for (int i = 0; i < 10; i++) {
248         JSHandle<JSTaggedValue> newValue(thread, JSTaggedValue(i));
249         JSHandle<EcmaString> newString =
250             factory->ConcatFromString(handleKey1, JSTaggedValue::ToString(thread, newValue));
251         JSHandle<JSTaggedValue> newKey(thread, newString.GetTaggedValue());
252         JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handleObject), newKey, newValue);
253     }
254     EXPECT_TRUE(objectOperator.UpdateDataValue(handleObject, handleValue1, false));
255     EXPECT_EQ(handleObject->GetPropertyInlinedProps(objectOperator.GetIndex()).GetInt(), 3);
256 
257     // object is DictionaryMode
258     JSObject::DeleteProperty(thread, handleObject, handleKey2);
259     EXPECT_TRUE(objectOperator.UpdateDataValue(handleObject, handleValue, false));
260     TaggedArray *resultElements2 = TaggedArray::Cast(handleObject->GetProperties().GetTaggedObject());
261     auto *resultDict = NumberDictionary::Cast(resultElements2);
262     EXPECT_EQ(resultDict->GetValue(objectOperator.GetIndex()).GetInt(), 4);
263 }
264 } // namespace panda::test