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 #include "ecmascript/base/builtins_base.h"
18
19 #include "ecmascript/ecma_runtime_call_info.h"
20 #include "ecmascript/ecma_string.h"
21 #include "ecmascript/ecma_vm.h"
22 #include "ecmascript/global_env.h"
23 #include "ecmascript/ic/proto_change_details.h"
24 #include "ecmascript/js_function.h"
25 #include "ecmascript/js_handle.h"
26 #include "ecmascript/js_hclass.h"
27 #include "ecmascript/js_object-inl.h"
28 #include "ecmascript/js_thread.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-inl.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 PandaVM *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()->NewFromCanBeCompressString(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()->NewFromCanBeCompressString(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()->NewFromCanBeCompressString(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()->NewFromCanBeCompressString("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()->NewFromCanBeCompressString("print"));
149 JSHandle<JSTaggedValue> printTestKey(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("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()->NewFromCanBeCompressString("key1"));
170 JSHandle<JSTaggedValue> fatherKey(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key2"));
171 JSHandle<JSTaggedValue> grandfatherKey(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("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()->NewFromCanBeCompressString("key3"));
197 JSHandle<JSTaggedValue> key2(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("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()->NewFromCanBeCompressString(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()->NewFromCanBeCompressString(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()->NewFromCanBeCompressString(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()->NewFromCanBeCompressString(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 auto testGrand = grandfather->GetPrototype(thread);
362 auto testFather = father->GetPrototype(thread);
363 auto testSon = son->GetPrototype(thread);
364 EXPECT_TRUE(testSon != testFather);
365 EXPECT_TRUE(testGrand != testFather);
366 JSHandle<JSTaggedValue> sonKey(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key1"));
367 JSHandle<JSTaggedValue> fatherKey(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key2"));
368 JSHandle<JSTaggedValue> grandfatherKey(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key3"));
369 JSHandle<JSTaggedValue> sonValue(thread, JSTaggedValue(1));
370 JSHandle<JSTaggedValue> fatherValue(thread, JSTaggedValue(2));
371 JSHandle<JSTaggedValue> grandfatherValue(thread, JSTaggedValue(3));
372
373 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(son), sonKey, sonValue);
374 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(father), fatherKey, fatherValue);
375 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(grandfather), grandfatherKey, grandfatherValue);
376
377 bool flag = JSObject::HasProperty(thread, son, sonKey);
378 EXPECT_TRUE(flag);
379 flag = JSObject::HasProperty(thread, son, fatherKey);
380 EXPECT_TRUE(flag);
381 flag = JSObject::HasProperty(thread, son, grandfatherKey);
382 EXPECT_TRUE(flag);
383 }
384
HWTEST_F_L0(JSObjectTest,HasOwnProperty)385 HWTEST_F_L0(JSObjectTest, HasOwnProperty)
386 {
387 JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
388 JSHandle<JSObject> grandfather = JSObject::ObjectCreate(thread, nullHandle);
389 JSHandle<JSObject> father = JSObject::ObjectCreate(thread, grandfather);
390 JSHandle<JSObject> son = JSObject::ObjectCreate(thread, father);
391
392 JSHandle<JSTaggedValue> sonKey(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key1"));
393 JSHandle<JSTaggedValue> fatherKey(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key2"));
394 JSHandle<JSTaggedValue> grandfatherKey(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key3"));
395 JSHandle<JSTaggedValue> sonValue(thread, JSTaggedValue(1));
396 JSHandle<JSTaggedValue> fatherValue(thread, JSTaggedValue(2));
397 JSHandle<JSTaggedValue> grandfatherValue(thread, JSTaggedValue(3));
398
399 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(son), sonKey, sonValue);
400 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(father), fatherKey, fatherValue);
401 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(grandfather), grandfatherKey, grandfatherValue);
402
403 bool flag = JSTaggedValue::HasOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(son), sonKey);
404 EXPECT_TRUE(flag);
405 flag = JSTaggedValue::HasOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(son), fatherKey);
406 EXPECT_FALSE(flag);
407 flag = JSTaggedValue::HasOwnProperty(thread, JSHandle<JSTaggedValue>::Cast(son), grandfatherKey);
408 EXPECT_FALSE(flag);
409 }
410
HWTEST_F_L0(JSObjectTest,GetOwnPropertyKeys)411 HWTEST_F_L0(JSObjectTest, GetOwnPropertyKeys)
412 {
413 JSHandle<JSTaggedValue> constructor(thread, JSObjectTestCreate(thread));
414 JSHandle<JSObject> obj =
415 thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor);
416
417 JSHandle<JSTaggedValue> key1(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("x"));
418 JSHandle<JSTaggedValue> key2(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("y"));
419 JSHandle<JSTaggedValue> key3(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("3"));
420 JSHandle<JSTaggedValue> key4(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("4"));
421 JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1));
422 JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(2));
423 JSHandle<JSTaggedValue> value3(thread, JSTaggedValue(3));
424 JSHandle<JSTaggedValue> value4(thread, JSTaggedValue(4));
425
426 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key1, value1);
427 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key2, value2);
428 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key3, value3);
429 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key4, value4);
430
431 JSHandle<TaggedArray> array = JSObject::GetOwnPropertyKeys(thread, obj);
432 int length = array->GetLength();
433 EXPECT_EQ(length, 4);
434 int sum = 0;
435 for (int i = 0; i < length; i++) {
436 JSHandle<JSTaggedValue> key(thread, array->Get(i));
437 sum += JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue()->GetInt();
438 }
439 EXPECT_EQ(sum, 10);
440 }
441
HWTEST_F_L0(JSObjectTest,ObjectCreateMethod)442 HWTEST_F_L0(JSObjectTest, ObjectCreateMethod)
443 {
444 JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
445 JSHandle<JSObject> grandfather = JSObject::ObjectCreate(thread, nullHandle);
446 JSHandle<JSObject> father = JSObject::ObjectCreate(thread, grandfather);
447 JSHandle<JSObject> son = JSObject::ObjectCreate(thread, father);
448
449 EXPECT_EQ(son->GetPrototype(thread), father.GetTaggedValue());
450 EXPECT_EQ(father->GetPrototype(thread), grandfather.GetTaggedValue());
451 EXPECT_EQ(grandfather->GetPrototype(thread), JSTaggedValue::Null());
452 }
453
HWTEST_F_L0(JSObjectTest,GetMethod)454 HWTEST_F_L0(JSObjectTest, GetMethod)
455 {
456 JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
457 JSHandle<JSObject> obj = JSObject::ObjectCreate(thread, nullHandle);
458 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
459 JSHandle<JSTaggedValue> func(thread->GetEcmaVM()->GetFactory()->NewJSFunction(env));
460 JSHandle<JSFunction>::Cast(func)->GetJSHClass()->SetCallable(true);
461 EXPECT_TRUE(*func != nullptr);
462 JSHandle<JSTaggedValue> key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("1"));
463 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key, func);
464 EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue().GetTaggedValue(),
465 func.GetTaggedValue());
466 }
467
HWTEST_F_L0(JSObjectTest,EnumerableOwnNames)468 HWTEST_F_L0(JSObjectTest, EnumerableOwnNames)
469 {
470 JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
471 JSHandle<JSObject> obj =
472 thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
473 EXPECT_TRUE(*obj != nullptr);
474
475 CString tagCStr = "x";
476 JSHandle<EcmaString> tagString = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(&tagCStr[0]);
477 JSHandle<JSTaggedValue> key(tagString);
478
479 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
480
481 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key, value);
482 EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue()->GetInt(), 1);
483
484 JSHandle<TaggedArray> names = JSObject::EnumerableOwnNames(thread, obj);
485
486 JSHandle<JSTaggedValue> keyFromNames(thread, JSTaggedValue(names->Get(0)));
487 EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), keyFromNames).GetValue()->GetInt(), 1);
488
489 PropertyDescriptor descNoEnum(thread);
490 descNoEnum.SetEnumerable(false);
491 JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(obj), key, descNoEnum);
492 EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue()->GetInt(), 1);
493
494 JSHandle<TaggedArray> namesNoEnum = JSObject::EnumerableOwnNames(thread, obj);
495 EXPECT_TRUE(namesNoEnum->GetLength() == 0);
496
497 PropertyDescriptor descEnum(thread);
498 descEnum.SetConfigurable(false);
499 descEnum.SetEnumerable(true);
500 JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(obj), key, descEnum);
501 EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue()->GetInt(), 1);
502
503 JSHandle<TaggedArray> namesNoConfig = JSObject::EnumerableOwnNames(thread, obj);
504
505 JSHandle<JSTaggedValue> keyNoConfig(thread, JSTaggedValue(namesNoConfig->Get(0)));
506 EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), keyNoConfig).GetValue()->GetInt(), 1);
507 }
508
HWTEST_F_L0(JSObjectTest,SetIntegrityLevelSealed)509 HWTEST_F_L0(JSObjectTest, SetIntegrityLevelSealed)
510 {
511 JSHandle<JSTaggedValue> dynclass1(thread, JSObjectTestCreate(thread));
512 JSHandle<JSObject> obj1 =
513 thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass1), dynclass1);
514 EXPECT_TRUE(*obj1 != nullptr);
515 CString undefinedCStr = "x";
516 JSHandle<JSTaggedValue> key1(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(&undefinedCStr[0]));
517 JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1));
518 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1);
519
520 // test SetIntegrityLevel::SEALED
521 JSHandle<JSObject> jsobject(obj1);
522 bool status1 = JSObject::SetIntegrityLevel(thread, jsobject, IntegrityLevel::SEALED);
523 EXPECT_TRUE(status1);
524 EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1).GetValue().GetTaggedValue(),
525 value1.GetTaggedValue());
526 PropertyDescriptor desc1(thread);
527 bool success1 = JSObject::GetOwnProperty(thread, jsobject, key1, desc1);
528 EXPECT_TRUE(success1);
529 EXPECT_EQ(true, desc1.IsWritable());
530 EXPECT_EQ(true, desc1.IsEnumerable());
531 EXPECT_EQ(false, desc1.IsConfigurable());
532 }
533
HWTEST_F_L0(JSObjectTest,SetIntegrityLevelFrozen)534 HWTEST_F_L0(JSObjectTest, SetIntegrityLevelFrozen)
535 {
536 JSHandle<JSTaggedValue> dynclass1(thread, JSObjectTestCreate(thread));
537 JSHandle<JSObject> obj1 =
538 thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass1), dynclass1);
539 EXPECT_TRUE(*obj1 != nullptr);
540
541 CString undefinedCStr = "x";
542 JSHandle<JSTaggedValue> key1(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(&undefinedCStr[0]));
543 JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1));
544 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1);
545
546 // test SetIntegrityLevel::FROZEN
547 bool status1 = JSObject::SetIntegrityLevel(thread, obj1, IntegrityLevel::FROZEN);
548 EXPECT_TRUE(status1);
549 EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1).GetValue().GetTaggedValue(),
550 value1.GetTaggedValue());
551 PropertyDescriptor desc1(thread);
552 bool success1 = JSObject::GetOwnProperty(thread, obj1, key1, desc1);
553 EXPECT_TRUE(success1);
554 EXPECT_EQ(false, desc1.IsWritable());
555 EXPECT_EQ(true, desc1.IsEnumerable());
556 EXPECT_EQ(false, desc1.IsConfigurable());
557 }
558
HWTEST_F_L0(JSObjectTest,TestIntegrityLevelSealed)559 HWTEST_F_L0(JSObjectTest, TestIntegrityLevelSealed)
560 {
561 JSHandle<JSTaggedValue> dynclass1(thread, JSObjectTestCreate(thread));
562 JSHandle<JSObject> obj1 =
563 thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass1), dynclass1);
564 CString undefinedCStr = "level";
565 JSHandle<JSTaggedValue> key1(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(&undefinedCStr[0]));
566 JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1));
567 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1);
568 obj1->GetJSHClass()->SetExtensible(false);
569
570 // test SetIntegrityLevel::SEALED
571 bool status1 = JSObject::SetIntegrityLevel(thread, obj1, IntegrityLevel::SEALED);
572 EXPECT_TRUE(status1);
573 EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1).GetValue().GetTaggedValue(),
574 value1.GetTaggedValue());
575
576 PropertyDescriptor desc1(thread);
577 bool success1 = JSObject::GetOwnProperty(thread, obj1, key1, desc1);
578 EXPECT_TRUE(success1);
579 EXPECT_EQ(true, JSObject::TestIntegrityLevel(thread, obj1, IntegrityLevel::SEALED));
580 EXPECT_EQ(false, JSObject::TestIntegrityLevel(thread, obj1, IntegrityLevel::FROZEN));
581 }
582
HWTEST_F_L0(JSObjectTest,TestIntegrityLevelFrozen)583 HWTEST_F_L0(JSObjectTest, TestIntegrityLevelFrozen)
584 {
585 JSHandle<JSTaggedValue> dynclass1(thread, JSObjectTestCreate(thread));
586 JSHandle<JSObject> obj1 =
587 thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass1), dynclass1);
588 CString undefinedCStr = "level";
589 JSHandle<JSTaggedValue> key1(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(&undefinedCStr[0]));
590 JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1));
591 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1);
592 obj1->GetJSHClass()->SetExtensible(false);
593
594 // test SetIntegrityLevel::FROZEN
595 bool status1 = JSObject::SetIntegrityLevel(thread, obj1, IntegrityLevel::FROZEN);
596 EXPECT_TRUE(status1);
597 EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1).GetValue().GetTaggedValue(),
598 value1.GetTaggedValue());
599
600 PropertyDescriptor desc1(thread);
601 bool success1 = JSObject::GetOwnProperty(thread, obj1, key1, desc1);
602 EXPECT_TRUE(success1);
603 EXPECT_EQ(true, JSObject::TestIntegrityLevel(thread, obj1, IntegrityLevel::SEALED));
604 EXPECT_EQ(true, JSObject::TestIntegrityLevel(thread, obj1, IntegrityLevel::FROZEN));
605 }
606
HWTEST_F_L0(JSObjectTest,TestIntegrityLevelWithoutProperty)607 HWTEST_F_L0(JSObjectTest, TestIntegrityLevelWithoutProperty)
608 {
609 JSHandle<JSTaggedValue> dynclass1(thread, JSObjectTestCreate(thread));
610 JSHandle<JSTaggedValue> obj1(
611 thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass1), dynclass1));
612 JSHandle<JSObject>::Cast(obj1)->GetJSHClass()->SetExtensible(false);
613 CString undefinedCStr = "level";
614 JSHandle<JSTaggedValue> key1(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(&undefinedCStr[0]));
615
616 // test SetIntegrityLevel::FROZEN
617 JSHandle<JSObject> jsobject(obj1);
618 bool status1 = JSObject::SetIntegrityLevel(thread, jsobject, IntegrityLevel::SEALED);
619 EXPECT_TRUE(status1);
620
621 PropertyDescriptor desc1(thread);
622 bool success1 = JSObject::GetOwnProperty(thread, jsobject, key1, desc1);
623 EXPECT_TRUE(!success1);
624 EXPECT_EQ(true, JSObject::TestIntegrityLevel(thread, jsobject, IntegrityLevel::SEALED));
625 EXPECT_EQ(true, JSObject::TestIntegrityLevel(thread, jsobject, IntegrityLevel::FROZEN));
626 }
627
TestGetter(EcmaRuntimeCallInfo * argv)628 JSTaggedValue TestGetter(EcmaRuntimeCallInfo *argv)
629 {
630 auto thread = argv->GetThread();
631 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
632 JSHandle<JSObject> obj(BuiltinsBase::GetThis(argv));
633 JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("y"));
634 JSTaggedValue value = JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue().GetTaggedValue();
635
636 return JSTaggedValue(value.GetInt() + 1);
637 }
638
HWTEST_F_L0(JSObjectTest,Getter)639 HWTEST_F_L0(JSObjectTest, Getter)
640 {
641 JSHandle<JSTaggedValue> dynclass1(thread, JSObjectTestCreate(thread));
642 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
643 JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass1), dynclass1);
644 JSHandle<JSTaggedValue> key1(factory->NewFromCanBeCompressString("x"));
645 JSHandle<JSTaggedValue> key2(factory->NewFromCanBeCompressString("y"));
646 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
647 JSHandle<JSFunction> getter =
648 thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, reinterpret_cast<void *>(TestGetter));
649
650 PropertyDescriptor desc1(thread);
651 desc1.SetGetter(JSHandle<JSTaggedValue>::Cast(getter));
652 bool success1 = JSObject::DefineOwnProperty(thread, obj, key1, desc1);
653 EXPECT_TRUE(success1);
654
655 PropertyDescriptor desc2(thread);
656 desc2.SetValue(JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)));
657 success1 = JSObject::DefineOwnProperty(thread, obj, key2, desc2);
658 EXPECT_TRUE(success1);
659
660 EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key1).GetValue().GetTaggedValue(),
661 JSTaggedValue(2));
662 }
663
TestSetter(EcmaRuntimeCallInfo * argv)664 JSTaggedValue TestSetter(EcmaRuntimeCallInfo *argv)
665 {
666 JSThread *thread = argv->GetThread();
667 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
668 JSHandle<JSObject> obj(BuiltinsBase::GetThis(argv));
669 JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("y"));
670 JSTaggedValue value(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue().GetTaggedValue());
671 JSHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue(value.GetInt() + 1));
672 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key, valueHandle);
673
674 return JSTaggedValue(JSTaggedValue::True());
675 }
676
HWTEST_F_L0(JSObjectTest,Setter)677 HWTEST_F_L0(JSObjectTest, Setter)
678 {
679 JSHandle<JSTaggedValue> dynclass1(thread, JSObjectTestCreate(thread));
680 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
681 JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass1), dynclass1);
682 JSHandle<JSTaggedValue> key1(factory->NewFromCanBeCompressString("x"));
683 JSHandle<JSTaggedValue> key2(factory->NewFromCanBeCompressString("y"));
684 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
685 JSHandle<JSFunction> setter =
686 thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, reinterpret_cast<void *>(TestSetter));
687
688 PropertyDescriptor desc1(thread);
689 desc1.SetSetter(JSHandle<JSTaggedValue>::Cast(setter));
690 bool success1 = JSObject::DefineOwnProperty(thread, obj, key1, desc1);
691 EXPECT_TRUE(success1);
692
693 PropertyDescriptor desc2(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), true, true, true);
694 success1 = JSObject::DefineOwnProperty(thread, obj, key2, desc2);
695 EXPECT_TRUE(success1);
696
697 JSHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
698 EXPECT_TRUE(JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key1, valueHandle));
699 EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key2).GetValue().GetTaggedValue(),
700 JSTaggedValue(2));
701 }
702
HWTEST_F_L0(JSObjectTest,SpeciesConstructor)703 HWTEST_F_L0(JSObjectTest, SpeciesConstructor)
704 {
705 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
706 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
707 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
708 JSHandle<JSFunction> constructorFunc =
709 factory->NewJSFunction(env, static_cast<void *>(nullptr), FunctionKind::BASE_CONSTRUCTOR);
710 JSHandle<JSTaggedValue> constructorFuncValue(constructorFunc);
711 constructorFunc->GetJSHClass()->SetExtensible(true);
712 JSFunction::NewJSFunctionPrototype(thread, factory, constructorFunc);
713
714 JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
715 JSHandle<JSTaggedValue> undefinedValue(thread, JSTaggedValue::Undefined());
716 JSHandle<JSObject> protoObj = JSObject::ObjectCreate(thread, nullHandle);
717 JSHandle<JSTaggedValue> protoObjValue(protoObj);
718
719 JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
720 JSObject::SetProperty(thread, protoObjValue, constructorKey, constructorFuncValue);
721
722 factory->NewJSObjectByConstructor(constructorFunc, JSHandle<JSTaggedValue>::Cast(constructorFunc));
723 JSHandle<JSFunction> speciesConstruct =
724 factory->NewJSFunction(env, static_cast<void *>(nullptr), FunctionKind::BASE_CONSTRUCTOR);
725 JSHandle<JSTaggedValue> speciesConstructValue(speciesConstruct);
726 constructorFunc->GetJSHClass()->SetExtensible(true);
727 JSFunction::MakeConstructor(thread, speciesConstruct, undefinedValue);
728
729 JSHandle<JSTaggedValue> speciesSymbol = env->GetSpeciesSymbol();
730 JSObject::SetProperty(thread, constructorFuncValue, speciesSymbol, speciesConstructValue);
731
732 JSTaggedValue speciesValue =
733 JSObject::SpeciesConstructor(thread, protoObj, constructorFuncValue).GetTaggedValue();
734 EXPECT_EQ(speciesValue, speciesConstructValue.GetTaggedValue());
735 }
736
TestUndefinedGetter(EcmaRuntimeCallInfo * argv)737 JSTaggedValue TestUndefinedGetter([[maybe_unused]] EcmaRuntimeCallInfo *argv)
738 {
739 // 10 : test case
740 return JSTaggedValue(10);
741 }
742
TestUndefinedSetter(EcmaRuntimeCallInfo * argv)743 JSTaggedValue TestUndefinedSetter([[maybe_unused]] EcmaRuntimeCallInfo *argv)
744 {
745 // 10 : test case
746 return JSTaggedValue(10);
747 }
748
HWTEST_F_L0(JSObjectTest,GetterIsUndefined)749 HWTEST_F_L0(JSObjectTest, GetterIsUndefined)
750 {
751 JSHandle<JSTaggedValue> dynclass1(thread, JSObjectTestCreate(thread));
752 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
753 JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass1), dynclass1);
754 JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("property"));
755 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
756 JSHandle<JSFunction> getter =
757 thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, reinterpret_cast<void *>(TestUndefinedGetter));
758 JSHandle<JSFunction> setter =
759 thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, reinterpret_cast<void *>(TestUndefinedSetter));
760 JSHandle<JSTaggedValue> unGetter(thread, JSTaggedValue::Undefined());
761
762 PropertyDescriptor desc1(thread);
763 desc1.SetGetter(JSHandle<JSTaggedValue>::Cast(getter));
764 desc1.SetSetter(JSHandle<JSTaggedValue>::Cast(setter));
765 desc1.SetConfigurable(true);
766 desc1.SetEnumerable(true);
767 bool success1 = JSObject::DefineOwnProperty(thread, obj, key, desc1);
768 EXPECT_TRUE(success1);
769
770 PropertyDescriptor desc2(thread);
771 desc2.SetGetter(unGetter);
772 bool success2 = JSObject::DefineOwnProperty(thread, obj, key, desc2);
773 EXPECT_TRUE(success2);
774
775 PropertyDescriptor desc(thread);
776 bool success = JSObject::GetOwnProperty(thread, obj, key, desc);
777 EXPECT_TRUE(success);
778 EXPECT_TRUE(desc.GetSetter()->IsJSFunction());
779 EXPECT_TRUE(desc.GetGetter()->IsUndefined());
780 }
781
HWTEST_F_L0(JSObjectTest,SetterIsUndefined)782 HWTEST_F_L0(JSObjectTest, SetterIsUndefined)
783 {
784 JSHandle<JSTaggedValue> dynclass1(thread, JSObjectTestCreate(thread));
785 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
786 JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass1), dynclass1);
787 JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("property"));
788 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
789 JSHandle<JSFunction> getter =
790 thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, reinterpret_cast<void *>(TestUndefinedGetter));
791 JSHandle<JSFunction> setter =
792 thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, reinterpret_cast<void *>(TestUndefinedSetter));
793 JSHandle<JSTaggedValue> unSetter(thread, JSTaggedValue::Undefined());
794
795 PropertyDescriptor desc1(thread);
796 desc1.SetGetter(JSHandle<JSTaggedValue>::Cast(getter));
797 desc1.SetSetter(JSHandle<JSTaggedValue>::Cast(setter));
798 desc1.SetConfigurable(true);
799 desc1.SetEnumerable(true);
800 bool success1 = JSObject::DefineOwnProperty(thread, obj, key, desc1);
801 EXPECT_TRUE(success1);
802
803 PropertyDescriptor desc2(thread);
804 desc2.SetSetter(unSetter);
805 bool success2 = JSObject::DefineOwnProperty(thread, obj, key, desc2);
806 EXPECT_TRUE(success2);
807
808 PropertyDescriptor desc(thread);
809 bool success = JSObject::GetOwnProperty(thread, obj, key, desc);
810 EXPECT_TRUE(success);
811 EXPECT_TRUE(desc.GetSetter()->IsUndefined());
812
813 EXPECT_EQ(JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), key).GetValue().GetTaggedValue(),
814 JSTaggedValue(10));
815 }
816
HWTEST_F_L0(JSObjectTest,Transitions)817 HWTEST_F_L0(JSObjectTest, Transitions)
818 {
819 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
820 JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
821 JSHandle<JSObject> obj1 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
822 JSHandle<JSObject> obj2 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
823
824 JSHandle<JSHClass> hc1(thread, obj1->GetJSHClass());
825 JSHandle<JSHClass> hc2(thread, obj2->GetJSHClass());
826 EXPECT_EQ(hc1.GetTaggedValue(), hc2.GetTaggedValue());
827
828 JSHandle<JSTaggedValue> key1(factory->NewFromCanBeCompressString("x"));
829 JSHandle<JSTaggedValue> key2(factory->NewFromCanBeCompressString("y"));
830 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
831
832 // key1
833 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value);
834 JSHandle<JSHClass> hc3(thread, obj1->GetJSHClass());
835 EXPECT_NE(hc1.GetTaggedValue(), hc3.GetTaggedValue());
836
837 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key1, value);
838 JSHandle<JSHClass> hc4(thread, obj2->GetJSHClass());
839 EXPECT_EQ(hc3.GetTaggedValue(), hc4.GetTaggedValue());
840
841 // key2
842 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2, value);
843 JSHandle<JSHClass> hc5(thread, obj1->GetJSHClass());
844 EXPECT_NE(hc3.GetTaggedValue(), hc5.GetTaggedValue());
845
846 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key2, value);
847 JSHandle<JSHClass> hc6(thread, obj2->GetJSHClass());
848 EXPECT_EQ(hc5.GetTaggedValue(), hc6.GetTaggedValue());
849 }
850
HWTEST_F_L0(JSObjectTest,FastToSlow)851 HWTEST_F_L0(JSObjectTest, FastToSlow)
852 {
853 auto ecmaVM = thread->GetEcmaVM();
854 ObjectFactory *factory = ecmaVM->GetFactory();
855
856 JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
857 JSHandle<JSObject> obj1 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
858
859 JSMutableHandle<EcmaString> key(factory->NewFromCanBeCompressString("x"));
860 JSMutableHandle<JSTaggedValue> number(thread, JSTaggedValue(0));
861 JSMutableHandle<JSTaggedValue> newkey(thread, JSTaggedValue(0));
862 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
863
864 ecmaVM->SetEnableForceGC(false);
865 for (uint32_t i = 0; i < PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES; i++) {
866 number.Update(JSTaggedValue(i));
867 number.Update(JSTaggedValue::ToString(thread, number).GetTaggedValue());
868 EcmaString *newString = *factory->ConcatFromString(key, JSTaggedValue::ToString(thread, number));
869 newkey.Update(JSTaggedValue(newString));
870 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), newkey, value);
871 }
872 ecmaVM->SetEnableForceGC(true);
873
874 EXPECT_FALSE(TaggedArray::Cast(obj1->GetProperties().GetTaggedObject())->IsDictionaryMode());
875
876 number.Update(JSTaggedValue(PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES));
877 number.Update(JSTaggedValue::ToString(thread, number).GetTaggedValue());
878 EcmaString *newString = *factory->ConcatFromString(key, JSTaggedValue::ToString(thread, number));
879 newkey.Update(JSTaggedValue(newString));
880 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), newkey, value);
881
882 EXPECT_TRUE(TaggedArray::Cast(obj1->GetProperties().GetTaggedObject())->IsDictionaryMode());
883 NameDictionary *dict = NameDictionary::Cast(obj1->GetProperties().GetTaggedObject());
884 EXPECT_EQ(dict->EntriesCount(), PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES + 1);
885 EXPECT_EQ(dict->NextEnumerationIndex(thread), PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES + 1);
886 }
887
HWTEST_F_L0(JSObjectTest,DeleteMiddle)888 HWTEST_F_L0(JSObjectTest, DeleteMiddle)
889 {
890 auto ecmaVM = thread->GetEcmaVM();
891 ObjectFactory *factory = ecmaVM->GetFactory();
892
893 JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
894 JSHandle<JSObject> obj1 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
895
896 JSMutableHandle<EcmaString> key(factory->NewFromCanBeCompressString("x"));
897 JSMutableHandle<JSTaggedValue> number(thread, JSTaggedValue(0));
898 JSMutableHandle<JSTaggedValue> newkey(thread, JSTaggedValue(0));
899 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
900
901 for (uint32_t i = 0; i < 10; i++) {
902 number.Update(JSTaggedValue(i));
903 number.Update(JSTaggedValue::ToString(thread, number).GetTaggedValue());
904 EcmaString *newString = *factory->ConcatFromString(key, JSTaggedValue::ToString(thread, number));
905 newkey.Update(JSTaggedValue(newString));
906 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), newkey, value);
907 }
908
909 EXPECT_FALSE(TaggedArray::Cast(obj1->GetProperties().GetTaggedObject())->IsDictionaryMode());
910
911 JSMutableHandle<JSTaggedValue> key5(factory->NewFromCanBeCompressString("x5"));
912 JSObject::DeleteProperty(thread, (obj1), key5);
913
914 EXPECT_TRUE(TaggedArray::Cast(obj1->GetProperties().GetTaggedObject())->IsDictionaryMode());
915 NameDictionary *dict = NameDictionary::Cast(obj1->GetProperties().GetTaggedObject());
916 EXPECT_EQ(dict->EntriesCount(), 9);
917 EXPECT_FALSE(JSObject::HasProperty(thread, obj1, key5));
918 }
919
HWTEST_F_L0(JSObjectTest,ElementFastToSlow)920 HWTEST_F_L0(JSObjectTest, ElementFastToSlow)
921 {
922 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
923 JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
924 JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
925 JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
926 JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(2));
927 JSHandle<JSTaggedValue> key2000(thread, JSTaggedValue(2000));
928 JSHandle<JSTaggedValue> keyStr(factory->NewFromCanBeCompressString("str"));
929
930 // test dictionary [0,1,2,...,2000]
931 JSHandle<JSObject> obj1 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
932 EXPECT_TRUE(!TaggedArray::Cast(obj1->GetElements().GetTaggedObject())->IsDictionaryMode());
933 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), keyStr, key2);
934 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key0, key0);
935 EXPECT_TRUE(!TaggedArray::Cast(obj1->GetElements().GetTaggedObject())->IsDictionaryMode());
936 JSHandle<JSHClass> dynClass(thread, obj1->GetJSHClass());
937 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, key1);
938 EXPECT_TRUE(!TaggedArray::Cast(obj1->GetElements().GetTaggedObject())->IsDictionaryMode());
939 EXPECT_EQ(obj1->GetJSHClass(), *dynClass);
940
941 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2000, key2000);
942 EXPECT_TRUE(TaggedArray::Cast(obj1->GetElements().GetTaggedObject())->IsDictionaryMode());
943 JSTaggedValue value =
944 JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj1), keyStr).GetValue().GetTaggedValue();
945 EXPECT_EQ(value, key2.GetTaggedValue());
946 // test holey [0,,2]
947 JSHandle<JSObject> obj2 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
948 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key0, key0);
949 EXPECT_TRUE(!TaggedArray::Cast(obj2->GetElements().GetTaggedObject())->IsDictionaryMode());
950 JSHandle<JSHClass> dynClass2(thread, obj2->GetJSHClass());
951 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key2, key2);
952 EXPECT_TRUE(!TaggedArray::Cast(obj2->GetElements().GetTaggedObject())->IsDictionaryMode());
953 EXPECT_EQ(obj2->GetJSHClass(), *dynClass2);
954 // test change attr
955 JSHandle<JSObject> obj3 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
956 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), key0, key0);
957 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), key1, key1);
958 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), key2, key2);
959 EXPECT_TRUE(!TaggedArray::Cast(obj3->GetElements().GetTaggedObject())->IsDictionaryMode());
960 PropertyDescriptor desc(thread);
961 desc.SetValue(key1);
962 desc.SetWritable(false);
963 JSObject::DefineOwnProperty(thread, obj3, key1, desc);
964 EXPECT_TRUE(TaggedArray::Cast(obj3->GetElements().GetTaggedObject())->IsDictionaryMode());
965 // test delete element
966 JSHandle<JSObject> obj4 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
967 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj4), key0, key0);
968 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj4), key1, key1);
969 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj4), key2, key2);
970 EXPECT_TRUE(!TaggedArray::Cast(obj4->GetElements().GetTaggedObject())->IsDictionaryMode());
971 JSObject::DeleteProperty(thread, (obj4), key1);
972 EXPECT_TRUE(TaggedArray::Cast(obj4->GetElements().GetTaggedObject())->IsDictionaryMode());
973
974 JSHandle<JSTaggedValue> value1001(thread, JSTaggedValue(1001));
975 JSHandle<JSObject> obj100 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
976 PropertyDescriptor desc1(thread);
977 desc1.SetValue(value1001);
978 desc1.SetWritable(false);
979 desc1.SetEnumerable(false);
980 desc1.SetConfigurable(false);
981 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj100), key0, key1);
982 JSObject::DefineOwnProperty(thread, obj100, key0, desc1);
983 JSTaggedValue result1001 =
984 JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj100), key0).GetValue().GetTaggedValue();
985 EXPECT_EQ(result1001, value1001.GetTaggedValue());
986 }
987
HWTEST_F_L0(JSObjectTest,EnableProtoChangeMarker)988 HWTEST_F_L0(JSObjectTest, EnableProtoChangeMarker)
989 {
990 JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
991 JSHandle<JSObject> obj1 = JSObject::ObjectCreate(thread, nullHandle);
992 JSHandle<JSObject> obj2 = JSObject::ObjectCreate(thread, obj1);
993 JSHandle<JSObject> obj3 = JSObject::ObjectCreate(thread, obj2);
994
995 JSHandle<JSTaggedValue> obj1Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key1"));
996 JSHandle<JSTaggedValue> obj2Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key2"));
997 JSHandle<JSTaggedValue> obj3Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key3"));
998 JSHandle<JSTaggedValue> obj1Value(thread, JSTaggedValue(1));
999 JSHandle<JSTaggedValue> obj2Value(thread, JSTaggedValue(2));
1000 JSHandle<JSTaggedValue> obj3Value(thread, JSTaggedValue(3));
1001
1002 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), obj1Key, obj1Value);
1003 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), obj2Key, obj2Value);
1004 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), obj3Key, obj3Value);
1005 JSHandle<JSHClass> obj3Dynclass(thread, obj3->GetJSHClass());
1006 JSHandle<JSTaggedValue> resultMarker = JSHClass::EnableProtoChangeMarker(thread, obj3Dynclass);
1007 EXPECT_TRUE(resultMarker->IsProtoChangeMarker());
1008 bool hasChanged = ProtoChangeMarker::Cast(resultMarker->GetTaggedObject())->GetHasChanged();
1009 EXPECT_TRUE(!hasChanged);
1010
1011 JSHandle<JSHClass> obj1Dynclass(thread, obj1->GetJSHClass());
1012 JSHandle<JSHClass> obj2Dynclass(thread, obj2->GetJSHClass());
1013 JSTaggedValue obj2Marker = obj2Dynclass->GetProtoChangeMarker();
1014 EXPECT_TRUE(obj2Marker.IsProtoChangeMarker());
1015 bool hasChanged2 = ProtoChangeMarker::Cast(obj2Marker.GetTaggedObject())->GetHasChanged();
1016 EXPECT_TRUE(!hasChanged2);
1017
1018 JSTaggedValue obj1Marker = obj1Dynclass->GetProtoChangeMarker();
1019 EXPECT_TRUE(!obj1Marker.IsProtoChangeMarker());
1020
1021 JSTaggedValue protoDetails2 = obj2Dynclass->GetProtoChangeDetails();
1022 EXPECT_TRUE(protoDetails2.IsProtoChangeDetails());
1023 JSTaggedValue protoDetails1 = obj1Dynclass->GetProtoChangeDetails();
1024 EXPECT_TRUE(protoDetails1.IsProtoChangeDetails());
1025 JSTaggedValue listeners1 = ProtoChangeDetails::Cast(protoDetails1.GetTaggedObject())->GetChangeListener();
1026 EXPECT_TRUE(listeners1 != JSTaggedValue::Undefined());
1027 JSTaggedValue listeners2 = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetChangeListener();
1028 EXPECT_TRUE(listeners2 == JSTaggedValue::Undefined());
1029 uint32_t index = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetRegisterIndex();
1030 JSTaggedValue listenersResult = ChangeListener::Cast(listeners1.GetTaggedObject())->Get(index);
1031 EXPECT_TRUE(listenersResult == obj2Dynclass.GetTaggedValue());
1032 }
1033
HWTEST_F_L0(JSObjectTest,BuildRegisterTree)1034 HWTEST_F_L0(JSObjectTest, BuildRegisterTree)
1035 {
1036 JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
1037 JSHandle<JSObject> obj1 = JSObject::ObjectCreate(thread, nullHandle);
1038 JSHandle<JSObject> obj2 = JSObject::ObjectCreate(thread, obj1);
1039 JSHandle<JSObject> obj3 = JSObject::ObjectCreate(thread, obj2);
1040 JSHandle<JSObject> obj4 = JSObject::ObjectCreate(thread, obj2);
1041 JSHandle<JSObject> obj5 = JSObject::ObjectCreate(thread, obj4);
1042 JSHandle<JSObject> obj6 = JSObject::ObjectCreate(thread, obj2);
1043 JSHandle<JSObject> obj7 = JSObject::ObjectCreate(thread, obj6);
1044
1045 JSHandle<JSTaggedValue> obj1Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key1"));
1046 JSHandle<JSTaggedValue> obj2Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key2"));
1047 JSHandle<JSTaggedValue> obj3Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key3"));
1048 JSHandle<JSTaggedValue> obj4Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key4"));
1049 JSHandle<JSTaggedValue> obj5Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key5"));
1050 JSHandle<JSTaggedValue> obj6Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key6"));
1051 JSHandle<JSTaggedValue> obj7Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key7"));
1052
1053 JSHandle<JSTaggedValue> obj1Value(thread, JSTaggedValue(1));
1054 JSHandle<JSTaggedValue> obj2Value(thread, JSTaggedValue(2));
1055 JSHandle<JSTaggedValue> obj3Value(thread, JSTaggedValue(3));
1056 JSHandle<JSTaggedValue> obj4Value(thread, JSTaggedValue(4));
1057 JSHandle<JSTaggedValue> obj5Value(thread, JSTaggedValue(5));
1058 JSHandle<JSTaggedValue> obj6Value(thread, JSTaggedValue(6));
1059 JSHandle<JSTaggedValue> obj7Value(thread, JSTaggedValue(7));
1060
1061 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), obj1Key, obj1Value);
1062 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), obj2Key, obj2Value);
1063 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), obj3Key, obj3Value);
1064 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj4), obj4Key, obj4Value);
1065 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj5), obj5Key, obj5Value);
1066 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj6), obj6Key, obj6Value);
1067 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj7), obj7Key, obj7Value);
1068
1069 JSHandle<JSHClass> obj1Dynclass(thread, obj1->GetJSHClass());
1070 JSHandle<JSHClass> obj2Dynclass(thread, obj2->GetJSHClass());
1071 JSHandle<JSHClass> obj3Dynclass(thread, obj3->GetJSHClass());
1072 JSHandle<JSHClass> obj4Dynclass(thread, obj4->GetJSHClass());
1073 JSHandle<JSHClass> obj5Dynclass(thread, obj5->GetJSHClass());
1074 JSHandle<JSHClass> obj6Dynclass(thread, obj6->GetJSHClass());
1075 JSHandle<JSHClass> obj7Dynclass(thread, obj7->GetJSHClass());
1076
1077 JSHandle<JSTaggedValue> result3Marker = JSHClass::EnableProtoChangeMarker(thread, obj3Dynclass);
1078 JSHandle<JSTaggedValue> result5Marker = JSHClass::EnableProtoChangeMarker(thread, obj5Dynclass);
1079 EXPECT_TRUE(result3Marker->IsProtoChangeMarker());
1080 EXPECT_TRUE(!(ProtoChangeMarker::Cast(result3Marker->GetTaggedObject())->GetHasChanged()));
1081 EXPECT_TRUE(result5Marker->IsProtoChangeMarker());
1082 EXPECT_TRUE(!(ProtoChangeMarker::Cast(result5Marker->GetTaggedObject())->GetHasChanged()));
1083
1084 EXPECT_TRUE(obj4Dynclass->GetProtoChangeMarker().IsProtoChangeMarker());
1085 EXPECT_TRUE(!obj6Dynclass->GetProtoChangeMarker().IsProtoChangeMarker());
1086
1087 JSHandle<JSTaggedValue> result7Marker = JSHClass::EnableProtoChangeMarker(thread, obj7Dynclass);
1088 EXPECT_TRUE(result7Marker->IsProtoChangeMarker());
1089 EXPECT_TRUE(!(ProtoChangeMarker::Cast(result7Marker->GetTaggedObject())->GetHasChanged()));
1090
1091 JSTaggedValue protoDetails1 = obj1Dynclass->GetProtoChangeDetails();
1092 EXPECT_TRUE(protoDetails1.IsProtoChangeDetails());
1093 JSTaggedValue listeners1Value = ProtoChangeDetails::Cast(protoDetails1.GetTaggedObject())->GetChangeListener();
1094 EXPECT_TRUE(listeners1Value != JSTaggedValue(0));
1095 JSHandle<ChangeListener> listeners1(thread, listeners1Value.GetTaggedObject());
1096 JSTaggedValue protoDetails2 = obj2Dynclass->GetProtoChangeDetails();
1097 EXPECT_TRUE(protoDetails2.IsProtoChangeDetails());
1098 uint32_t index2 = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetRegisterIndex();
1099 EXPECT_TRUE(listeners1->Get(index2) == obj2Dynclass.GetTaggedValue());
1100
1101 JSTaggedValue listeners2Value = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetChangeListener();
1102 EXPECT_TRUE(listeners2Value != JSTaggedValue(0));
1103 JSHandle<ChangeListener> listeners2(thread, listeners2Value.GetTaggedObject());
1104 JSTaggedValue protoDetails4 = obj4Dynclass->GetProtoChangeDetails();
1105 JSTaggedValue protoDetails6 = obj6Dynclass->GetProtoChangeDetails();
1106 EXPECT_TRUE(protoDetails4.IsProtoChangeDetails());
1107 EXPECT_TRUE(protoDetails6.IsProtoChangeDetails());
1108 uint32_t index4 = ProtoChangeDetails::Cast(protoDetails4.GetTaggedObject())->GetRegisterIndex();
1109 EXPECT_TRUE(listeners2->Get(index4) == obj4Dynclass.GetTaggedValue());
1110 uint32_t index6 = ProtoChangeDetails::Cast(protoDetails6.GetTaggedObject())->GetRegisterIndex();
1111 EXPECT_TRUE(listeners2->Get(index6) == obj6Dynclass.GetTaggedValue());
1112
1113 EXPECT_TRUE(listeners1->GetEnd() == 1);
1114 EXPECT_TRUE(listeners2->GetEnd() == 2);
1115 }
1116
HWTEST_F_L0(JSObjectTest,NoticeThroughChain)1117 HWTEST_F_L0(JSObjectTest, NoticeThroughChain)
1118 {
1119 JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
1120 JSHandle<JSObject> obj1 = JSObject::ObjectCreate(thread, nullHandle);
1121 JSHandle<JSObject> obj2 = JSObject::ObjectCreate(thread, obj1);
1122 JSHandle<JSObject> obj3 = JSObject::ObjectCreate(thread, obj2);
1123 JSHandle<JSObject> obj4 = JSObject::ObjectCreate(thread, obj2);
1124 JSHandle<JSObject> obj5 = JSObject::ObjectCreate(thread, obj4);
1125 JSHandle<JSObject> obj6 = JSObject::ObjectCreate(thread, obj2);
1126 JSHandle<JSObject> obj7 = JSObject::ObjectCreate(thread, obj6);
1127
1128 JSHandle<JSTaggedValue> obj1Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key1"));
1129 JSHandle<JSTaggedValue> obj2Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key2"));
1130 JSHandle<JSTaggedValue> obj3Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key3"));
1131 JSHandle<JSTaggedValue> obj4Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key4"));
1132 JSHandle<JSTaggedValue> obj5Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key5"));
1133 JSHandle<JSTaggedValue> obj6Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key6"));
1134 JSHandle<JSTaggedValue> obj7Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key7"));
1135
1136 JSHandle<JSTaggedValue> obj1Value(thread, JSTaggedValue(1));
1137 JSHandle<JSTaggedValue> obj2Value(thread, JSTaggedValue(2));
1138 JSHandle<JSTaggedValue> obj3Value(thread, JSTaggedValue(3));
1139 JSHandle<JSTaggedValue> obj4Value(thread, JSTaggedValue(4));
1140 JSHandle<JSTaggedValue> obj5Value(thread, JSTaggedValue(5));
1141 JSHandle<JSTaggedValue> obj6Value(thread, JSTaggedValue(6));
1142 JSHandle<JSTaggedValue> obj7Value(thread, JSTaggedValue(7));
1143
1144 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), obj1Key, obj1Value);
1145 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), obj2Key, obj2Value);
1146 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), obj3Key, obj3Value);
1147 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj4), obj4Key, obj4Value);
1148 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj5), obj5Key, obj5Value);
1149 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj6), obj6Key, obj6Value);
1150 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj7), obj7Key, obj7Value);
1151
1152 JSHandle<JSHClass> obj1Dynclass(thread, obj1->GetJSHClass());
1153 JSHandle<JSHClass> obj2Dynclass(thread, obj2->GetJSHClass());
1154 JSHandle<JSHClass> obj3Dynclass(thread, obj3->GetJSHClass());
1155 JSHandle<JSHClass> obj4Dynclass(thread, obj4->GetJSHClass());
1156 JSHandle<JSHClass> obj5Dynclass(thread, obj5->GetJSHClass());
1157 JSHandle<JSHClass> obj6Dynclass(thread, obj6->GetJSHClass());
1158 JSHandle<JSHClass> obj7Dynclass(thread, obj7->GetJSHClass());
1159
1160 JSHClass::EnableProtoChangeMarker(thread, obj3Dynclass);
1161 JSHClass::EnableProtoChangeMarker(thread, obj7Dynclass);
1162 JSHClass::EnableProtoChangeMarker(thread, obj5Dynclass);
1163
1164 JSHClass::NoticeThroughChain(thread, obj2Dynclass);
1165 JSHClass::UnregisterOnProtoChain(thread, obj2Dynclass);
1166 JSTaggedValue protoDetails1 = obj1Dynclass->GetProtoChangeDetails();
1167 EXPECT_TRUE(protoDetails1.IsProtoChangeDetails());
1168 JSTaggedValue listeners1Value = ProtoChangeDetails::Cast(protoDetails1.GetTaggedObject())->GetChangeListener();
1169 EXPECT_TRUE(listeners1Value != JSTaggedValue(0));
1170 JSHandle<ChangeListener> listeners1(thread, listeners1Value.GetTaggedObject());
1171 uint32_t holeIndex = ChangeListener::CheckHole(listeners1);
1172 EXPECT_TRUE(holeIndex == 0);
1173
1174 JSTaggedValue protoDetails2 = obj2Dynclass->GetProtoChangeDetails();
1175 EXPECT_TRUE(protoDetails2.IsProtoChangeDetails());
1176 JSTaggedValue listeners2Value = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetChangeListener();
1177 EXPECT_TRUE(listeners2Value != JSTaggedValue(0));
1178 uint32_t index2 = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetRegisterIndex();
1179 EXPECT_TRUE(listeners1->Get(index2) == JSTaggedValue::Hole());
1180
1181 JSTaggedValue obj6Marker = obj6Dynclass->GetProtoChangeMarker();
1182 EXPECT_TRUE(obj6Marker.IsProtoChangeMarker());
1183 bool hasChanged6 = ProtoChangeMarker::Cast(obj6Marker.GetTaggedObject())->GetHasChanged();
1184 EXPECT_TRUE(hasChanged6);
1185
1186 JSTaggedValue obj4Marker = obj4Dynclass->GetProtoChangeMarker();
1187 EXPECT_TRUE(obj4Marker.IsProtoChangeMarker());
1188 bool hasChanged4 = ProtoChangeMarker::Cast(obj4Marker.GetTaggedObject())->GetHasChanged();
1189 EXPECT_TRUE(hasChanged4);
1190 }
1191
HWTEST_F_L0(JSObjectTest,ChangeProtoAndNoticeTheChain)1192 HWTEST_F_L0(JSObjectTest, ChangeProtoAndNoticeTheChain)
1193 {
1194 JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
1195 JSHandle<JSObject> obj1 = JSObject::ObjectCreate(thread, nullHandle);
1196 JSHandle<JSObject> obj2 = JSObject::ObjectCreate(thread, obj1);
1197 JSHandle<JSObject> obj3 = JSObject::ObjectCreate(thread, obj1);
1198 JSHandle<JSObject> obj4 = JSObject::ObjectCreate(thread, obj2);
1199 JSHandle<JSObject> obj5 = JSObject::ObjectCreate(thread, obj4);
1200 JSHandle<JSObject> obj6 = JSObject::ObjectCreate(thread, obj2);
1201 JSHandle<JSObject> obj7 = JSObject::ObjectCreate(thread, obj6);
1202
1203 JSHandle<JSTaggedValue> obj1Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key1"));
1204 JSHandle<JSTaggedValue> obj2Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key2"));
1205 JSHandle<JSTaggedValue> obj3Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key3"));
1206 JSHandle<JSTaggedValue> obj4Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key4"));
1207 JSHandle<JSTaggedValue> obj5Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key5"));
1208 JSHandle<JSTaggedValue> obj6Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key6"));
1209 JSHandle<JSTaggedValue> obj7Key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("key7"));
1210
1211 JSHandle<JSTaggedValue> obj1Value(thread, JSTaggedValue(1));
1212 JSHandle<JSTaggedValue> obj2Value(thread, JSTaggedValue(2));
1213 JSHandle<JSTaggedValue> obj3Value(thread, JSTaggedValue(3));
1214 JSHandle<JSTaggedValue> obj4Value(thread, JSTaggedValue(4));
1215 JSHandle<JSTaggedValue> obj5Value(thread, JSTaggedValue(5));
1216 JSHandle<JSTaggedValue> obj6Value(thread, JSTaggedValue(6));
1217 JSHandle<JSTaggedValue> obj7Value(thread, JSTaggedValue(7));
1218
1219 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), obj1Key, obj1Value);
1220 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), obj2Key, obj2Value);
1221 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), obj3Key, obj3Value);
1222 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj4), obj4Key, obj4Value);
1223 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj5), obj5Key, obj5Value);
1224 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj6), obj6Key, obj6Value);
1225 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj7), obj7Key, obj7Value);
1226
1227 JSHandle<JSHClass> obj5Dynclass(thread, obj5->GetJSHClass());
1228 JSHandle<JSHClass> obj7Dynclass(thread, obj7->GetJSHClass());
1229
1230 JSHClass::EnableProtoChangeMarker(thread, obj7Dynclass);
1231 JSHClass::EnableProtoChangeMarker(thread, obj5Dynclass);
1232
1233 JSObject::SetPrototype(thread, obj2, JSHandle<JSTaggedValue>(obj3));
1234
1235 JSHandle<JSHClass> obj1Dynclass(thread, obj1->GetJSHClass());
1236 JSHandle<JSHClass> obj2Dynclass(thread, obj2->GetJSHClass());
1237 JSHandle<JSHClass> obj3Dynclass(thread, obj3->GetJSHClass());
1238 JSHandle<JSHClass> obj4Dynclass(thread, obj4->GetJSHClass());
1239 JSHandle<JSHClass> obj6Dynclass(thread, obj6->GetJSHClass());
1240
1241 JSTaggedValue obj6Marker = obj6Dynclass->GetProtoChangeMarker();
1242 EXPECT_TRUE(obj6Marker.IsProtoChangeMarker());
1243 bool hasChanged6 = ProtoChangeMarker::Cast(obj6Marker.GetTaggedObject())->GetHasChanged();
1244 EXPECT_TRUE(hasChanged6);
1245
1246 JSTaggedValue obj4Marker = obj4Dynclass->GetProtoChangeMarker();
1247 EXPECT_TRUE(obj4Marker.IsProtoChangeMarker());
1248 bool hasChanged4 = ProtoChangeMarker::Cast(obj4Marker.GetTaggedObject())->GetHasChanged();
1249 EXPECT_TRUE(hasChanged4);
1250
1251 JSTaggedValue protoDetails1 = obj1Dynclass->GetProtoChangeDetails();
1252 EXPECT_TRUE(protoDetails1.IsProtoChangeDetails());
1253 JSTaggedValue protoDetails2 = obj2Dynclass->GetProtoChangeDetails();
1254 EXPECT_TRUE(protoDetails2.IsProtoChangeDetails());
1255 JSTaggedValue protoDetails3 = obj3Dynclass->GetProtoChangeDetails();
1256 EXPECT_TRUE(protoDetails3.IsProtoChangeDetails());
1257 JSTaggedValue protoDetails4 = obj4Dynclass->GetProtoChangeDetails();
1258 EXPECT_TRUE(protoDetails4.IsProtoChangeDetails());
1259 JSTaggedValue protoDetails6 = obj6Dynclass->GetProtoChangeDetails();
1260 EXPECT_TRUE(protoDetails6.IsProtoChangeDetails());
1261
1262 JSTaggedValue listeners1 = ProtoChangeDetails::Cast(protoDetails1.GetTaggedObject())->GetChangeListener();
1263 EXPECT_TRUE(listeners1 != JSTaggedValue(0));
1264 JSTaggedValue listeners2 = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetChangeListener();
1265 EXPECT_TRUE(listeners2 != JSTaggedValue(0));
1266 JSTaggedValue listeners3 = ProtoChangeDetails::Cast(protoDetails3.GetTaggedObject())->GetChangeListener();
1267 EXPECT_TRUE(listeners3 != JSTaggedValue(0));
1268
1269 uint32_t index2 = ProtoChangeDetails::Cast(protoDetails2.GetTaggedObject())->GetRegisterIndex();
1270 uint32_t index3 = ProtoChangeDetails::Cast(protoDetails3.GetTaggedObject())->GetRegisterIndex();
1271 uint32_t index4 = ProtoChangeDetails::Cast(protoDetails4.GetTaggedObject())->GetRegisterIndex();
1272 uint32_t index6 = ProtoChangeDetails::Cast(protoDetails6.GetTaggedObject())->GetRegisterIndex();
1273
1274 JSTaggedValue result2 = ChangeListener::Cast(listeners3.GetTaggedObject())->Get(index2);
1275 JSTaggedValue result3 = ChangeListener::Cast(listeners1.GetTaggedObject())->Get(index3);
1276 JSTaggedValue result4 = ChangeListener::Cast(listeners2.GetTaggedObject())->Get(index4);
1277 JSTaggedValue result6 = ChangeListener::Cast(listeners2.GetTaggedObject())->Get(index6);
1278
1279 EXPECT_TRUE(result2 == obj2Dynclass.GetTaggedValue());
1280 EXPECT_TRUE(result3 == obj3Dynclass.GetTaggedValue());
1281 EXPECT_TRUE(result4 == obj4Dynclass.GetTaggedValue());
1282 EXPECT_TRUE(result6 == obj6Dynclass.GetTaggedValue());
1283 }
1284
HWTEST_F_L0(JSObjectTest,NativePointerField)1285 HWTEST_F_L0(JSObjectTest, NativePointerField)
1286 {
1287 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1288 JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
1289 JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
1290 obj->SetHash(87);
1291 EXPECT_TRUE(obj->GetHash() == 87);
1292
1293 obj->SetNativePointerFieldCount(1);
1294 char array[] = "Hello World!";
1295 obj->SetNativePointerField(0, array, nullptr, nullptr);
1296 int32_t count = obj->GetNativePointerFieldCount();
1297 EXPECT_TRUE(count == 1);
1298 void *pointer = obj->GetNativePointerField(0);
1299 EXPECT_TRUE(pointer == array);
1300 }
1301 } // namespace panda::test
1302