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