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