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