• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 testing::Test {
36 public:
SetUpTestCase()37     static void SetUpTestCase()
38     {
39         GTEST_LOG_(INFO) << "SetUpTestCase";
40     }
41 
TearDownTestCase()42     static void TearDownTestCase()
43     {
44         GTEST_LOG_(INFO) << "TearDownCase";
45     }
46 
SetUp()47     void SetUp() override
48     {
49         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
50     }
51 
TearDown()52     void TearDown() override
53     {
54         TestHelper::DestroyEcmaVMWithScope(instance, scope);
55     }
56 
57     EcmaVM *instance {nullptr};
58     ecmascript::EcmaHandleScope *scope {nullptr};
59     JSThread *thread {nullptr};
60 };
61 
GetGlobal(JSThread * thread)62 JSHandle<GlobalEnv> GetGlobal(JSThread *thread)
63 {
64     return thread->GetEcmaVM()->GetGlobalEnv();
65 }
66 
HWTEST_F_L0(ObjectFactoryTest,NewJSObjectByConstructor)67 HWTEST_F_L0(ObjectFactoryTest, NewJSObjectByConstructor)
68 {
69     thread->GetEcmaVM()->SetEnableForceGC(false);
70     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
71     JSHandle<JSTaggedValue> objFun = GetGlobal(thread)->GetObjectFunction();
72 
73     // check mem alloc
74     JSHandle<JSObject> newObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
75     JSHandle<JSHClass> newObjCls(thread, newObj->GetJSHClass());
76     EXPECT_TRUE(*newObj != nullptr);
77     EXPECT_TRUE(*newObjCls != nullptr);
78 
79     // check feild
80     EXPECT_EQ(newObj->GetProperties(), thread->GlobalConstants()->GetEmptyArray());
81     EXPECT_EQ(newObj->GetElements(), thread->GlobalConstants()->GetEmptyArray());
82     EXPECT_TRUE(JSTaggedValue(*newObj).IsECMAObject());
83 
84     // check jshclass
85     JSHClass *cls = *newObjCls;
86     EXPECT_TRUE(cls->GetObjectSize() ==
87                 JSObject::SIZE + JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS * JSTaggedValue::TaggedTypeSize());
88     EXPECT_TRUE(cls->GetPrototype() == GetGlobal(thread)->GetObjectFunctionPrototype().GetTaggedValue());
89     EXPECT_TRUE(cls->GetObjectType() == JSType::JS_OBJECT);
90 
91     // check gc handle update
92     auto *prototype = cls->GetPrototype().GetTaggedObject();
93     thread->GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC);
94     // After FullGC
95     if (thread->GetEcmaVM()->GetJSOptions().EnableSnapshotDeserialize()) {
96         EXPECT_TRUE(prototype == newObjCls->GetPrototype().GetTaggedObject());
97     } else {
98         EXPECT_TRUE(prototype != newObjCls->GetPrototype().GetTaggedObject());
99     }
100     thread->GetEcmaVM()->SetEnableForceGC(true);
101 }
102 
HWTEST_F_L0(ObjectFactoryTest,NewJSFunction)103 HWTEST_F_L0(ObjectFactoryTest, NewJSFunction)
104 {
105     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
106     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
107 
108     // check mem alloc
109     JSHandle<JSFunction> newFun = factory->NewJSFunction(env);
110     JSHandle<JSHClass> newFunCls(thread, newFun->GetJSHClass());
111     EXPECT_TRUE(*newFun != nullptr);
112     EXPECT_TRUE(*newFunCls != nullptr);
113 
114     // check feild
115     EXPECT_EQ(newFun->GetProperties(), thread->GlobalConstants()->GetEmptyArray());
116     EXPECT_EQ(newFun->GetElements(), thread->GlobalConstants()->GetEmptyArray());
117     EXPECT_EQ(newFun->GetProtoOrHClass(), JSTaggedValue::Hole());
118     EXPECT_EQ(newFun->GetHomeObject(), JSTaggedValue::Undefined());
119     EXPECT_TRUE(JSTaggedValue(*newFun).IsJSFunction());
120 
121     // check jshclass
122     JSHClass *cls = *newFunCls;
123     EXPECT_TRUE(cls->GetObjectSize() ==
124                 JSFunction::SIZE + JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS * JSTaggedValue::TaggedTypeSize());
125     EXPECT_TRUE(cls->GetPrototype() == GetGlobal(thread)->GetFunctionPrototype().GetTaggedValue());
126     EXPECT_TRUE(cls->GetObjectType() == JSType::JS_FUNCTION);
127     EXPECT_TRUE(cls->IsCallable());
128     EXPECT_TRUE(cls->IsExtensible());
129     EXPECT_TRUE(!cls->IsConstructor());
130 }
131 
HWTEST_F_L0(ObjectFactoryTest,NewJSBoundFunction)132 HWTEST_F_L0(ObjectFactoryTest, NewJSBoundFunction)
133 {
134     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
135 
136     // test prepare
137     JSHandle<JSFunction> funFun(GetGlobal(thread)->GetObjectFunction());
138     JSHandle<JSTaggedValue> bound(thread, GetGlobal(thread)->GetObjectFunctionPrototype().GetTaggedValue());
139     const JSHandle<TaggedArray> array(thread->GlobalConstants()->GetHandledEmptyArray());
140 
141     // check mem alloc
142     JSHandle<JSFunctionBase> targetFunc(funFun);
143     JSHandle<JSBoundFunction> newBoundFun = factory->NewJSBoundFunction(targetFunc, bound, array);
144     JSHandle<JSHClass> newBoundFunCls(thread, newBoundFun->GetJSHClass());
145     EXPECT_TRUE(*newBoundFun != nullptr);
146     EXPECT_TRUE(*newBoundFunCls != nullptr);
147 }
148 
HWTEST_F_L0(ObjectFactoryTest,NewJSPrimitiveRef)149 HWTEST_F_L0(ObjectFactoryTest, NewJSPrimitiveRef)
150 {
151     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
152 
153     // test prepare
154     JSHandle<JSFunction> numberFun(GetGlobal(thread)->GetNumberFunction());
155     JSHandle<JSTaggedValue> primitive(thread, JSTaggedValue(1));
156 
157     // check mem alloc
158     JSHandle<JSPrimitiveRef> newPrimitive = factory->NewJSPrimitiveRef(numberFun, primitive);
159     JSHandle<JSHClass> newPrimitiveCls(thread, newPrimitive->GetJSHClass());
160     EXPECT_TRUE(*newPrimitive != nullptr);
161     EXPECT_TRUE(*newPrimitiveCls != nullptr);
162 
163     EXPECT_TRUE(newPrimitive->GetValue() == JSTaggedValue(1));
164 }
165 
HWTEST_F_L0(ObjectFactoryTest,NewLexicalEnv)166 HWTEST_F_L0(ObjectFactoryTest, NewLexicalEnv)
167 {
168     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
169 
170     // check mem alloc
171     JSHandle<LexicalEnv> newLexicalEnv = factory->NewLexicalEnv(0);
172     JSHandle<JSHClass> newLexicalEnvCls(thread, newLexicalEnv->GetClass());
173     EXPECT_TRUE(*newLexicalEnv != nullptr);
174     EXPECT_TRUE(*newLexicalEnvCls != nullptr);
175 }
176 
HWTEST_F_L0(ObjectFactoryTest,NewJSArray)177 HWTEST_F_L0(ObjectFactoryTest, NewJSArray)
178 {
179     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
180 
181     // check mem alloc
182     JSHandle<JSArray> newJSAarray = factory->NewJSArray();
183     JSHandle<JSHClass> newJSArrayCls(thread, newJSAarray->GetJSHClass());
184     EXPECT_TRUE(*newJSAarray != nullptr);
185     EXPECT_TRUE(*newJSArrayCls != nullptr);
186 }
187 
HWTEST_F_L0(ObjectFactoryTest,RemoveElementByIndex)188 HWTEST_F_L0(ObjectFactoryTest, RemoveElementByIndex)
189 {
190     constexpr uint32_t ELEMENT_NUMS = 20;
191     constexpr uint32_t REMOVE_INDEX = 0;
192     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
193     JSHandle<TaggedArray> semiTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS, JSTaggedValue::Hole(),
194                                                                     MemSpaceType::SEMI_SPACE);
195     JSHandle<TaggedArray> oldTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS, JSTaggedValue::Hole(),
196                                                                    MemSpaceType::OLD_SPACE);
197     // init tagggedArray
198     for (uint32_t i = 0; i < ELEMENT_NUMS; i++) {
199         semiTaggedarray->Set(thread, i, JSTaggedValue(i));
200         oldTaggedarray->Set(thread, i, JSTaggedValue(i));
201     }
202     factory->RemoveElementByIndex(semiTaggedarray, REMOVE_INDEX, ELEMENT_NUMS);
203     factory->RemoveElementByIndex(oldTaggedarray, REMOVE_INDEX, ELEMENT_NUMS);
204 
205     for (uint32_t i = 0; i < ELEMENT_NUMS - 1; i++) {
206         EXPECT_EQ(semiTaggedarray->Get(thread, i), JSTaggedValue(i + 1));
207         EXPECT_EQ(oldTaggedarray->Get(thread, i), JSTaggedValue(i + 1));
208     }
209     EXPECT_EQ(semiTaggedarray->Get(thread, ELEMENT_NUMS - 1), JSTaggedValue::Hole());
210     EXPECT_EQ(oldTaggedarray->Get(thread, ELEMENT_NUMS - 1), JSTaggedValue::Hole());
211 }
212 
HWTEST_F_L0(ObjectFactoryTest,InsertElementByIndex)213 HWTEST_F_L0(ObjectFactoryTest, InsertElementByIndex)
214 {
215     constexpr uint32_t ELEMENT_NUMS = 20;
216     constexpr uint32_t INSERT_INDEX = 0;
217     JSHandle<JSTaggedValue> insertValue(thread, JSTaggedValue(ELEMENT_NUMS));
218     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
219     JSHandle<TaggedArray> semiTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS, JSTaggedValue::Hole(),
220                                                                     MemSpaceType::SEMI_SPACE);
221     JSHandle<TaggedArray> oldTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS, JSTaggedValue::Hole(),
222                                                                    MemSpaceType::OLD_SPACE);
223     // init tagggedArray
224     for (uint32_t i = 0; i < ELEMENT_NUMS - 1; i++) {
225         semiTaggedarray->Set(thread, i, JSTaggedValue(i));
226         oldTaggedarray->Set(thread, i, JSTaggedValue(i));
227     }
228     factory->InsertElementByIndex(semiTaggedarray, insertValue, INSERT_INDEX, ELEMENT_NUMS - 1);
229     factory->InsertElementByIndex(oldTaggedarray, insertValue, INSERT_INDEX, ELEMENT_NUMS - 1);
230     // check
231     EXPECT_EQ(semiTaggedarray->Get(thread, 0), insertValue.GetTaggedValue());
232     EXPECT_EQ(oldTaggedarray->Get(thread, 0), insertValue.GetTaggedValue());
233     for (uint32_t i = 1; i < ELEMENT_NUMS; i++) {
234         EXPECT_EQ(semiTaggedarray->Get(thread, i), JSTaggedValue(i - 1));
235         EXPECT_EQ(oldTaggedarray->Get(thread, i), JSTaggedValue(i - 1));
236     }
237 }
238 
HWTEST_F_L0(ObjectFactoryTest,NewAndCopyTaggedArray)239 HWTEST_F_L0(ObjectFactoryTest, NewAndCopyTaggedArray)
240 {
241     constexpr uint32_t SHORT_ELEMENT_NUMS = 20;
242     constexpr uint32_t LONG_ELEMENT_NUMS = 100;
243     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
244     JSHandle<TaggedArray> shortTaggedarray = factory->NewTaggedArray(SHORT_ELEMENT_NUMS);
245     // init tagggedArray
246     for (uint32_t i = 0; i < SHORT_ELEMENT_NUMS; i++) {
247         shortTaggedarray->Set(thread, i, JSTaggedValue(i));
248     }
249     JSHandle<TaggedArray> copiedShort = factory->NewAndCopyTaggedArray(shortTaggedarray, SHORT_ELEMENT_NUMS,
250                                                                        SHORT_ELEMENT_NUMS);
251     JSHandle<TaggedArray> copiedLong = factory->NewAndCopyTaggedArray(shortTaggedarray, LONG_ELEMENT_NUMS,
252                                                                        SHORT_ELEMENT_NUMS);
253     // check
254     for (uint32_t i = 0; i < SHORT_ELEMENT_NUMS; i++) {
255         EXPECT_EQ(copiedShort->Get(thread, i), shortTaggedarray->Get(thread, i));
256         EXPECT_EQ(copiedLong->Get(thread, i), shortTaggedarray->Get(thread, i));
257     }
258     for (uint32_t i = SHORT_ELEMENT_NUMS; i < LONG_ELEMENT_NUMS; i++) {
259         EXPECT_EQ(copiedLong->Get(thread, i), JSTaggedValue::Hole());
260     }
261 }
262 
HWTEST_F_L0(ObjectFactoryTest,CopyTaggedArrayElement)263 HWTEST_F_L0(ObjectFactoryTest, CopyTaggedArrayElement)
264 {
265     constexpr uint32_t ELEMENT_NUMS = 20;
266     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
267     JSHandle<TaggedArray> srcSemiTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS, JSTaggedValue::Hole(),
268                                                                        MemSpaceType::SEMI_SPACE);
269     JSHandle<TaggedArray> srcOldTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS, JSTaggedValue::Hole(),
270                                                                       MemSpaceType::OLD_SPACE);
271     JSHandle<TaggedArray> dstSemiTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS);
272     JSHandle<TaggedArray> dstOldTaggedarray = factory->NewTaggedArray(ELEMENT_NUMS);
273     // init tagggedArray
274     for (uint32_t i = 0; i < ELEMENT_NUMS; i++) {
275         srcSemiTaggedarray->Set(thread, i, JSTaggedValue(i));
276         srcOldTaggedarray->Set(thread, i, JSTaggedValue(i));
277         dstSemiTaggedarray->Set(thread, i, JSTaggedValue(-i));
278         dstOldTaggedarray->Set(thread, i, JSTaggedValue(-i));
279     }
280     factory->CopyTaggedArrayElement(srcSemiTaggedarray, dstSemiTaggedarray, ELEMENT_NUMS);
281     factory->CopyTaggedArrayElement(srcOldTaggedarray, dstOldTaggedarray, ELEMENT_NUMS);
282 
283     for (uint32_t i = 0; i < ELEMENT_NUMS; i++) {
284         EXPECT_EQ(srcSemiTaggedarray->Get(thread, i), dstSemiTaggedarray->Get(thread, i));
285         EXPECT_EQ(srcOldTaggedarray->Get(thread, i), dstOldTaggedarray->Get(thread, i));
286     }
287 }
288 }  // namespace panda::test
289