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