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