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