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/ecma_string-inl.h"
17 #include "ecmascript/ecma_vm.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/js_array.h"
20 #include "ecmascript/js_function.h"
21 #include "ecmascript/js_hclass.h"
22 #include "ecmascript/js_object-inl.h"
23 #include "ecmascript/js_primitive_ref.h"
24 #include "ecmascript/js_tagged_value-inl.h"
25 #include "ecmascript/lexical_env.h"
26 #include "ecmascript/object_factory.h"
27 #include "ecmascript/tagged_array-inl.h"
28 #include "ecmascript/tests/test_helper.h"
29
30 using namespace panda;
31
32 using namespace panda::ecmascript;
33
34 namespace panda::test {
35 class ObjectFactoryTest : public BaseTestWithScope<false> {
36 };
37
GetGlobal(JSThread * thread)38 JSHandle<GlobalEnv> GetGlobal(JSThread *thread)
39 {
40 return thread->GetEcmaVM()->GetGlobalEnv();
41 }
42
HWTEST_F_L0(ObjectFactoryTest,NewJSObjectByConstructor)43 HWTEST_F_L0(ObjectFactoryTest, NewJSObjectByConstructor)
44 {
45 thread->GetEcmaVM()->SetEnableForceGC(false);
46 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
47 JSHandle<JSTaggedValue> objFun = GetGlobal(thread)->GetObjectFunction();
48
49 // check mem alloc
50 JSHandle<JSObject> newObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
51 JSHandle<JSHClass> newObjCls(thread, newObj->GetJSHClass());
52 EXPECT_TRUE(*newObj != nullptr);
53 EXPECT_TRUE(*newObjCls != nullptr);
54
55 // check feild
56 EXPECT_EQ(newObj->GetProperties(), thread->GlobalConstants()->GetEmptyArray());
57 EXPECT_EQ(newObj->GetElements(), thread->GlobalConstants()->GetEmptyArray());
58 EXPECT_TRUE(JSTaggedValue(*newObj).IsECMAObject());
59
60 // check jshclass
61 JSHClass *cls = *newObjCls;
62 EXPECT_TRUE(cls->GetObjectSize() ==
63 JSObject::SIZE + JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS * JSTaggedValue::TaggedTypeSize());
64 EXPECT_TRUE(cls->GetPrototype() == GetGlobal(thread)->GetObjectFunctionPrototype().GetTaggedValue());
65 EXPECT_TRUE(cls->GetObjectType() == JSType::JS_OBJECT);
66
67 // check gc handle update
68 auto *prototype = cls->GetPrototype().GetTaggedObject();
69 thread->GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC);
70 // After FullGC
71 if (thread->GetEcmaVM()->GetJSOptions().EnableSnapshotDeserialize()) {
72 EXPECT_TRUE(prototype == newObjCls->GetPrototype().GetTaggedObject());
73 } else {
74 EXPECT_TRUE(prototype != newObjCls->GetPrototype().GetTaggedObject());
75 }
76 thread->GetEcmaVM()->SetEnableForceGC(true);
77 }
78
HWTEST_F_L0(ObjectFactoryTest,NewJSFunction)79 HWTEST_F_L0(ObjectFactoryTest, NewJSFunction)
80 {
81 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
82 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
83
84 // check mem alloc
85 JSHandle<JSFunction> newFun = factory->NewJSFunction(env);
86 JSHandle<JSHClass> newFunCls(thread, newFun->GetJSHClass());
87 EXPECT_TRUE(*newFun != nullptr);
88 EXPECT_TRUE(*newFunCls != nullptr);
89
90 // check feild
91 EXPECT_EQ(newFun->GetProperties(), thread->GlobalConstants()->GetEmptyArray());
92 EXPECT_EQ(newFun->GetElements(), thread->GlobalConstants()->GetEmptyArray());
93 EXPECT_EQ(newFun->GetProtoOrHClass(), JSTaggedValue::Hole());
94 EXPECT_EQ(newFun->GetHomeObject(), JSTaggedValue::Undefined());
95 EXPECT_TRUE(JSTaggedValue(*newFun).IsJSFunction());
96
97 // check jshclass
98 JSHClass *cls = *newFunCls;
99 EXPECT_TRUE(cls->GetObjectSize() ==
100 JSFunction::SIZE + JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS * JSTaggedValue::TaggedTypeSize());
101 EXPECT_TRUE(cls->GetPrototype() == GetGlobal(thread)->GetFunctionPrototype().GetTaggedValue());
102 EXPECT_TRUE(cls->GetObjectType() == JSType::JS_FUNCTION);
103 EXPECT_TRUE(cls->IsCallable());
104 EXPECT_TRUE(cls->IsExtensible());
105 EXPECT_TRUE(!cls->IsConstructor());
106 }
107
HWTEST_F_L0(ObjectFactoryTest,NewJSBoundFunction)108 HWTEST_F_L0(ObjectFactoryTest, NewJSBoundFunction)
109 {
110 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
111
112 // test prepare
113 JSHandle<JSFunction> funFun(GetGlobal(thread)->GetObjectFunction());
114 JSHandle<JSTaggedValue> bound(thread, GetGlobal(thread)->GetObjectFunctionPrototype().GetTaggedValue());
115 const JSHandle<TaggedArray> array(thread->GlobalConstants()->GetHandledEmptyArray());
116
117 // check mem alloc
118 JSHandle<JSBoundFunction> newBoundFun =
119 factory->NewJSBoundFunction(JSHandle<JSTaggedValue>::Cast(funFun), bound, array);
120 JSHandle<JSHClass> newBoundFunCls(thread, newBoundFun->GetJSHClass());
121 EXPECT_TRUE(*newBoundFun != nullptr);
122 EXPECT_TRUE(*newBoundFunCls != nullptr);
123 }
124
HWTEST_F_L0(ObjectFactoryTest,NewJSPrimitiveRef)125 HWTEST_F_L0(ObjectFactoryTest, NewJSPrimitiveRef)
126 {
127 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
128
129 // test prepare
130 JSHandle<JSFunction> numberFun(GetGlobal(thread)->GetNumberFunction());
131 JSHandle<JSTaggedValue> primitive(thread, JSTaggedValue(1));
132
133 // check mem alloc
134 JSHandle<JSPrimitiveRef> newPrimitive = factory->NewJSPrimitiveRef(numberFun, primitive);
135 JSHandle<JSHClass> newPrimitiveCls(thread, newPrimitive->GetJSHClass());
136 EXPECT_TRUE(*newPrimitive != nullptr);
137 EXPECT_TRUE(*newPrimitiveCls != nullptr);
138
139 EXPECT_TRUE(newPrimitive->GetValue() == JSTaggedValue(1));
140 }
141
HWTEST_F_L0(ObjectFactoryTest,NewLexicalEnv)142 HWTEST_F_L0(ObjectFactoryTest, NewLexicalEnv)
143 {
144 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
145
146 // check mem alloc
147 JSHandle<LexicalEnv> newLexicalEnv = factory->NewLexicalEnv(0);
148 JSHandle<JSHClass> newLexicalEnvCls(thread, newLexicalEnv->GetClass());
149 EXPECT_TRUE(*newLexicalEnv != nullptr);
150 EXPECT_TRUE(*newLexicalEnvCls != nullptr);
151 }
152
HWTEST_F_L0(ObjectFactoryTest,NewJSArray)153 HWTEST_F_L0(ObjectFactoryTest, NewJSArray)
154 {
155 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
156
157 // check mem alloc
158 JSHandle<JSArray> newJSAarray = factory->NewJSArray();
159 JSHandle<JSHClass> newJSArrayCls(thread, newJSAarray->GetJSHClass());
160 EXPECT_TRUE(*newJSAarray != nullptr);
161 EXPECT_TRUE(*newJSArrayCls != nullptr);
162 }
163
HWTEST_F_L0(ObjectFactoryTest,NewAndCopyTaggedArray)164 HWTEST_F_L0(ObjectFactoryTest, NewAndCopyTaggedArray)
165 {
166 constexpr uint32_t SHORT_ELEMENT_NUMS = 20;
167 constexpr uint32_t LONG_ELEMENT_NUMS = 100;
168 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
169 JSHandle<TaggedArray> shortTaggedarray = factory->NewTaggedArray(SHORT_ELEMENT_NUMS);
170 // init tagggedArray
171 for (uint32_t i = 0; i < SHORT_ELEMENT_NUMS; i++) {
172 shortTaggedarray->Set(thread, i, JSTaggedValue(i));
173 }
174 JSHandle<TaggedArray> copiedShort = factory->NewAndCopyTaggedArray(shortTaggedarray, SHORT_ELEMENT_NUMS,
175 SHORT_ELEMENT_NUMS);
176 JSHandle<TaggedArray> copiedLong = factory->NewAndCopyTaggedArray(shortTaggedarray, LONG_ELEMENT_NUMS,
177 SHORT_ELEMENT_NUMS);
178 // check
179 for (uint32_t i = 0; i < SHORT_ELEMENT_NUMS; i++) {
180 EXPECT_EQ(copiedShort->Get(thread, i), shortTaggedarray->Get(thread, i));
181 EXPECT_EQ(copiedLong->Get(thread, i), shortTaggedarray->Get(thread, i));
182 }
183 for (uint32_t i = SHORT_ELEMENT_NUMS; i < LONG_ELEMENT_NUMS; i++) {
184 EXPECT_EQ(copiedLong->Get(thread, i), JSTaggedValue::Hole());
185 }
186 }
187
HWTEST_F_L0(ObjectFactoryTest,NewAndCopyTaggedArrayNeedBarrier)188 HWTEST_F_L0(ObjectFactoryTest, NewAndCopyTaggedArrayNeedBarrier)
189 {
190 constexpr uint32_t SHORT_ELEMENT_NUMS = 20;
191 constexpr uint32_t LONG_ELEMENT_NUMS = 100;
192 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
193 JSHandle<TaggedArray> shortTaggedarray = factory->NewTaggedArray(SHORT_ELEMENT_NUMS);
194 // init tagggedArray
195 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
196 for (uint32_t i = 0; i < SHORT_ELEMENT_NUMS; i++) {
197 JSHandle<JSFunction> newFun = factory->NewJSFunction(env);
198 shortTaggedarray->Set(thread, i, newFun);
199 }
200 JSHandle<TaggedArray> copiedShort = factory->NewAndCopyTaggedArray(shortTaggedarray, SHORT_ELEMENT_NUMS,
201 SHORT_ELEMENT_NUMS);
202 JSHandle<TaggedArray> copiedLong = factory->NewAndCopyTaggedArray(shortTaggedarray, LONG_ELEMENT_NUMS,
203 SHORT_ELEMENT_NUMS);
204 // check
205 for (uint32_t i = 0; i < SHORT_ELEMENT_NUMS; i++) {
206 EXPECT_EQ(copiedShort->Get(thread, i), shortTaggedarray->Get(thread, i));
207 EXPECT_EQ(copiedLong->Get(thread, i), shortTaggedarray->Get(thread, i));
208 }
209 for (uint32_t i = SHORT_ELEMENT_NUMS; i < LONG_ELEMENT_NUMS; i++) {
210 EXPECT_EQ(copiedLong->Get(thread, i), JSTaggedValue::Hole());
211 }
212 }
213 } // namespace panda::test
214