• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/base/builtins_base.h"
17 
18 #include "ecmascript/ecma_runtime_call_info.h"
19 #include "ecmascript/ecma_string.h"
20 #include "ecmascript/ecma_vm.h"
21 #include "ecmascript/global_env.h"
22 #include "ecmascript/ic/proto_change_details.h"
23 #include "ecmascript/js_function.h"
24 #include "ecmascript/js_handle.h"
25 #include "ecmascript/js_hclass.h"
26 #include "ecmascript/js_object-inl.h"
27 #include "ecmascript/js_thread.h"
28 #include "ecmascript/mem/verification.h"
29 #include "ecmascript/object_factory.h"
30 #include "ecmascript/object_operator.h"
31 #include "ecmascript/tagged_array-inl.h"
32 #include "ecmascript/tagged_dictionary.h"
33 #include "ecmascript/tests/test_helper.h"
34 #include "ecmascript/weak_vector.h"
35 
36 using namespace panda::ecmascript;
37 using namespace panda::ecmascript::base;
38 
39 namespace panda::test {
40 class JSObjectTest : public testing::Test {
41 public:
SetUpTestCase()42     static void SetUpTestCase()
43     {
44         GTEST_LOG_(INFO) << "SetUpTestCase";
45     }
46 
TearDownTestCase()47     static void TearDownTestCase()
48     {
49         GTEST_LOG_(INFO) << "TearDownCase";
50     }
51 
SetUp()52     void SetUp() override
53     {
54         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
55     }
56 
TearDown()57     void TearDown() override
58     {
59         TestHelper::DestroyEcmaVMWithScope(instance, scope);
60     }
61 
62     EcmaVM *instance {nullptr};
63     ecmascript::EcmaHandleScope *scope {nullptr};
64     JSThread *thread {nullptr};
65 };
66 
JSObjectTestCreate(JSThread * thread)67 static JSFunction *JSObjectTestCreate(JSThread *thread)
68 {
69     JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
70     return globalEnv->GetObjectFunction().GetObject<JSFunction>();
71 }
72 
HWTEST_F_L0(JSObjectTest,Create)73 HWTEST_F_L0(JSObjectTest, Create)
74 {
75     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
76     JSHandle<JSObject> jsobject =
77         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
78     EXPECT_TRUE(*jsobject != nullptr);
79 }
80 
HWTEST_F_L0(JSObjectTest,SetProperty)81 HWTEST_F_L0(JSObjectTest, SetProperty)
82 {
83     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
84     JSHandle<JSObject> jsobject =
85         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
86     EXPECT_TRUE(*jsobject != nullptr);
87 
88     char array[] = "x";
89     JSHandle<JSTaggedValue> key(thread->GetEcmaVM()->GetFactory()->NewFromASCII(array));
90     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
91 
92     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsobject), key, value);
93     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(jsobject), key).GetValue()->GetInt(), 1);
94 
95     JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(2));
96     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsobject), key, value2);
97     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(jsobject), key).GetValue()->GetInt(), 2);
98 }
99 
HWTEST_F_L0(JSObjectTest,GetProperty)100 HWTEST_F_L0(JSObjectTest, GetProperty)
101 {
102     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
103     JSHandle<JSObject> obj =
104         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
105     EXPECT_TRUE(*obj != nullptr);
106 
107     char array[] = "x";
108     JSHandle<JSTaggedValue> key(thread->GetEcmaVM()->GetFactory()->NewFromASCII(array));
109     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
110 
111     EXPECT_TRUE(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue()->IsUndefined());
112 
113     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key, value);
114     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue()->GetInt(), 1);
115 }
116 
HWTEST_F_L0(JSObjectTest,DeleteProperty)117 HWTEST_F_L0(JSObjectTest, DeleteProperty)
118 {
119     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
120     JSHandle<JSObject> obj =
121         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
122     EXPECT_TRUE(*obj != nullptr);
123 
124     char array[] = "print";
125     JSHandle<JSTaggedValue> key(thread->GetEcmaVM()->GetFactory()->NewFromASCII(array));
126     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
127 
128     JSObject::DeleteProperty(thread, (obj), key);
129     EXPECT_TRUE(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue()->IsUndefined());
130 
131     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key, value);
132     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue()->GetInt(), 1);
133 
134     JSHandle<JSTaggedValue> key2(thread->GetEcmaVM()->GetFactory()->NewFromASCII("print_test"));
135     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key2,
136                           JSHandle<JSTaggedValue>(thread, JSTaggedValue(10)));
137     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key2).GetValue()->GetInt(), 10);
138 
139     JSObject::DeleteProperty(thread, (obj), key);
140     EXPECT_TRUE(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue()->IsUndefined());
141     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key2).GetValue()->GetInt(), 10);
142 }
143 
HWTEST_F_L0(JSObjectTest,DeletePropertyGlobal)144 HWTEST_F_L0(JSObjectTest, DeletePropertyGlobal)
145 {
146     JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
147     JSHandle<JSTaggedValue> global(thread, globalEnv->GetGlobalObject());
148     JSHandle<JSTaggedValue> printKey(thread->GetEcmaVM()->GetFactory()->NewFromASCII("print"));
149     JSHandle<JSTaggedValue> printTestKey(thread->GetEcmaVM()->GetFactory()->NewFromASCII("print_test"));
150 
151     JSHandle<JSTaggedValue> value = JSObject::GetProperty(thread, global, printKey).GetValue();
152 
153     JSObject::SetProperty(thread, global, printTestKey, value);
154 
155     JSTaggedValue val2 = JSObject::GetProperty(thread, global, printTestKey).GetValue().GetTaggedValue();
156     EXPECT_EQ(val2, value.GetTaggedValue());
157     JSTaggedValue::DeletePropertyOrThrow(thread, global, printTestKey);
158     JSTaggedValue val3 = JSObject::GetProperty(thread, global, printKey).GetValue().GetTaggedValue();
159     EXPECT_NE(val3, JSTaggedValue::Undefined());
160 }
161 
HWTEST_F_L0(JSObjectTest,GetPropertyInPrototypeChain)162 HWTEST_F_L0(JSObjectTest, GetPropertyInPrototypeChain)
163 {
164     JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
165     JSHandle<JSObject> grandfather = JSObject::ObjectCreate(thread, nullHandle);
166     JSHandle<JSObject> father = JSObject::ObjectCreate(thread, grandfather);
167     JSHandle<JSObject> son = JSObject::ObjectCreate(thread, father);
168 
169     JSHandle<JSTaggedValue> sonKey(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key1"));
170     JSHandle<JSTaggedValue> fatherKey(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key2"));
171     JSHandle<JSTaggedValue> grandfatherKey(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key3"));
172     JSHandle<JSTaggedValue> sonValue(thread, JSTaggedValue(1));
173     JSHandle<JSTaggedValue> fatherValue(thread, JSTaggedValue(2));
174     JSHandle<JSTaggedValue> grandfatherValue(thread, JSTaggedValue(3));
175 
176     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(son), sonKey, sonValue);
177     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(father), fatherKey, fatherValue);
178     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(grandfather), grandfatherKey, grandfatherValue);
179 
180     EXPECT_EQ(sonValue.GetTaggedValue(),
181               JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(son), sonKey).GetValue().GetTaggedValue());
182     EXPECT_EQ(fatherValue.GetTaggedValue(),
183               JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(son), fatherKey).GetValue().GetTaggedValue());
184     EXPECT_EQ(grandfatherValue.GetTaggedValue(),
185               JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(son), grandfatherKey).GetValue().GetTaggedValue());
186 }
187 
HWTEST_F_L0(JSObjectTest,PropertyAttribute)188 HWTEST_F_L0(JSObjectTest, PropertyAttribute)
189 {
190     JSHandle<JSTaggedValue> constructor(thread, JSObjectTestCreate(thread));
191     JSHandle<JSObject> obj1 =
192         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor);
193     JSHandle<JSObject> obj2 =
194         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor);
195 
196     JSHandle<JSTaggedValue> key1(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key3"));
197     JSHandle<JSTaggedValue> key2(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key3"));
198 
199     JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1));
200     JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(2));
201 
202     // test set property
203     PropertyDescriptor desc(thread);
204     desc.SetValue(value1);
205     desc.SetWritable(false);
206     JSObject::DefineOwnProperty(thread, obj1, key1, desc);
207     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value2);
208     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key1, value1);
209     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key1, value2);
210     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1).GetValue().GetTaggedValue(),
211               value1.GetTaggedValue());
212     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj2), key1).GetValue().GetTaggedValue(),
213               value2.GetTaggedValue());
214 
215     // test delete property
216     PropertyDescriptor desc1(thread);
217     desc1.SetValue(value1);
218     desc1.SetConfigurable(false);
219     JSObject::DefineOwnProperty(thread, obj1, key2, desc1);
220     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2, value1);
221     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key2, value1);
222     JSObject::DeleteProperty(thread, (obj1), key2);
223     JSObject::DeleteProperty(thread, (obj2), key2);
224     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2).GetValue().GetTaggedValue(),
225               value1.GetTaggedValue());
226     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj2), key2).GetValue().GetTaggedValue(),
227               JSTaggedValue::Undefined());
228 }
229 
HWTEST_F_L0(JSObjectTest,CreateDataProperty)230 HWTEST_F_L0(JSObjectTest, CreateDataProperty)
231 {
232     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
233     JSHandle<JSObject> obj =
234         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
235     EXPECT_TRUE(*obj != nullptr);
236 
237     char array[] = "x";
238     JSHandle<JSTaggedValue> key(thread->GetEcmaVM()->GetFactory()->NewFromASCII(array));
239     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
240 
241     bool success = JSObject::CreateDataProperty(thread, obj, key, value);
242     EXPECT_TRUE(success);
243 
244     success = JSTaggedValue::HasOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(obj), key);
245     EXPECT_TRUE(success);
246 
247     PropertyDescriptor desc(thread);
248     success = JSObject::GetOwnProperty(thread, obj, key, desc);
249     EXPECT_TRUE(success);
250     EXPECT_EQ(true, desc.IsWritable());
251     EXPECT_EQ(true, desc.IsEnumerable());
252     EXPECT_EQ(true, desc.IsConfigurable());
253 }
254 
HWTEST_F_L0(JSObjectTest,CreateMethodProperty)255 HWTEST_F_L0(JSObjectTest, CreateMethodProperty)
256 {
257     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
258     JSHandle<JSObject> obj =
259         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
260     EXPECT_TRUE(*obj != nullptr);
261 
262     char array[] = "x";
263     JSHandle<JSTaggedValue> key(thread->GetEcmaVM()->GetFactory()->NewFromASCII(array));
264     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
265 
266     bool success = JSObject::CreateMethodProperty(thread, obj, key, value);
267     EXPECT_TRUE(success);
268 
269     success = JSTaggedValue::HasOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(obj), key);
270     EXPECT_TRUE(success);
271 
272     PropertyDescriptor desc(thread);
273     success = JSObject::GetOwnProperty(thread, obj, key, desc);
274     EXPECT_TRUE(success);
275     EXPECT_EQ(true, desc.IsWritable());
276     EXPECT_EQ(false, desc.IsEnumerable());
277     EXPECT_EQ(true, desc.IsConfigurable());
278 }
279 
HWTEST_F_L0(JSObjectTest,DefinePropertyOrThrow)280 HWTEST_F_L0(JSObjectTest, DefinePropertyOrThrow)
281 {
282     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
283     JSHandle<JSObject> obj =
284         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
285     EXPECT_TRUE(*obj != nullptr);
286 
287     char array[] = "x";
288     JSHandle<JSTaggedValue> key(thread->GetEcmaVM()->GetFactory()->NewFromASCII(array));
289 
290     PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), true, true, true);
291     bool success = JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(obj), key, desc1);
292     EXPECT_TRUE(success);
293     PropertyDescriptor descRes1(thread);
294     success = JSObject::GetOwnProperty(thread, obj, key, descRes1);
295     EXPECT_TRUE(success);
296     EXPECT_EQ(1, descRes1.GetValue()->GetInt());
297     EXPECT_EQ(true, descRes1.IsWritable());
298     EXPECT_EQ(true, descRes1.IsEnumerable());
299     EXPECT_EQ(true, descRes1.IsConfigurable());
300 
301     PropertyDescriptor desc2(thread, false, true, true);
302     success = JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(obj), key, desc2);
303     EXPECT_TRUE(success);
304     PropertyDescriptor descRes2(thread);
305     success = JSObject::GetOwnProperty(thread, obj, key, descRes2);
306     EXPECT_TRUE(success);
307     EXPECT_EQ(1, descRes2.GetValue()->GetInt());
308     EXPECT_EQ(false, descRes2.IsWritable());
309     EXPECT_EQ(true, descRes2.IsEnumerable());
310     EXPECT_EQ(true, descRes2.IsConfigurable());
311 
312     PropertyDescriptor desc3(thread);
313     desc3.SetWritable(false);
314     desc3.SetEnumerable(false);
315     desc3.SetConfigurable(false);
316     success = JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(obj), key, desc3);
317     EXPECT_TRUE(success);
318     PropertyDescriptor descRes3(thread);
319     success = JSObject::GetOwnProperty(thread, obj, key, descRes3);
320     EXPECT_TRUE(success);
321     EXPECT_EQ(1, descRes3.GetValue()->GetInt());
322     EXPECT_EQ(false, descRes3.IsWritable());
323     EXPECT_EQ(false, descRes3.IsEnumerable());
324     EXPECT_EQ(false, descRes3.IsConfigurable());
325 
326     PropertyDescriptor desc4(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(2)));
327     success = JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(obj), key, desc4);
328     EXPECT_FALSE(success);
329 }
330 
HWTEST_F_L0(JSObjectTest,HasProperty)331 HWTEST_F_L0(JSObjectTest, HasProperty)
332 {
333     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
334     JSHandle<JSObject> obj =
335         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
336     EXPECT_TRUE(*obj != nullptr);
337 
338     char array[] = "x";
339     JSHandle<JSTaggedValue> key(thread->GetEcmaVM()->GetFactory()->NewFromASCII(array));
340     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
341 
342     bool flag = JSObject::HasProperty(thread, obj, key);
343     EXPECT_FALSE(flag);
344 
345     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key, value);
346     flag = JSObject::HasProperty(thread, obj, key);
347     EXPECT_TRUE(flag);
348 
349     JSObject::DeleteProperty(thread, (obj), key);
350     flag = JSObject::HasProperty(thread, obj, key);
351     EXPECT_FALSE(flag);
352 }
353 
HWTEST_F_L0(JSObjectTest,HasPropertyWithProtoType)354 HWTEST_F_L0(JSObjectTest, HasPropertyWithProtoType)
355 {
356     JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
357     JSHandle<JSObject> grandfather = JSObject::ObjectCreate(thread, nullHandle);
358     JSHandle<JSObject> father = JSObject::ObjectCreate(thread, grandfather);
359     JSHandle<JSObject> son = JSObject::ObjectCreate(thread, father);
360 
361     JSHandle<JSTaggedValue> testGrand(thread,
362         JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(grandfather)));
363     JSHandle<JSTaggedValue> testFather(thread, JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(father)));
364     JSHandle<JSTaggedValue> testSon(thread, JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(son)));
365     EXPECT_TRUE(testSon.GetTaggedValue() != testFather.GetTaggedValue());
366     EXPECT_TRUE(testGrand.GetTaggedValue() != testFather.GetTaggedValue());
367     JSHandle<JSTaggedValue> sonKey(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key1"));
368     JSHandle<JSTaggedValue> fatherKey(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key2"));
369     JSHandle<JSTaggedValue> grandfatherKey(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key3"));
370     JSHandle<JSTaggedValue> sonValue(thread, JSTaggedValue(1));
371     JSHandle<JSTaggedValue> fatherValue(thread, JSTaggedValue(2));
372     JSHandle<JSTaggedValue> grandfatherValue(thread, JSTaggedValue(3));
373 
374     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(son), sonKey, sonValue);
375     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(father), fatherKey, fatherValue);
376     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(grandfather), grandfatherKey, grandfatherValue);
377 
378     bool flag = JSObject::HasProperty(thread, son, sonKey);
379     EXPECT_TRUE(flag);
380     flag = JSObject::HasProperty(thread, son, fatherKey);
381     EXPECT_TRUE(flag);
382     flag = JSObject::HasProperty(thread, son, grandfatherKey);
383     EXPECT_TRUE(flag);
384 }
385 
HWTEST_F_L0(JSObjectTest,HasOwnProperty)386 HWTEST_F_L0(JSObjectTest, HasOwnProperty)
387 {
388     JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
389     JSHandle<JSObject> grandfather = JSObject::ObjectCreate(thread, nullHandle);
390     JSHandle<JSObject> father = JSObject::ObjectCreate(thread, grandfather);
391     JSHandle<JSObject> son = JSObject::ObjectCreate(thread, father);
392 
393     JSHandle<JSTaggedValue> sonKey(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key1"));
394     JSHandle<JSTaggedValue> fatherKey(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key2"));
395     JSHandle<JSTaggedValue> grandfatherKey(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key3"));
396     JSHandle<JSTaggedValue> sonValue(thread, JSTaggedValue(1));
397     JSHandle<JSTaggedValue> fatherValue(thread, JSTaggedValue(2));
398     JSHandle<JSTaggedValue> grandfatherValue(thread, JSTaggedValue(3));
399 
400     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(son), sonKey, sonValue);
401     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(father), fatherKey, fatherValue);
402     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(grandfather), grandfatherKey, grandfatherValue);
403 
404     bool flag = JSTaggedValue::HasOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(son), sonKey);
405     EXPECT_TRUE(flag);
406     flag = JSTaggedValue::HasOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(son), fatherKey);
407     EXPECT_FALSE(flag);
408     flag = JSTaggedValue::HasOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(son), grandfatherKey);
409     EXPECT_FALSE(flag);
410 }
411 
HWTEST_F_L0(JSObjectTest,GetOwnPropertyKeys)412 HWTEST_F_L0(JSObjectTest, GetOwnPropertyKeys)
413 {
414     JSHandle<JSTaggedValue> constructor(thread, JSObjectTestCreate(thread));
415     JSHandle<JSObject> obj =
416         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor);
417 
418     JSHandle<JSTaggedValue> key1(thread->GetEcmaVM()->GetFactory()->NewFromASCII("x"));
419     JSHandle<JSTaggedValue> key2(thread->GetEcmaVM()->GetFactory()->NewFromASCII("y"));
420     JSHandle<JSTaggedValue> key3(thread->GetEcmaVM()->GetFactory()->NewFromASCII("3"));
421     JSHandle<JSTaggedValue> key4(thread->GetEcmaVM()->GetFactory()->NewFromASCII("4"));
422     JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1));
423     JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(2));
424     JSHandle<JSTaggedValue> value3(thread, JSTaggedValue(3));
425     JSHandle<JSTaggedValue> value4(thread, JSTaggedValue(4));
426 
427     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key1, value1);
428     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key2, value2);
429     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key3, value3);
430     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key4, value4);
431 
432     JSHandle<TaggedArray> array = JSObject::GetOwnPropertyKeys(thread, obj);
433     uint32_t length = array->GetLength();
434     EXPECT_EQ(length, 4U);
435     int sum = 0;
436     for (uint32_t i = 0; i < length; i++) {
437         JSHandle<JSTaggedValue> key(thread, array->Get(i));
438         sum += JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue()->GetInt();
439     }
440     EXPECT_EQ(sum, 10);
441 }
442 
HWTEST_F_L0(JSObjectTest,ObjectCreateMethod)443 HWTEST_F_L0(JSObjectTest, ObjectCreateMethod)
444 {
445     JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
446     JSHandle<JSObject> grandfather = JSObject::ObjectCreate(thread, nullHandle);
447     JSHandle<JSObject> father = JSObject::ObjectCreate(thread, grandfather);
448     JSHandle<JSObject> son = JSObject::ObjectCreate(thread, father);
449 
450     EXPECT_EQ(JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(son)), father.GetTaggedValue());
451     EXPECT_EQ(JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(father)), grandfather.GetTaggedValue());
452     EXPECT_EQ(JSTaggedValue::GetPrototype(thread, JSHandle<JSTaggedValue>(grandfather)), JSTaggedValue::Null());
453 }
454 
HWTEST_F_L0(JSObjectTest,GetMethod)455 HWTEST_F_L0(JSObjectTest, GetMethod)
456 {
457     JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
458     JSHandle<JSObject> obj = JSObject::ObjectCreate(thread, nullHandle);
459     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
460     JSHandle<JSTaggedValue> func(thread->GetEcmaVM()->GetFactory()->NewJSFunction(env));
461     JSHandle<JSFunction>::Cast(func)->GetJSHClass()->SetCallable(true);
462     EXPECT_TRUE(*func != nullptr);
463     JSHandle<JSTaggedValue> key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("1"));
464     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key, func);
465     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue().GetTaggedValue(),
466               func.GetTaggedValue());
467 }
468 
HWTEST_F_L0(JSObjectTest,EnumerableOwnNames)469 HWTEST_F_L0(JSObjectTest, EnumerableOwnNames)
470 {
471     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
472     JSHandle<JSObject> obj =
473         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
474     EXPECT_TRUE(*obj != nullptr);
475 
476     CString tagCStr = "x";
477     JSHandle<EcmaString> tagString = thread->GetEcmaVM()->GetFactory()->NewFromASCII(&tagCStr[0]);
478     JSHandle<JSTaggedValue> key(tagString);
479 
480     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
481 
482     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key, value);
483     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue()->GetInt(), 1);
484 
485     JSHandle<TaggedArray> names = JSObject::EnumerableOwnNames(thread, obj);
486 
487     JSHandle<JSTaggedValue> keyFromNames(thread, JSTaggedValue(names->Get(0)));
488     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), keyFromNames).GetValue()->GetInt(), 1);
489 
490     PropertyDescriptor descNoEnum(thread);
491     descNoEnum.SetEnumerable(false);
492     JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(obj), key, descNoEnum);
493     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue()->GetInt(), 1);
494 
495     JSHandle<TaggedArray> namesNoEnum = JSObject::EnumerableOwnNames(thread, obj);
496     EXPECT_TRUE(namesNoEnum->GetLength() == 0U);
497 
498     PropertyDescriptor descEnum(thread);
499     descEnum.SetConfigurable(false);
500     descEnum.SetEnumerable(true);
501     JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(obj), key, descEnum);
502     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue()->GetInt(), 1);
503 
504     JSHandle<TaggedArray> namesNoConfig = JSObject::EnumerableOwnNames(thread, obj);
505 
506     JSHandle<JSTaggedValue> keyNoConfig(thread, JSTaggedValue(namesNoConfig->Get(0)));
507     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), keyNoConfig).GetValue()->GetInt(), 1);
508 }
509 
HWTEST_F_L0(JSObjectTest,SetIntegrityLevelSealed)510 HWTEST_F_L0(JSObjectTest, SetIntegrityLevelSealed)
511 {
512     JSHandle<JSTaggedValue> hclass1(thread, JSObjectTestCreate(thread));
513     JSHandle<JSObject> obj1 =
514         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass1), hclass1);
515     EXPECT_TRUE(*obj1 != nullptr);
516     CString undefinedCStr = "x";
517     JSHandle<JSTaggedValue> key1(thread->GetEcmaVM()->GetFactory()->NewFromASCII(&undefinedCStr[0]));
518     JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1));
519     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1);
520 
521     // test SetIntegrityLevel::SEALED
522     JSHandle<JSObject> jsobject(obj1);
523     bool status1 = JSObject::SetIntegrityLevel(thread, jsobject, IntegrityLevel::SEALED);
524     EXPECT_TRUE(status1);
525     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1).GetValue().GetTaggedValue(),
526               value1.GetTaggedValue());
527     PropertyDescriptor desc1(thread);
528     bool success1 = JSObject::GetOwnProperty(thread, jsobject, key1, desc1);
529     EXPECT_TRUE(success1);
530     EXPECT_EQ(true, desc1.IsWritable());
531     EXPECT_EQ(true, desc1.IsEnumerable());
532     EXPECT_EQ(false, desc1.IsConfigurable());
533 }
534 
HWTEST_F_L0(JSObjectTest,SetIntegrityLevelFrozen)535 HWTEST_F_L0(JSObjectTest, SetIntegrityLevelFrozen)
536 {
537     JSHandle<JSTaggedValue> hclass1(thread, JSObjectTestCreate(thread));
538     JSHandle<JSObject> obj1 =
539         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass1), hclass1);
540     EXPECT_TRUE(*obj1 != nullptr);
541 
542     CString undefinedCStr = "x";
543     JSHandle<JSTaggedValue> key1(thread->GetEcmaVM()->GetFactory()->NewFromASCII(&undefinedCStr[0]));
544     JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1));
545     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1);
546 
547     // test SetIntegrityLevel::FROZEN
548     bool status1 = JSObject::SetIntegrityLevel(thread, obj1, IntegrityLevel::FROZEN);
549     EXPECT_TRUE(status1);
550     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1).GetValue().GetTaggedValue(),
551               value1.GetTaggedValue());
552     PropertyDescriptor desc1(thread);
553     bool success1 = JSObject::GetOwnProperty(thread, obj1, key1, desc1);
554     EXPECT_TRUE(success1);
555     EXPECT_EQ(false, desc1.IsWritable());
556     EXPECT_EQ(true, desc1.IsEnumerable());
557     EXPECT_EQ(false, desc1.IsConfigurable());
558 }
559 
HWTEST_F_L0(JSObjectTest,TestIntegrityLevelSealed)560 HWTEST_F_L0(JSObjectTest, TestIntegrityLevelSealed)
561 {
562     JSHandle<JSTaggedValue> hclass1(thread, JSObjectTestCreate(thread));
563     JSHandle<JSObject> obj1 =
564         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass1), hclass1);
565     CString undefinedCStr = "level";
566     JSHandle<JSTaggedValue> key1(thread->GetEcmaVM()->GetFactory()->NewFromASCII(&undefinedCStr[0]));
567     JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1));
568     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1);
569     obj1->GetJSHClass()->SetExtensible(false);
570 
571     // test SetIntegrityLevel::SEALED
572     bool status1 = JSObject::SetIntegrityLevel(thread, obj1, IntegrityLevel::SEALED);
573     EXPECT_TRUE(status1);
574     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1).GetValue().GetTaggedValue(),
575               value1.GetTaggedValue());
576 
577     PropertyDescriptor desc1(thread);
578     bool success1 = JSObject::GetOwnProperty(thread, obj1, key1, desc1);
579     EXPECT_TRUE(success1);
580     EXPECT_EQ(true, JSObject::TestIntegrityLevel(thread, obj1, IntegrityLevel::SEALED));
581     EXPECT_EQ(false, JSObject::TestIntegrityLevel(thread, obj1, IntegrityLevel::FROZEN));
582 }
583 
HWTEST_F_L0(JSObjectTest,TestIntegrityLevelFrozen)584 HWTEST_F_L0(JSObjectTest, TestIntegrityLevelFrozen)
585 {
586     JSHandle<JSTaggedValue> hclass1(thread, JSObjectTestCreate(thread));
587     JSHandle<JSObject> obj1 =
588         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass1), hclass1);
589     CString undefinedCStr = "level";
590     JSHandle<JSTaggedValue> key1(thread->GetEcmaVM()->GetFactory()->NewFromASCII(&undefinedCStr[0]));
591     JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1));
592     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1);
593     obj1->GetJSHClass()->SetExtensible(false);
594 
595     // test SetIntegrityLevel::FROZEN
596     bool status1 = JSObject::SetIntegrityLevel(thread, obj1, IntegrityLevel::FROZEN);
597     EXPECT_TRUE(status1);
598     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1).GetValue().GetTaggedValue(),
599               value1.GetTaggedValue());
600 
601     PropertyDescriptor desc1(thread);
602     bool success1 = JSObject::GetOwnProperty(thread, obj1, key1, desc1);
603     EXPECT_TRUE(success1);
604     EXPECT_EQ(true, JSObject::TestIntegrityLevel(thread, obj1, IntegrityLevel::SEALED));
605     EXPECT_EQ(true, JSObject::TestIntegrityLevel(thread, obj1, IntegrityLevel::FROZEN));
606 }
607 
HWTEST_F_L0(JSObjectTest,TestIntegrityLevelWithoutProperty)608 HWTEST_F_L0(JSObjectTest, TestIntegrityLevelWithoutProperty)
609 {
610     JSHandle<JSTaggedValue> hclass1(thread, JSObjectTestCreate(thread));
611     JSHandle<JSTaggedValue> obj1(
612         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass1), hclass1));
613     JSHandle<JSObject>::Cast(obj1)->GetJSHClass()->SetExtensible(false);
614     CString undefinedCStr = "level";
615     JSHandle<JSTaggedValue> key1(thread->GetEcmaVM()->GetFactory()->NewFromASCII(&undefinedCStr[0]));
616 
617     // test SetIntegrityLevel::FROZEN
618     JSHandle<JSObject> jsobject(obj1);
619     bool status1 = JSObject::SetIntegrityLevel(thread, jsobject, IntegrityLevel::SEALED);
620     EXPECT_TRUE(status1);
621 
622     PropertyDescriptor desc1(thread);
623     bool success1 = JSObject::GetOwnProperty(thread, jsobject, key1, desc1);
624     EXPECT_TRUE(!success1);
625     EXPECT_EQ(true, JSObject::TestIntegrityLevel(thread, jsobject, IntegrityLevel::SEALED));
626     EXPECT_EQ(true, JSObject::TestIntegrityLevel(thread, jsobject, IntegrityLevel::FROZEN));
627 }
628 
TestGetter(EcmaRuntimeCallInfo * argv)629 JSTaggedValue TestGetter(EcmaRuntimeCallInfo *argv)
630 {
631     auto thread = argv->GetThread();
632     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
633     JSHandle<JSObject> obj(BuiltinsBase::GetThis(argv));
634     JSHandle<JSTaggedValue> key(factory->NewFromASCII("y"));
635     JSTaggedValue value = JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue().GetTaggedValue();
636 
637     return JSTaggedValue(value.GetInt() + 1);
638 }
639 
HWTEST_F_L0(JSObjectTest,Getter)640 HWTEST_F_L0(JSObjectTest, Getter)
641 {
642     JSHandle<JSTaggedValue> hclass1(thread, JSObjectTestCreate(thread));
643     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
644     JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass1), hclass1);
645     JSHandle<JSTaggedValue> key1(factory->NewFromASCII("x"));
646     JSHandle<JSTaggedValue> key2(factory->NewFromASCII("y"));
647     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
648     JSHandle<JSFunction> getter =
649         thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, reinterpret_cast<void *>(TestGetter));
650 
651     PropertyDescriptor desc1(thread);
652     desc1.SetGetter(JSHandle<JSTaggedValue>::Cast(getter));
653     bool success1 = JSObject::DefineOwnProperty(thread, obj, key1, desc1);
654     EXPECT_TRUE(success1);
655 
656     PropertyDescriptor desc2(thread);
657     desc2.SetValue(JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)));
658     success1 = JSObject::DefineOwnProperty(thread, obj, key2, desc2);
659     EXPECT_TRUE(success1);
660 
661     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key1).GetValue().GetTaggedValue(),
662               JSTaggedValue(2));
663 }
664 
TestSetter(EcmaRuntimeCallInfo * argv)665 JSTaggedValue TestSetter(EcmaRuntimeCallInfo *argv)
666 {
667     JSThread *thread = argv->GetThread();
668     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
669     JSHandle<JSObject> obj(BuiltinsBase::GetThis(argv));
670     JSHandle<JSTaggedValue> key(factory->NewFromASCII("y"));
671     JSTaggedValue value(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue().GetTaggedValue());
672     JSHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue(value.GetInt() + 1));
673     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key, valueHandle);
674 
675     return JSTaggedValue(JSTaggedValue::True());
676 }
677 
HWTEST_F_L0(JSObjectTest,Setter)678 HWTEST_F_L0(JSObjectTest, Setter)
679 {
680     JSHandle<JSTaggedValue> hclass1(thread, JSObjectTestCreate(thread));
681     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
682     JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass1), hclass1);
683     JSHandle<JSTaggedValue> key1(factory->NewFromASCII("x"));
684     JSHandle<JSTaggedValue> key2(factory->NewFromASCII("y"));
685     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
686     JSHandle<JSFunction> setter =
687         thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, reinterpret_cast<void *>(TestSetter));
688 
689     PropertyDescriptor desc1(thread);
690     desc1.SetSetter(JSHandle<JSTaggedValue>::Cast(setter));
691     bool success1 = JSObject::DefineOwnProperty(thread, obj, key1, desc1);
692     EXPECT_TRUE(success1);
693 
694     PropertyDescriptor desc2(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), true, true, true);
695     success1 = JSObject::DefineOwnProperty(thread, obj, key2, desc2);
696     EXPECT_TRUE(success1);
697 
698     JSHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
699     EXPECT_TRUE(JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key1, valueHandle));
700     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key2).GetValue().GetTaggedValue(),
701               JSTaggedValue(2));
702 }
703 
HWTEST_F_L0(JSObjectTest,SpeciesConstructor)704 HWTEST_F_L0(JSObjectTest, SpeciesConstructor)
705 {
706     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
707     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
708     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
709     JSHandle<JSFunction> constructorFunc =
710         factory->NewJSFunction(env, static_cast<void *>(nullptr), FunctionKind::BASE_CONSTRUCTOR);
711     JSHandle<JSTaggedValue> constructorFuncValue(constructorFunc);
712     constructorFunc->GetJSHClass()->SetExtensible(true);
713     JSFunction::NewJSFunctionPrototype(thread, constructorFunc);
714 
715     JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
716     JSHandle<JSTaggedValue> undefinedValue(thread, JSTaggedValue::Undefined());
717     JSHandle<JSObject> protoObj = JSObject::ObjectCreate(thread, nullHandle);
718     JSHandle<JSTaggedValue> protoObjValue(protoObj);
719 
720     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
721     JSObject::SetProperty(thread, protoObjValue, constructorKey, constructorFuncValue);
722 
723     factory->NewJSObjectByConstructor(constructorFunc, JSHandle<JSTaggedValue>::Cast(constructorFunc));
724     JSHandle<JSFunction> speciesConstruct =
725         factory->NewJSFunction(env, static_cast<void *>(nullptr), FunctionKind::BASE_CONSTRUCTOR);
726     JSHandle<JSTaggedValue> speciesConstructValue(speciesConstruct);
727     constructorFunc->GetJSHClass()->SetExtensible(true);
728     JSFunction::MakeConstructor(thread, speciesConstruct, undefinedValue);
729 
730     JSHandle<JSTaggedValue> speciesSymbol = env->GetSpeciesSymbol();
731     JSObject::SetProperty(thread, constructorFuncValue, speciesSymbol, speciesConstructValue);
732 
733     JSTaggedValue speciesValue =
734         JSObject::SpeciesConstructor(thread, protoObj, constructorFuncValue).GetTaggedValue();
735     EXPECT_EQ(speciesValue, speciesConstructValue.GetTaggedValue());
736 }
737 
TestUndefinedGetter(EcmaRuntimeCallInfo * argv)738 JSTaggedValue TestUndefinedGetter([[maybe_unused]] EcmaRuntimeCallInfo *argv)
739 {
740     // 10 : test case
741     return JSTaggedValue(10);
742 }
743 
TestUndefinedSetter(EcmaRuntimeCallInfo * argv)744 JSTaggedValue TestUndefinedSetter([[maybe_unused]] EcmaRuntimeCallInfo *argv)
745 {
746     // 10 : test case
747     return JSTaggedValue(10);
748 }
749 
HWTEST_F_L0(JSObjectTest,GetterIsUndefined)750 HWTEST_F_L0(JSObjectTest, GetterIsUndefined)
751 {
752     JSHandle<JSTaggedValue> hclass1(thread, JSObjectTestCreate(thread));
753     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
754     JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass1), hclass1);
755     JSHandle<JSTaggedValue> key(factory->NewFromASCII("property"));
756     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
757     JSHandle<JSFunction> getter =
758         thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, reinterpret_cast<void *>(TestUndefinedGetter));
759     JSHandle<JSFunction> setter =
760         thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, reinterpret_cast<void *>(TestUndefinedSetter));
761     JSHandle<JSTaggedValue> unGetter(thread, JSTaggedValue::Undefined());
762 
763     PropertyDescriptor desc1(thread);
764     desc1.SetGetter(JSHandle<JSTaggedValue>::Cast(getter));
765     desc1.SetSetter(JSHandle<JSTaggedValue>::Cast(setter));
766     desc1.SetConfigurable(true);
767     desc1.SetEnumerable(true);
768     bool success1 = JSObject::DefineOwnProperty(thread, obj, key, desc1);
769     EXPECT_TRUE(success1);
770 
771     PropertyDescriptor desc2(thread);
772     desc2.SetGetter(unGetter);
773     bool success2 = JSObject::DefineOwnProperty(thread, obj, key, desc2);
774     EXPECT_TRUE(success2);
775 
776     PropertyDescriptor desc(thread);
777     bool success = JSObject::GetOwnProperty(thread, obj, key, desc);
778     EXPECT_TRUE(success);
779     EXPECT_TRUE(desc.GetSetter()->IsJSFunction());
780     EXPECT_TRUE(desc.GetGetter()->IsUndefined());
781 }
782 
HWTEST_F_L0(JSObjectTest,SetterIsUndefined)783 HWTEST_F_L0(JSObjectTest, SetterIsUndefined)
784 {
785     JSHandle<JSTaggedValue> hclass1(thread, JSObjectTestCreate(thread));
786     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
787     JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(hclass1), hclass1);
788     JSHandle<JSTaggedValue> key(factory->NewFromASCII("property"));
789     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
790     JSHandle<JSFunction> getter =
791         thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, reinterpret_cast<void *>(TestUndefinedGetter));
792     JSHandle<JSFunction> setter =
793         thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, reinterpret_cast<void *>(TestUndefinedSetter));
794     JSHandle<JSTaggedValue> unSetter(thread, JSTaggedValue::Undefined());
795 
796     PropertyDescriptor desc1(thread);
797     desc1.SetGetter(JSHandle<JSTaggedValue>::Cast(getter));
798     desc1.SetSetter(JSHandle<JSTaggedValue>::Cast(setter));
799     desc1.SetConfigurable(true);
800     desc1.SetEnumerable(true);
801     bool success1 = JSObject::DefineOwnProperty(thread, obj, key, desc1);
802     EXPECT_TRUE(success1);
803 
804     PropertyDescriptor desc2(thread);
805     desc2.SetSetter(unSetter);
806     bool success2 = JSObject::DefineOwnProperty(thread, obj, key, desc2);
807     EXPECT_TRUE(success2);
808 
809     PropertyDescriptor desc(thread);
810     bool success = JSObject::GetOwnProperty(thread, obj, key, desc);
811     EXPECT_TRUE(success);
812     EXPECT_TRUE(desc.GetSetter()->IsUndefined());
813 
814     EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue().GetTaggedValue(),
815               JSTaggedValue(10));
816 }
817 
HWTEST_F_L0(JSObjectTest,Transitions)818 HWTEST_F_L0(JSObjectTest, Transitions)
819 {
820     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
821     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
822     JSHandle<JSObject> obj1 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
823     JSHandle<JSObject> obj2 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
824 
825     JSHandle<JSHClass> hc1(thread, obj1->GetJSHClass());
826     JSHandle<JSHClass> hc2(thread, obj2->GetJSHClass());
827     EXPECT_EQ(hc1.GetTaggedValue(), hc2.GetTaggedValue());
828 
829     JSHandle<JSTaggedValue> key1(factory->NewFromASCII("x"));
830     JSHandle<JSTaggedValue> key2(factory->NewFromASCII("y"));
831     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
832 
833     // key1
834     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value);
835     JSHandle<JSHClass> hc3(thread, obj1->GetJSHClass());
836     EXPECT_NE(hc1.GetTaggedValue(), hc3.GetTaggedValue());
837 
838     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key1, value);
839     JSHandle<JSHClass> hc4(thread, obj2->GetJSHClass());
840     EXPECT_EQ(hc3.GetTaggedValue(), hc4.GetTaggedValue());
841 
842     // key2
843     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2, value);
844     JSHandle<JSHClass> hc5(thread, obj1->GetJSHClass());
845     EXPECT_NE(hc3.GetTaggedValue(), hc5.GetTaggedValue());
846 
847     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key2, value);
848     JSHandle<JSHClass> hc6(thread, obj2->GetJSHClass());
849     EXPECT_EQ(hc5.GetTaggedValue(), hc6.GetTaggedValue());
850 }
851 
HWTEST_F_L0(JSObjectTest,FastToSlow)852 HWTEST_F_L0(JSObjectTest, FastToSlow)
853 {
854     auto ecmaVM = thread->GetEcmaVM();
855     ObjectFactory *factory = ecmaVM->GetFactory();
856 
857     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
858     JSHandle<JSObject> obj1 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
859 
860     JSMutableHandle<EcmaString> key(thread, factory->NewFromASCII("x"));
861     JSMutableHandle<JSTaggedValue> number(thread, JSTaggedValue(0));
862     JSMutableHandle<JSTaggedValue> newkey(thread, JSTaggedValue(0));
863     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
864 
865     ecmaVM->SetEnableForceGC(false);
866     for (uint32_t i = 0; i < PropertyAttributes::MAX_FAST_PROPS_CAPACITY; i++) {
867         number.Update(JSTaggedValue(i));
868         number.Update(JSTaggedValue::ToString(thread, number).GetTaggedValue());
869         EcmaString *newString = *factory->ConcatFromString(key, JSTaggedValue::ToString(thread, number));
870         newkey.Update(JSTaggedValue(newString));
871         JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), newkey, value);
872     }
873     ecmaVM->SetEnableForceGC(true);
874 
875     EXPECT_FALSE(TaggedArray::Cast(obj1->GetProperties().GetTaggedObject())->IsDictionaryMode());
876 
877     number.Update(JSTaggedValue(PropertyAttributes::MAX_FAST_PROPS_CAPACITY));
878     number.Update(JSTaggedValue::ToString(thread, number).GetTaggedValue());
879     EcmaString *newString = *factory->ConcatFromString(key, JSTaggedValue::ToString(thread, number));
880     newkey.Update(JSTaggedValue(newString));
881     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), newkey, value);
882 
883     EXPECT_TRUE(TaggedArray::Cast(obj1->GetProperties().GetTaggedObject())->IsDictionaryMode());
884     NameDictionary *dict = NameDictionary::Cast(obj1->GetProperties().GetTaggedObject());
885     EXPECT_EQ(dict->EntriesCount(), static_cast<int>(PropertyAttributes::MAX_FAST_PROPS_CAPACITY + 1));
886     EXPECT_EQ(dict->NextEnumerationIndex(thread),
887               static_cast<int>(PropertyAttributes::MAX_FAST_PROPS_CAPACITY + 1));
888 }
889 
HWTEST_F_L0(JSObjectTest,DeleteMiddle)890 HWTEST_F_L0(JSObjectTest, DeleteMiddle)
891 {
892     auto ecmaVM = thread->GetEcmaVM();
893     ObjectFactory *factory = ecmaVM->GetFactory();
894 
895     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
896     JSHandle<JSObject> obj1 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
897 
898     JSMutableHandle<EcmaString> key(thread, factory->NewFromASCII("x"));
899     JSMutableHandle<JSTaggedValue> number(thread, JSTaggedValue(0));
900     JSMutableHandle<JSTaggedValue> newkey(thread, JSTaggedValue(0));
901     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
902 
903     for (uint32_t i = 0; i < 10; i++) {
904         number.Update(JSTaggedValue(i));
905         number.Update(JSTaggedValue::ToString(thread, number).GetTaggedValue());
906         EcmaString *newString = *factory->ConcatFromString(key, JSTaggedValue::ToString(thread, number));
907         newkey.Update(JSTaggedValue(newString));
908         JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), newkey, value);
909     }
910 
911     EXPECT_FALSE(TaggedArray::Cast(obj1->GetProperties().GetTaggedObject())->IsDictionaryMode());
912 
913     JSMutableHandle<JSTaggedValue> key5(thread, factory->NewFromASCII("x5"));
914     JSObject::DeleteProperty(thread, (obj1), key5);
915 
916     EXPECT_TRUE(TaggedArray::Cast(obj1->GetProperties().GetTaggedObject())->IsDictionaryMode());
917     NameDictionary *dict = NameDictionary::Cast(obj1->GetProperties().GetTaggedObject());
918     EXPECT_EQ(dict->EntriesCount(), 9);
919     EXPECT_FALSE(JSObject::HasProperty(thread, obj1, key5));
920 }
921 
HWTEST_F_L0(JSObjectTest,ElementFastToSlow)922 HWTEST_F_L0(JSObjectTest, ElementFastToSlow)
923 {
924     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
925     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
926     JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
927     JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
928     JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(2));
929     JSHandle<JSTaggedValue> key2000(thread, JSTaggedValue(2000));
930     JSHandle<JSTaggedValue> keyStr(factory->NewFromASCII("str"));
931 
932     // test dictionary [0,1,2,...,2000]
933     JSHandle<JSObject> obj1 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
934     EXPECT_TRUE(!TaggedArray::Cast(obj1->GetElements().GetTaggedObject())->IsDictionaryMode());
935     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), keyStr, key2);
936     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key0, key0);
937     EXPECT_TRUE(!TaggedArray::Cast(obj1->GetElements().GetTaggedObject())->IsDictionaryMode());
938     JSHandle<JSHClass> hclass(thread, obj1->GetJSHClass());
939     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, key1);
940     EXPECT_TRUE(!TaggedArray::Cast(obj1->GetElements().GetTaggedObject())->IsDictionaryMode());
941     EXPECT_EQ(obj1->GetJSHClass(), *hclass);
942 
943     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2000, key2000);
944     EXPECT_TRUE(TaggedArray::Cast(obj1->GetElements().GetTaggedObject())->IsDictionaryMode());
945     JSTaggedValue value =
946         JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj1), keyStr).GetValue().GetTaggedValue();
947     EXPECT_EQ(value, key2.GetTaggedValue());
948     // test holey [0,,2]
949     JSHandle<JSObject> obj2 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
950     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key0, key0);
951     EXPECT_TRUE(!TaggedArray::Cast(obj2->GetElements().GetTaggedObject())->IsDictionaryMode());
952     JSHandle<JSHClass> hclass2(thread, obj2->GetJSHClass());
953     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key2, key2);
954     EXPECT_TRUE(!TaggedArray::Cast(obj2->GetElements().GetTaggedObject())->IsDictionaryMode());
955     EXPECT_EQ(obj2->GetJSHClass(), *hclass2);
956     // test change attr
957     JSHandle<JSObject> obj3 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
958     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), key0, key0);
959     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), key1, key1);
960     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), key2, key2);
961     EXPECT_TRUE(!TaggedArray::Cast(obj3->GetElements().GetTaggedObject())->IsDictionaryMode());
962     PropertyDescriptor desc(thread);
963     desc.SetValue(key1);
964     desc.SetWritable(false);
965     JSObject::DefineOwnProperty(thread, obj3, key1, desc);
966     EXPECT_TRUE(TaggedArray::Cast(obj3->GetElements().GetTaggedObject())->IsDictionaryMode());
967     // test delete element
968     JSHandle<JSObject> obj4 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
969     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj4), key0, key0);
970     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj4), key1, key1);
971     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj4), key2, key2);
972     EXPECT_TRUE(!TaggedArray::Cast(obj4->GetElements().GetTaggedObject())->IsDictionaryMode());
973     JSObject::DeleteProperty(thread, (obj4), key1);
974     EXPECT_TRUE(TaggedArray::Cast(obj4->GetElements().GetTaggedObject())->IsDictionaryMode());
975 
976     JSHandle<JSTaggedValue> value1001(thread, JSTaggedValue(1001));
977     JSHandle<JSObject> obj100 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
978     PropertyDescriptor desc1(thread);
979     desc1.SetValue(value1001);
980     desc1.SetWritable(false);
981     desc1.SetEnumerable(false);
982     desc1.SetConfigurable(false);
983     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj100), key0, key1);
984     JSObject::DefineOwnProperty(thread, obj100, key0, desc1);
985     JSTaggedValue result1001 =
986         JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj100), key0).GetValue().GetTaggedValue();
987     EXPECT_EQ(result1001, value1001.GetTaggedValue());
988 }
989 
HWTEST_F_L0(JSObjectTest,EnableProtoChangeMarker)990 HWTEST_F_L0(JSObjectTest, EnableProtoChangeMarker)
991 {
992     JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
993     JSHandle<JSObject> obj1 = JSObject::ObjectCreate(thread, nullHandle);
994     JSHandle<JSObject> obj2 = JSObject::ObjectCreate(thread, obj1);
995     JSHandle<JSObject> obj3 = JSObject::ObjectCreate(thread, obj2);
996 
997     JSHandle<JSTaggedValue> obj1Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key1"));
998     JSHandle<JSTaggedValue> obj2Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key2"));
999     JSHandle<JSTaggedValue> obj3Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key3"));
1000     JSHandle<JSTaggedValue> obj1Value(thread, JSTaggedValue(1));
1001     JSHandle<JSTaggedValue> obj2Value(thread, JSTaggedValue(2));
1002     JSHandle<JSTaggedValue> obj3Value(thread, JSTaggedValue(3));
1003 
1004     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), obj1Key, obj1Value);
1005     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), obj2Key, obj2Value);
1006     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), obj3Key, obj3Value);
1007     JSHandle<JSHClass> obj3Class(thread, obj3->GetJSHClass());
1008     JSHandle<JSTaggedValue> resultMarker = JSHClass::EnableProtoChangeMarker(thread, obj3Class);
1009     EXPECT_TRUE(resultMarker->IsProtoChangeMarker());
1010     bool hasChanged = ProtoChangeMarker::Cast(resultMarker->GetTaggedObject())->GetHasChanged();
1011     EXPECT_TRUE(!hasChanged);
1012 
1013     JSHandle<JSHClass> obj1Class(thread, obj1->GetJSHClass());
1014     JSHandle<JSHClass> obj2Class(thread, obj2->GetJSHClass());
1015     JSTaggedValue obj2Marker = obj2Class->GetProtoChangeMarker();
1016     EXPECT_TRUE(obj2Marker.IsProtoChangeMarker());
1017     bool hasChanged2 = ProtoChangeMarker::Cast(obj2Marker.GetTaggedObject())->GetHasChanged();
1018     EXPECT_TRUE(!hasChanged2);
1019 
1020     JSTaggedValue obj1Marker = obj1Class->GetProtoChangeMarker();
1021     EXPECT_TRUE(!obj1Marker.IsProtoChangeMarker());
1022 
1023     JSTaggedValue protoDetails2 = obj2Class->GetProtoChangeDetails();
1024     EXPECT_TRUE(protoDetails2.IsProtoChangeDetails());
1025     JSTaggedValue protoDetails1 = obj1Class->GetProtoChangeDetails();
1026     EXPECT_TRUE(protoDetails1.IsProtoChangeDetails());
1027     JSTaggedValue listeners1 = ProtoChangeDetails::Cast(protoDetails1.GetTaggedObject())->GetChangeListener();
1028     EXPECT_TRUE(!listeners1.IsUndefined());
1029     JSTaggedValue listeners2 = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetChangeListener();
1030     EXPECT_TRUE(listeners2.IsUndefined());
1031     uint32_t index = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetRegisterIndex();
1032     JSTaggedValue listenersResult = ChangeListener::Cast(listeners1.GetTaggedObject())->Get(index);
1033     EXPECT_TRUE(listenersResult == obj2Class.GetTaggedValue());
1034 }
1035 
HWTEST_F_L0(JSObjectTest,BuildRegisterTree)1036 HWTEST_F_L0(JSObjectTest, BuildRegisterTree)
1037 {
1038     JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
1039     JSHandle<JSObject> obj1 = JSObject::ObjectCreate(thread, nullHandle);
1040     JSHandle<JSObject> obj2 = JSObject::ObjectCreate(thread, obj1);
1041     JSHandle<JSObject> obj3 = JSObject::ObjectCreate(thread, obj2);
1042     JSHandle<JSObject> obj4 = JSObject::ObjectCreate(thread, obj2);
1043     JSHandle<JSObject> obj5 = JSObject::ObjectCreate(thread, obj4);
1044     JSHandle<JSObject> obj6 = JSObject::ObjectCreate(thread, obj2);
1045     JSHandle<JSObject> obj7 = JSObject::ObjectCreate(thread, obj6);
1046 
1047     JSHandle<JSTaggedValue> obj1Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key1"));
1048     JSHandle<JSTaggedValue> obj2Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key2"));
1049     JSHandle<JSTaggedValue> obj3Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key3"));
1050     JSHandle<JSTaggedValue> obj4Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key4"));
1051     JSHandle<JSTaggedValue> obj5Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key5"));
1052     JSHandle<JSTaggedValue> obj6Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key6"));
1053     JSHandle<JSTaggedValue> obj7Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key7"));
1054 
1055     JSHandle<JSTaggedValue> obj1Value(thread, JSTaggedValue(1));
1056     JSHandle<JSTaggedValue> obj2Value(thread, JSTaggedValue(2));
1057     JSHandle<JSTaggedValue> obj3Value(thread, JSTaggedValue(3));
1058     JSHandle<JSTaggedValue> obj4Value(thread, JSTaggedValue(4));
1059     JSHandle<JSTaggedValue> obj5Value(thread, JSTaggedValue(5));
1060     JSHandle<JSTaggedValue> obj6Value(thread, JSTaggedValue(6));
1061     JSHandle<JSTaggedValue> obj7Value(thread, JSTaggedValue(7));
1062 
1063     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), obj1Key, obj1Value);
1064     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), obj2Key, obj2Value);
1065     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), obj3Key, obj3Value);
1066     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj4), obj4Key, obj4Value);
1067     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj5), obj5Key, obj5Value);
1068     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj6), obj6Key, obj6Value);
1069     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj7), obj7Key, obj7Value);
1070 
1071     JSHandle<JSHClass> obj1Class(thread, obj1->GetJSHClass());
1072     JSHandle<JSHClass> obj2Class(thread, obj2->GetJSHClass());
1073     JSHandle<JSHClass> obj3Class(thread, obj3->GetJSHClass());
1074     JSHandle<JSHClass> obj4Class(thread, obj4->GetJSHClass());
1075     JSHandle<JSHClass> obj5Class(thread, obj5->GetJSHClass());
1076     JSHandle<JSHClass> obj6Class(thread, obj6->GetJSHClass());
1077     JSHandle<JSHClass> obj7Class(thread, obj7->GetJSHClass());
1078 
1079     JSHandle<JSTaggedValue> result3Marker = JSHClass::EnableProtoChangeMarker(thread, obj3Class);
1080     JSHandle<JSTaggedValue> result5Marker = JSHClass::EnableProtoChangeMarker(thread, obj5Class);
1081     EXPECT_TRUE(result3Marker->IsProtoChangeMarker());
1082     EXPECT_TRUE(!(ProtoChangeMarker::Cast(result3Marker->GetTaggedObject())->GetHasChanged()));
1083     EXPECT_TRUE(result5Marker->IsProtoChangeMarker());
1084     EXPECT_TRUE(!(ProtoChangeMarker::Cast(result5Marker->GetTaggedObject())->GetHasChanged()));
1085 
1086     EXPECT_TRUE(obj4Class->GetProtoChangeMarker().IsProtoChangeMarker());
1087     EXPECT_TRUE(!obj6Class->GetProtoChangeMarker().IsProtoChangeMarker());
1088 
1089     JSHandle<JSTaggedValue> result7Marker = JSHClass::EnableProtoChangeMarker(thread, obj7Class);
1090     EXPECT_TRUE(result7Marker->IsProtoChangeMarker());
1091     EXPECT_TRUE(!(ProtoChangeMarker::Cast(result7Marker->GetTaggedObject())->GetHasChanged()));
1092 
1093     JSTaggedValue protoDetails1 = obj1Class->GetProtoChangeDetails();
1094     EXPECT_TRUE(protoDetails1.IsProtoChangeDetails());
1095     JSTaggedValue listeners1Value = ProtoChangeDetails::Cast(protoDetails1.GetTaggedObject())->GetChangeListener();
1096     EXPECT_TRUE(listeners1Value != JSTaggedValue(0));
1097     JSHandle<ChangeListener> listeners1(thread, listeners1Value.GetTaggedObject());
1098     JSTaggedValue protoDetails2 = obj2Class->GetProtoChangeDetails();
1099     EXPECT_TRUE(protoDetails2.IsProtoChangeDetails());
1100     uint32_t index2 = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetRegisterIndex();
1101     EXPECT_TRUE(listeners1->Get(index2) == obj2Class.GetTaggedValue());
1102 
1103     JSTaggedValue listeners2Value = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetChangeListener();
1104     EXPECT_TRUE(listeners2Value != JSTaggedValue(0));
1105     JSHandle<ChangeListener> listeners2(thread, listeners2Value.GetTaggedObject());
1106     JSTaggedValue protoDetails4 = obj4Class->GetProtoChangeDetails();
1107     JSTaggedValue protoDetails6 = obj6Class->GetProtoChangeDetails();
1108     EXPECT_TRUE(protoDetails4.IsProtoChangeDetails());
1109     EXPECT_TRUE(protoDetails6.IsProtoChangeDetails());
1110     uint32_t index4 = ProtoChangeDetails::Cast(protoDetails4.GetTaggedObject())->GetRegisterIndex();
1111     EXPECT_TRUE(listeners2->Get(index4) == obj4Class.GetTaggedValue());
1112     uint32_t index6 = ProtoChangeDetails::Cast(protoDetails6.GetTaggedObject())->GetRegisterIndex();
1113     EXPECT_TRUE(listeners2->Get(index6) == obj6Class.GetTaggedValue());
1114 
1115     EXPECT_TRUE(listeners1->GetEnd() == 1U);
1116     EXPECT_TRUE(listeners2->GetEnd() == 2U);
1117 }
1118 
HWTEST_F_L0(JSObjectTest,NoticeThroughChain)1119 HWTEST_F_L0(JSObjectTest, NoticeThroughChain)
1120 {
1121     JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
1122     JSHandle<JSObject> obj1 = JSObject::ObjectCreate(thread, nullHandle);
1123     JSHandle<JSObject> obj2 = JSObject::ObjectCreate(thread, obj1);
1124     JSHandle<JSObject> obj3 = JSObject::ObjectCreate(thread, obj2);
1125     JSHandle<JSObject> obj4 = JSObject::ObjectCreate(thread, obj2);
1126     JSHandle<JSObject> obj5 = JSObject::ObjectCreate(thread, obj4);
1127     JSHandle<JSObject> obj6 = JSObject::ObjectCreate(thread, obj2);
1128     JSHandle<JSObject> obj7 = JSObject::ObjectCreate(thread, obj6);
1129 
1130     JSHandle<JSTaggedValue> obj1Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key1"));
1131     JSHandle<JSTaggedValue> obj2Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key2"));
1132     JSHandle<JSTaggedValue> obj3Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key3"));
1133     JSHandle<JSTaggedValue> obj4Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key4"));
1134     JSHandle<JSTaggedValue> obj5Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key5"));
1135     JSHandle<JSTaggedValue> obj6Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key6"));
1136     JSHandle<JSTaggedValue> obj7Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key7"));
1137 
1138     JSHandle<JSTaggedValue> obj1Value(thread, JSTaggedValue(1));
1139     JSHandle<JSTaggedValue> obj2Value(thread, JSTaggedValue(2));
1140     JSHandle<JSTaggedValue> obj3Value(thread, JSTaggedValue(3));
1141     JSHandle<JSTaggedValue> obj4Value(thread, JSTaggedValue(4));
1142     JSHandle<JSTaggedValue> obj5Value(thread, JSTaggedValue(5));
1143     JSHandle<JSTaggedValue> obj6Value(thread, JSTaggedValue(6));
1144     JSHandle<JSTaggedValue> obj7Value(thread, JSTaggedValue(7));
1145 
1146     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), obj1Key, obj1Value);
1147     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), obj2Key, obj2Value);
1148     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), obj3Key, obj3Value);
1149     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj4), obj4Key, obj4Value);
1150     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj5), obj5Key, obj5Value);
1151     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj6), obj6Key, obj6Value);
1152     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj7), obj7Key, obj7Value);
1153 
1154     JSHandle<JSHClass> obj1Class(thread, obj1->GetJSHClass());
1155     JSHandle<JSHClass> obj2Class(thread, obj2->GetJSHClass());
1156     JSHandle<JSHClass> obj3Class(thread, obj3->GetJSHClass());
1157     JSHandle<JSHClass> obj4Class(thread, obj4->GetJSHClass());
1158     JSHandle<JSHClass> obj5Class(thread, obj5->GetJSHClass());
1159     JSHandle<JSHClass> obj6Class(thread, obj6->GetJSHClass());
1160     JSHandle<JSHClass> obj7Class(thread, obj7->GetJSHClass());
1161 
1162     JSHClass::EnableProtoChangeMarker(thread, obj3Class);
1163     JSHClass::EnableProtoChangeMarker(thread, obj7Class);
1164     JSHClass::EnableProtoChangeMarker(thread, obj5Class);
1165 
1166     JSHClass::NoticeThroughChain(thread, obj2Class);
1167     JSHClass::UnregisterOnProtoChain(thread, obj2Class);
1168     JSTaggedValue protoDetails1 = obj1Class->GetProtoChangeDetails();
1169     EXPECT_TRUE(protoDetails1.IsProtoChangeDetails());
1170     JSTaggedValue listeners1Value = ProtoChangeDetails::Cast(protoDetails1.GetTaggedObject())->GetChangeListener();
1171     EXPECT_TRUE(listeners1Value != JSTaggedValue(0));
1172     JSHandle<ChangeListener> listeners1(thread, listeners1Value.GetTaggedObject());
1173     uint32_t holeIndex = ChangeListener::CheckHole(listeners1);
1174     EXPECT_TRUE(holeIndex == 0U);
1175 
1176     JSTaggedValue protoDetails2 = obj2Class->GetProtoChangeDetails();
1177     EXPECT_TRUE(protoDetails2.IsProtoChangeDetails());
1178     JSTaggedValue listeners2Value = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetChangeListener();
1179     EXPECT_TRUE(listeners2Value != JSTaggedValue(0));
1180     uint32_t index2 = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetRegisterIndex();
1181     EXPECT_TRUE(listeners1->Get(index2).IsHole());
1182 
1183     JSTaggedValue obj6Marker = obj6Class->GetProtoChangeMarker();
1184     EXPECT_TRUE(obj6Marker.IsProtoChangeMarker());
1185     bool hasChanged6 = ProtoChangeMarker::Cast(obj6Marker.GetTaggedObject())->GetHasChanged();
1186     EXPECT_TRUE(hasChanged6);
1187 
1188     JSTaggedValue obj4Marker = obj4Class->GetProtoChangeMarker();
1189     EXPECT_TRUE(obj4Marker.IsProtoChangeMarker());
1190     bool hasChanged4 = ProtoChangeMarker::Cast(obj4Marker.GetTaggedObject())->GetHasChanged();
1191     EXPECT_TRUE(hasChanged4);
1192 }
1193 
HWTEST_F_L0(JSObjectTest,ChangeProtoAndNoticeTheChain)1194 HWTEST_F_L0(JSObjectTest, ChangeProtoAndNoticeTheChain)
1195 {
1196     JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
1197     JSHandle<JSObject> obj1 = JSObject::ObjectCreate(thread, nullHandle);
1198     JSHandle<JSObject> obj2 = JSObject::ObjectCreate(thread, obj1);
1199     JSHandle<JSObject> obj3 = JSObject::ObjectCreate(thread, obj1);
1200     JSHandle<JSObject> obj4 = JSObject::ObjectCreate(thread, obj2);
1201     JSHandle<JSObject> obj5 = JSObject::ObjectCreate(thread, obj4);
1202     JSHandle<JSObject> obj6 = JSObject::ObjectCreate(thread, obj2);
1203     JSHandle<JSObject> obj7 = JSObject::ObjectCreate(thread, obj6);
1204 
1205     JSHandle<JSTaggedValue> obj1Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key1"));
1206     JSHandle<JSTaggedValue> obj2Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key2"));
1207     JSHandle<JSTaggedValue> obj3Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key3"));
1208     JSHandle<JSTaggedValue> obj4Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key4"));
1209     JSHandle<JSTaggedValue> obj5Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key5"));
1210     JSHandle<JSTaggedValue> obj6Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key6"));
1211     JSHandle<JSTaggedValue> obj7Key(thread->GetEcmaVM()->GetFactory()->NewFromASCII("key7"));
1212 
1213     JSHandle<JSTaggedValue> obj1Value(thread, JSTaggedValue(1));
1214     JSHandle<JSTaggedValue> obj2Value(thread, JSTaggedValue(2));
1215     JSHandle<JSTaggedValue> obj3Value(thread, JSTaggedValue(3));
1216     JSHandle<JSTaggedValue> obj4Value(thread, JSTaggedValue(4));
1217     JSHandle<JSTaggedValue> obj5Value(thread, JSTaggedValue(5));
1218     JSHandle<JSTaggedValue> obj6Value(thread, JSTaggedValue(6));
1219     JSHandle<JSTaggedValue> obj7Value(thread, JSTaggedValue(7));
1220 
1221     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), obj1Key, obj1Value);
1222     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), obj2Key, obj2Value);
1223     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), obj3Key, obj3Value);
1224     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj4), obj4Key, obj4Value);
1225     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj5), obj5Key, obj5Value);
1226     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj6), obj6Key, obj6Value);
1227     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj7), obj7Key, obj7Value);
1228 
1229     JSHandle<JSHClass> obj5Class(thread, obj5->GetJSHClass());
1230     JSHandle<JSHClass> obj7Class(thread, obj7->GetJSHClass());
1231 
1232     JSHClass::EnableProtoChangeMarker(thread, obj7Class);
1233     JSHClass::EnableProtoChangeMarker(thread, obj5Class);
1234 
1235     JSObject::SetPrototype(thread, obj2, JSHandle<JSTaggedValue>(obj3));
1236 
1237     JSHandle<JSHClass> obj1Class(thread, obj1->GetJSHClass());
1238     JSHandle<JSHClass> obj2Class(thread, obj2->GetJSHClass());
1239     JSHandle<JSHClass> obj3Class(thread, obj3->GetJSHClass());
1240     JSHandle<JSHClass> obj4Class(thread, obj4->GetJSHClass());
1241     JSHandle<JSHClass> obj6Class(thread, obj6->GetJSHClass());
1242 
1243     JSTaggedValue obj6Marker = obj6Class->GetProtoChangeMarker();
1244     EXPECT_TRUE(obj6Marker.IsProtoChangeMarker());
1245     bool hasChanged6 = ProtoChangeMarker::Cast(obj6Marker.GetTaggedObject())->GetHasChanged();
1246     EXPECT_TRUE(hasChanged6);
1247 
1248     JSTaggedValue obj4Marker = obj4Class->GetProtoChangeMarker();
1249     EXPECT_TRUE(obj4Marker.IsProtoChangeMarker());
1250     bool hasChanged4 = ProtoChangeMarker::Cast(obj4Marker.GetTaggedObject())->GetHasChanged();
1251     EXPECT_TRUE(hasChanged4);
1252 
1253     JSTaggedValue protoDetails1 = obj1Class->GetProtoChangeDetails();
1254     EXPECT_TRUE(protoDetails1.IsProtoChangeDetails());
1255     JSTaggedValue protoDetails2 = obj2Class->GetProtoChangeDetails();
1256     EXPECT_TRUE(protoDetails2.IsProtoChangeDetails());
1257     JSTaggedValue protoDetails3 = obj3Class->GetProtoChangeDetails();
1258     EXPECT_TRUE(protoDetails3.IsProtoChangeDetails());
1259     JSTaggedValue protoDetails4 = obj4Class->GetProtoChangeDetails();
1260     EXPECT_TRUE(protoDetails4.IsProtoChangeDetails());
1261     JSTaggedValue protoDetails6 = obj6Class->GetProtoChangeDetails();
1262     EXPECT_TRUE(protoDetails6.IsProtoChangeDetails());
1263 
1264     JSTaggedValue listeners1 = ProtoChangeDetails::Cast(protoDetails1.GetTaggedObject())->GetChangeListener();
1265     EXPECT_TRUE(listeners1 != JSTaggedValue(0));
1266     JSTaggedValue listeners2 = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetChangeListener();
1267     EXPECT_TRUE(listeners2 != JSTaggedValue(0));
1268     JSTaggedValue listeners3 = ProtoChangeDetails::Cast(protoDetails3.GetTaggedObject())->GetChangeListener();
1269     EXPECT_TRUE(listeners3 != JSTaggedValue(0));
1270 
1271     uint32_t index2 = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetRegisterIndex();
1272     uint32_t index3 = ProtoChangeDetails::Cast(protoDetails3.GetTaggedObject())->GetRegisterIndex();
1273     uint32_t index4 = ProtoChangeDetails::Cast(protoDetails4.GetTaggedObject())->GetRegisterIndex();
1274     uint32_t index6 = ProtoChangeDetails::Cast(protoDetails6.GetTaggedObject())->GetRegisterIndex();
1275 
1276     JSTaggedValue result2 = ChangeListener::Cast(listeners3.GetTaggedObject())->Get(index2);
1277     JSTaggedValue result3 = ChangeListener::Cast(listeners1.GetTaggedObject())->Get(index3);
1278     JSTaggedValue result4 = ChangeListener::Cast(listeners2.GetTaggedObject())->Get(index4);
1279     JSTaggedValue result6 = ChangeListener::Cast(listeners2.GetTaggedObject())->Get(index6);
1280 
1281     EXPECT_TRUE(result2 == obj2Class.GetTaggedValue());
1282     EXPECT_TRUE(result3 == obj3Class.GetTaggedValue());
1283     EXPECT_TRUE(result4 == obj4Class.GetTaggedValue());
1284     EXPECT_TRUE(result6 == obj6Class.GetTaggedValue());
1285 }
1286 
HWTEST_F_L0(JSObjectTest,NativePointerField)1287 HWTEST_F_L0(JSObjectTest, NativePointerField)
1288 {
1289     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1290     JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
1291     JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
1292     ECMAObject::SetHash(thread, 87, JSHandle<ECMAObject>::Cast(obj));
1293     EXPECT_TRUE(obj->GetHash() == 87);
1294 
1295     obj->SetNativePointerFieldCount(thread, 1);
1296     char array[] = "Hello World!";
1297     obj->SetNativePointerField(thread, 0, array, nullptr, nullptr);
1298     int32_t count = obj->GetNativePointerFieldCount();
1299     EXPECT_TRUE(count == 1);
1300     void *pointer = obj->GetNativePointerField(0);
1301     EXPECT_TRUE(pointer == array);
1302 }
1303 
CreateTestHClass(JSThread * thread)1304 static JSHandle<JSHClass> CreateTestHClass(JSThread *thread)
1305 {
1306     JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
1307     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1308     JSHandle<JSTaggedValue> objectFuncPrototype = globalEnv->GetObjectFunctionPrototype();
1309     JSHandle<JSHClass> hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, objectFuncPrototype);
1310     return hclass;
1311 }
1312 
HWTEST_F_L0(JSObjectTest,UpdateWeakTransitions)1313 HWTEST_F_L0(JSObjectTest, UpdateWeakTransitions)
1314 {
1315     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1316     EcmaVM *vm = thread->GetEcmaVM();
1317     PropertyAttributes attr = PropertyAttributes::Default();
1318 
1319     // Initialize three objects by hc0
1320     JSHandle<JSHClass> hc0 = CreateTestHClass(thread);
1321     JSMutableHandle<JSHClass> hca(thread, JSTaggedValue::Undefined());
1322     JSMutableHandle<JSHClass> hcb(thread, JSTaggedValue::Undefined());
1323     [[maybe_unused]] JSHandle<JSObject> obj0 = factory->NewJSObject(hc0);  // need it to ensure hc0 not be collected
1324     JSHandle<JSObject> obj1 = factory->NewJSObject(hc0);
1325     JSHandle<JSObject> obj2 = factory->NewJSObject(hc0);
1326 
1327     JSHandle<JSTaggedValue> keyA(factory->NewFromASCII("a"));
1328     JSHandle<JSTaggedValue> keyB(factory->NewFromASCII("b"));
1329 
1330     {
1331         // need a new handle scope to ensure no scope refers hc1, hc2.
1332         [[maybe_unused]] EcmaHandleScope handleScope(thread);
1333 
1334         //                               / hc1 (obj1)
1335         // occur transition,  hc0 (obj0)
1336         //                               \ hc2 (obj2)
1337         JSObject::SetProperty(thread, obj1, keyA, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)));
1338         JSObject::SetProperty(thread, obj2, keyB, JSHandle<JSTaggedValue>(thread, JSTaggedValue(2)));
1339 
1340         EXPECT_TRUE(hc0->GetTransitions().IsTaggedArray());
1341         EXPECT_EQ(hc0->FindTransitions(keyA.GetTaggedValue(), attr.GetTaggedValue()), obj1->GetClass());
1342         EXPECT_EQ(hc0->FindTransitions(keyB.GetTaggedValue(), attr.GetTaggedValue()), obj2->GetClass());
1343         hca.Update(JSTaggedValue(obj1->GetClass()));
1344         hcb.Update(JSTaggedValue(obj2->GetClass()));
1345 
1346         //            / hc1 --> hc3 (obj1)
1347         // hc0 (obj0)
1348         //            \ hc2 --> hc4 (obj2)
1349         JSObject::SetProperty(thread, obj1, keyB, JSHandle<JSTaggedValue>(thread, JSTaggedValue(3)));
1350         JSObject::SetProperty(thread, obj2, keyA, JSHandle<JSTaggedValue>(thread, JSTaggedValue(4)));
1351     }
1352 
1353     // collect hc1, hc2
1354     vm->CollectGarbage(TriggerGCType::FULL_GC);
1355 
1356     EXPECT_EQ(hc0->FindTransitions(keyA.GetTaggedValue(), attr.GetTaggedValue()), hca.GetObject<JSHClass>());
1357     EXPECT_EQ(hc0->FindTransitions(keyB.GetTaggedValue(), attr.GetTaggedValue()), hcb.GetObject<JSHClass>());
1358 
1359     JSHandle<JSObject> obj3 = factory->NewJSObject(hc0);
1360     JSHandle<JSObject> obj4 = factory->NewJSObject(hc0);
1361 
1362     //                                  / hc5 (obj3)
1363     // re-occur transition,  hc0 (obj0)
1364     //                                  \ hc6 (obj4)
1365     JSObject::SetProperty(thread, obj3, keyA, JSHandle<JSTaggedValue>(thread, JSTaggedValue(5)));
1366     JSObject::SetProperty(thread, obj4, keyB, JSHandle<JSTaggedValue>(thread, JSTaggedValue(6)));
1367 
1368     EXPECT_TRUE(hc0->GetTransitions().IsTaggedArray());
1369     EXPECT_EQ(hc0->FindTransitions(keyA.GetTaggedValue(), attr.GetTaggedValue()), obj3->GetClass());
1370     EXPECT_EQ(hc0->FindTransitions(keyB.GetTaggedValue(), attr.GetTaggedValue()), obj4->GetClass());
1371     EXPECT_EQ(obj3->GetClass(), hca.GetObject<JSHClass>());
1372     EXPECT_EQ(obj4->GetClass(), hcb.GetObject<JSHClass>());
1373 }
1374 
HWTEST_F_L0(JSObjectTest,CreateObjectFromProperties)1375 HWTEST_F_L0(JSObjectTest, CreateObjectFromProperties)
1376 {
1377     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1378     JSHandle<TaggedArray> properties = factory->NewTaggedArray(2060); // 2060: array length
1379 
1380     JSHandle<EcmaString> key1(factory->NewFromASCII("aa"));
1381     JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1));
1382 
1383     for (int i = 0; i < 1030; i++) {
1384         JSHandle<EcmaString> key2(factory->NewFromASCII(std::to_string(i)));
1385         JSHandle<EcmaString> key3 =
1386             JSHandle<EcmaString>(thread, EcmaStringAccessor::Concat(thread->GetEcmaVM(), key1, key2));
1387         properties->Set(thread, 2 * i, key3.GetTaggedValue());
1388         properties->Set(thread, 2 * i + 1, value1.GetTaggedValue());
1389     }
1390 
1391     JSHandle<JSObject> newObj = JSObject::CreateObjectFromProperties(thread, properties);
1392     Heap *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
1393     heap->GetSweeper()->EnsureAllTaskFinished();
1394     Verification(heap).VerifyAll();
1395     EXPECT_TRUE(newObj->GetClass()->IsDictionaryMode());
1396 }
1397 }  // namespace panda::test
1398