• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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/global_env.h"
17 #include "ecmascript/accessor_data.h"
18 #include "ecmascript/object_factory.h"
19 #include "ecmascript/object_operator.h"
20 #include "ecmascript/tests/test_helper.h"
21 
22 using namespace panda::ecmascript;
23 
24 namespace panda::test {
25 class AccessorDataTest : public testing::Test {
26 public:
SetUpTestCase()27     static void SetUpTestCase()
28     {
29         GTEST_LOG_(INFO) << "SetUpTestCase";
30     }
31 
TearDownTestCase()32     static void TearDownTestCase()
33     {
34         GTEST_LOG_(INFO) << "TearDownCase";
35     }
36 
SetUp()37     void SetUp() override
38     {
39         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
40     }
41 
TearDown()42     void TearDown() override
43     {
44         TestHelper::DestroyEcmaVMWithScope(instance, scope);
45     }
46 
47     EcmaVM *instance {nullptr};
48     EcmaHandleScope *scope {nullptr};
49     JSThread *thread {nullptr};
50 };
51 
52 /**
53  * @tc.name: Cast
54  * @tc.desc: Convert an object of type TaggedObject to type AccessorData object.
55  * @tc.type: FUNC
56  * @tc.require:
57  */
HWTEST_F_L0(AccessorDataTest,AccessorData_Cast)58 HWTEST_F_L0(AccessorDataTest, AccessorData_Cast)
59 {
60     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
61     JSHandle<JSTaggedValue> nullHandle(thread, JSTaggedValue::Null());
62 
63     JSHandle<JSHClass> accClassHandle =
64         factory->NewEcmaHClass(JSObject::SIZE, JSType::ACCESSOR_DATA, nullHandle);
65     TaggedObject *accObject = factory->NewObject(accClassHandle);
66     AccessorData::Cast(accObject)->SetGetter(thread, JSTaggedValue::Undefined());
67     AccessorData::Cast(accObject)->SetSetter(thread, JSTaggedValue::Undefined());
68     EXPECT_TRUE(JSTaggedValue(accObject).IsAccessorData());
69     AccessorData *acc = AccessorData::Cast(accObject);
70     EXPECT_TRUE(JSTaggedValue(acc).IsAccessorData());
71 
72     JSHandle<JSHClass> internalAccClassHandle =
73         factory->NewEcmaHClass(JSObject::SIZE, JSType::INTERNAL_ACCESSOR, nullHandle);
74     TaggedObject *internalAccObject = factory->NewObject(internalAccClassHandle);
75     EXPECT_TRUE(JSTaggedValue(internalAccObject).IsInternalAccessor());
76     AccessorData *internalAcc = AccessorData::Cast(internalAccObject);
77     EXPECT_TRUE(JSTaggedValue(internalAcc).IsInternalAccessor());
78 }
79 
80 /**
81  * @tc.name: IsInternal
82  * @tc.desc: Judge whether the accessor is internal.
83  * @tc.type: FUNC
84  * @tc.require:
85  */
HWTEST_F_L0(AccessorDataTest,IsInternal)86 HWTEST_F_L0(AccessorDataTest, IsInternal)
87 {
88     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
89     JSHandle<AccessorData> accHandle = factory->NewAccessorData();
90     EXPECT_EQ(accHandle->IsInternal(), false);
91 
92     void *setter = nullptr;
93     void *getter = nullptr;
94     JSHandle<AccessorData> internalAccHancle = factory->NewInternalAccessor(setter, getter);
95     EXPECT_EQ(internalAccHancle->IsInternal(), true);
96 
97     JSHandle<JSTaggedValue> nullHandle(thread, JSTaggedValue::Null());
98     JSHandle<JSHClass> accClass = factory->NewEcmaHClass(JSObject::SIZE, JSType::ACCESSOR_DATA, nullHandle);
99     TaggedObject *accObject = factory->NewObject(accClass);
100     AccessorData *acc = AccessorData::Cast(accObject);
101     acc->SetGetter(thread, JSTaggedValue::Undefined());
102     acc->SetSetter(thread, JSTaggedValue::Undefined());
103     EXPECT_EQ(acc->IsInternal(), false);
104 
105     JSHandle<JSHClass> internalAccClass =
106         factory->NewEcmaHClass(JSObject::SIZE, JSType::INTERNAL_ACCESSOR, nullHandle);
107     TaggedObject *internalAccObject = factory->NewObject(internalAccClass);
108     AccessorData *internalAcc = AccessorData::Cast(internalAccObject);
109     EXPECT_EQ(internalAcc->IsInternal(), true);
110 }
111 
112 /**
113  * @tc.name: HasSetter
114  * @tc.desc: Judge whether the accessor have a undefined type "Setter".
115  * @tc.type: FUNC
116  * @tc.require:
117  */
HWTEST_F_L0(AccessorDataTest,HasSetter)118 HWTEST_F_L0(AccessorDataTest, HasSetter)
119 {
120     JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
121     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
122     JSHandle<JSTaggedValue> normalFunction = globalEnv->GetNormalFunctionClass();
123 
124     // 1.Create normal AccessorData object by NewAccessorData function.
125     JSHandle<AccessorData> accHandle = factory->NewAccessorData();
126     EXPECT_EQ(accHandle->HasSetter(), false);
127     accHandle->SetSetter(thread, JSTaggedValue::Undefined());
128     EXPECT_EQ(accHandle->HasSetter(), false);
129     accHandle->SetSetter(thread, normalFunction);
130     EXPECT_EQ(accHandle->HasSetter(), true);
131 
132     // 2.Create internal AccessorData object by NewInternalAccessor function.
133     void *setter = nullptr;
134     void *getter = nullptr;
135     JSHandle<AccessorData> internalAccHandle = factory->NewInternalAccessor(setter, getter);
136     EXPECT_EQ(internalAccHandle->HasSetter(), false);
137     internalAccHandle->SetSetter(thread, JSTaggedValue::Undefined());
138     EXPECT_EQ(internalAccHandle->HasSetter(), false);
139     internalAccHandle->SetSetter(thread, normalFunction);
140     EXPECT_EQ(internalAccHandle->HasSetter(), true);
141 
142     // 3.Create normal AccessorData object from dynamic class.
143     JSHandle<JSTaggedValue> nullHandle(thread, JSTaggedValue::Null());
144     JSHandle<JSHClass> accClass = factory->NewEcmaHClass(JSObject::SIZE, JSType::ACCESSOR_DATA, nullHandle);
145     TaggedObject *accObject = factory->NewObject(accClass);
146     AccessorData *acc = AccessorData::Cast(accObject);
147     acc->SetGetter(thread, JSTaggedValue::Undefined());
148     EXPECT_EQ(acc->HasSetter(), true);
149     acc->SetSetter(thread, JSTaggedValue::Undefined());
150     EXPECT_EQ(acc->HasSetter(), false);
151     acc->SetSetter(thread, normalFunction);
152     EXPECT_EQ(acc->HasSetter(), true);
153 
154     // 4.Create internal AccessorData object from dynamic class.
155     JSHandle<JSHClass> internalAccClass =
156         factory->NewEcmaHClass(JSObject::SIZE, JSType::INTERNAL_ACCESSOR, nullHandle);
157     TaggedObject *internalAccObject = factory->NewObject(internalAccClass);
158     AccessorData *internalAcc = AccessorData::Cast(internalAccObject);
159     EXPECT_EQ(internalAcc->HasSetter(), true);
160     internalAcc->SetSetter(thread, JSTaggedValue::Undefined());
161     EXPECT_EQ(internalAcc->HasSetter(), false);
162     internalAcc->SetSetter(thread, normalFunction);
163     EXPECT_EQ(internalAcc->HasSetter(), true);
164 }
165 
166 /**
167  * @tc.name: CallInternalSet/CallInternalGet
168  * @tc.desc: Call internal set & get function to set object prototype.
169  * @tc.type: FUNC
170  * @tc.require:
171  */
HWTEST_F_L0(AccessorDataTest,CallInternalSet)172 HWTEST_F_L0(AccessorDataTest, CallInternalSet)
173 {
174     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
175     JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
176 
177     // Construct objects and specify specific prototypes.
178     JSFunction *func1 = globalEnv->GetObjectFunction().GetObject<JSFunction>();
179     Method::Cast(func1->GetMethod().GetTaggedObject())->SetFunctionKind(FunctionKind::BASE_CONSTRUCTOR);
180     JSHandle<JSFunction> funcTagVal1 =
181         factory->CloneJSFuction(JSHandle<JSFunction>(thread, func1));
182 
183     // Call the CallInternalGet method to inspect prototype.
184     JSHandle<JSTaggedValue> nullPrototypeHandle(thread, JSTaggedValue::Null());
185     JSHandle<JSHClass> accClass1 =
186         factory->NewEcmaHClass(JSObject::SIZE, JSType::INTERNAL_ACCESSOR, nullPrototypeHandle);
187     JSHandle<AccessorData> accObject1(thread, factory->NewObject(accClass1));
188     accObject1->SetGetter(thread, JSTaggedValue::Undefined());
189     accObject1->SetSetter(thread, JSTaggedValue::Undefined());
190     JSHandle<JSNativePointer> prototypeGetterFuncNativePtrHandle =
191         factory->NewJSNativePointer(reinterpret_cast<void *>(JSFunction::PrototypeGetter), nullptr, nullptr, true);
192     accObject1->SetGetter(thread, prototypeGetterFuncNativePtrHandle);
193 
194     JSTaggedValue valNullPrototype = accObject1->CallInternalGet(thread, JSHandle<JSObject>::Cast(funcTagVal1));
195     EXPECT_NE(valNullPrototype.GetRawData(), JSTaggedValue::Undefined().GetRawData());
196 
197     // Call the CallInternalSet method to set new prototype.
198     JSHandle<JSTaggedValue> undefPrototypeHandle(thread, JSTaggedValue::Undefined());
199     JSHandle<JSNativePointer> prototypeSetterFuncNativePtrHandle =
200         factory->NewJSNativePointer(reinterpret_cast<void *>(JSFunction::PrototypeSetter), nullptr, nullptr, true);
201     accObject1->SetSetter(thread, prototypeSetterFuncNativePtrHandle);
202     bool res1 = accObject1->CallInternalSet(thread, JSHandle<JSObject>::Cast(funcTagVal1), undefPrototypeHandle);
203     EXPECT_TRUE(res1);
204 
205     // Call the CallInternalGet method to check the changed prototype.
206     valNullPrototype = accObject1->CallInternalGet(thread, JSHandle<JSObject>::Cast(funcTagVal1));
207     EXPECT_EQ(valNullPrototype.GetRawData(), JSTaggedValue::Undefined().GetRawData());
208 }
209 
210 /**
211  * @tc.name: Cast
212  * @tc.desc: Convert an object of type TaggedObject to type CompletionRecord object.
213  * @tc.type: FUNC
214  * @tc.require:
215  */
HWTEST_F_L0(AccessorDataTest,CompletionRecord_Cast)216 HWTEST_F_L0(AccessorDataTest, CompletionRecord_Cast)
217 {
218     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
219     JSHandle<JSTaggedValue> nullHandle(thread, JSTaggedValue::Null());
220 
221     JSHandle<JSHClass> comRecordClassHandle =
222         factory->NewEcmaHClass(JSObject::SIZE, JSType::COMPLETION_RECORD, nullHandle);
223     TaggedObject *comRecordObject = factory->NewObject(comRecordClassHandle);
224     EXPECT_TRUE(JSTaggedValue(comRecordObject).IsCompletionRecord());
225     CompletionRecord *comRecord = CompletionRecord::Cast(comRecordObject);
226     EXPECT_TRUE(JSTaggedValue(comRecord).IsCompletionRecord());
227 }
228 
229 /**
230  * @tc.name: IsThrow
231  * @tc.desc: Judge whether the completion record is THROW type.
232  * @tc.type: FUNC
233  * @tc.require:
234  */
HWTEST_F_L0(AccessorDataTest,IsThrow)235 HWTEST_F_L0(AccessorDataTest, IsThrow)
236 {
237     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
238     JSHandle<JSTaggedValue> exceptionHandle(thread, thread->GetException());
239 
240     JSHandle<CompletionRecord> normalComRecHandle =
241         factory->NewCompletionRecord(CompletionRecordType::NORMAL, exceptionHandle);
242     EXPECT_TRUE(!normalComRecHandle->IsThrow());
243 
244     JSHandle<CompletionRecord> throwComRecHandle =
245         factory->NewCompletionRecord(CompletionRecordType::THROW, exceptionHandle);
246     EXPECT_TRUE(throwComRecHandle->IsThrow());
247 }
248 }  // namespace panda::test
249