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,NewAndCopyTaggedArray)188 HWTEST_F_L0(ObjectFactoryTest, NewAndCopyTaggedArray)
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 for (uint32_t i = 0; i < SHORT_ELEMENT_NUMS; i++) {
196 shortTaggedarray->Set(thread, i, JSTaggedValue(i));
197 }
198 JSHandle<TaggedArray> copiedShort = factory->NewAndCopyTaggedArray(shortTaggedarray, SHORT_ELEMENT_NUMS,
199 SHORT_ELEMENT_NUMS);
200 JSHandle<TaggedArray> copiedLong = factory->NewAndCopyTaggedArray(shortTaggedarray, LONG_ELEMENT_NUMS,
201 SHORT_ELEMENT_NUMS);
202 // check
203 for (uint32_t i = 0; i < SHORT_ELEMENT_NUMS; i++) {
204 EXPECT_EQ(copiedShort->Get(thread, i), shortTaggedarray->Get(thread, i));
205 EXPECT_EQ(copiedLong->Get(thread, i), shortTaggedarray->Get(thread, i));
206 }
207 for (uint32_t i = SHORT_ELEMENT_NUMS; i < LONG_ELEMENT_NUMS; i++) {
208 EXPECT_EQ(copiedLong->Get(thread, i), JSTaggedValue::Hole());
209 }
210 }
211 } // namespace panda::test
212