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 #include "ecmascript/ts_types/ts_type.h"
16
17 #include "ecmascript/js_function.h"
18 #include "ecmascript/object_factory.h"
19 #include "ecmascript/property_attributes.h"
20
21 namespace panda::ecmascript {
IsEqual(JSHandle<TSUnionType> unionB)22 bool TSUnionType::IsEqual(JSHandle<TSUnionType> unionB)
23 {
24 DISALLOW_GARBAGE_COLLECTION;
25 ASSERT(unionB->GetComponents().IsTaggedArray());
26
27 TaggedArray *unionArrayA = TaggedArray::Cast(TSUnionType::GetComponents().GetTaggedObject());
28 TaggedArray *unionArrayB = TaggedArray::Cast(unionB->GetComponents().GetTaggedObject());
29 uint32_t unionALength = unionArrayA->GetLength();
30 uint32_t unionBLength = unionArrayB->GetLength();
31 if (unionALength != unionBLength) {
32 return false;
33 }
34 for (uint32_t unionAIndex = 0; unionAIndex < unionALength; unionAIndex++) {
35 int argUnionA = unionArrayA->Get(unionAIndex).GetNumber();
36 bool findArgTag = false;
37 for (uint32_t unionBIndex = 0; unionBIndex < unionBLength; unionBIndex++) {
38 int argUnionB = unionArrayB->Get(unionBIndex).GetNumber();
39 if (argUnionA == argUnionB) {
40 findArgTag = true;
41 break;
42 }
43 }
44 if (!findArgTag) {
45 return false;
46 }
47 }
48 return true;
49 }
50
GetPropTypeGT(JSThread * thread,JSHandle<TSClassType> classType,JSHandle<JSTaggedValue> propName)51 GlobalTSTypeRef TSClassType::GetPropTypeGT(JSThread *thread, JSHandle<TSClassType> classType,
52 JSHandle<JSTaggedValue> propName)
53 {
54 DISALLOW_GARBAGE_COLLECTION;
55 TSManager *tsManager = thread->GetCurrentEcmaContext()->GetTSManager();
56 JSMutableHandle<TSClassType> mutableClassType(thread, classType.GetTaggedValue());
57 JSMutableHandle<TSObjectType> mutableConstructorType(thread, mutableClassType->GetConstructorType());
58 GlobalTSTypeRef propTypeGT = GlobalTSTypeRef::Default();
59
60 while (propTypeGT.IsDefault()) { // not find
61 propTypeGT = TSObjectType::GetPropTypeGT(thread, mutableConstructorType, propName);
62 GlobalTSTypeRef classTypeGT = mutableClassType->GetExtensionGT();
63 if (classTypeGT.IsDefault()) { // end of prototype chain
64 break;
65 }
66
67 JSTaggedValue tmpType = tsManager->GetTSType(classTypeGT).GetTaggedValue();
68 if (tmpType.IsUndefined()) {
69 return GlobalTSTypeRef::Default();
70 }
71 mutableClassType.Update(tmpType);
72 mutableConstructorType.Update(mutableClassType->GetConstructorType());
73 }
74 return propTypeGT;
75 }
76
GetSuperPropTypeGT(JSThread * thread,JSHandle<TSClassType> classType,JSHandle<JSTaggedValue> propName,PropertyType propType)77 GlobalTSTypeRef TSClassType::GetSuperPropTypeGT(JSThread *thread, JSHandle<TSClassType> classType,
78 JSHandle<JSTaggedValue> propName, PropertyType propType)
79 {
80 DISALLOW_GARBAGE_COLLECTION;
81 TSManager *tsManager = thread->GetCurrentEcmaContext()->GetTSManager();
82 JSMutableHandle<TSClassType> mutableClassType(thread, classType.GetTaggedValue());
83 GlobalTSTypeRef propTypeGT = GlobalTSTypeRef::Default();
84 GlobalTSTypeRef notExistPropGt = kungfu::GateType::UndefinedType().GetGTRef();
85 GlobalTSTypeRef superClassTypeGT = mutableClassType->GetExtensionGT();
86 if (superClassTypeGT.IsDefault()) { // end of prototype chain
87 return notExistPropGt;
88 }
89 ASSERT(propType != PropertyType::OTHERS);
90 bool isStatic = propType == PropertyType::STATIC;
91 mutableClassType.Update(tsManager->GetTSType(superClassTypeGT).GetTaggedValue());
92 JSMutableHandle<TSObjectType> mutablePropTypes(thread, isStatic ?
93 mutableClassType->GetConstructorType() : mutableClassType->GetPrototypeType());
94 while (propTypeGT.IsDefault()) {
95 propTypeGT = TSObjectType::GetPropTypeGT(thread, mutablePropTypes, propName);
96 GlobalTSTypeRef classTypeGT = mutableClassType->GetExtensionGT();
97 if (classTypeGT.IsDefault()) { // end of prototype chain
98 break;
99 }
100 JSTaggedValue tmpType = tsManager->GetTSType(classTypeGT).GetTaggedValue();
101 if (tmpType.IsUndefined()) { // this is for builtin.d.abc
102 return GlobalTSTypeRef::Default();
103 }
104 mutableClassType.Update(tmpType);
105 mutablePropTypes.Update(isStatic ?
106 mutableClassType->GetConstructorType() : mutableClassType->GetPrototypeType());
107 }
108 return propTypeGT.IsDefault() ? notExistPropGt : propTypeGT;
109 }
110
GetNonStaticPropTypeGT(JSThread * thread,JSHandle<TSClassType> classType,JSHandle<JSTaggedValue> propName)111 GlobalTSTypeRef TSClassType::GetNonStaticPropTypeGT(JSThread *thread, JSHandle<TSClassType> classType,
112 JSHandle<JSTaggedValue> propName)
113 {
114 DISALLOW_GARBAGE_COLLECTION;
115 TSManager *tsManager = thread->GetCurrentEcmaContext()->GetTSManager();
116 JSHandle<TSObjectType> instanceType(thread, classType->GetInstanceType());
117 GlobalTSTypeRef propTypeGT = TSObjectType::GetPropTypeGT(thread, instanceType, propName);
118 if (!propTypeGT.IsDefault()) {
119 return propTypeGT;
120 }
121
122 // search on prototype chain
123 JSMutableHandle<TSClassType> mutableClassType(thread, classType.GetTaggedValue());
124 JSMutableHandle<TSObjectType> mutablePrototypeType(thread, classType->GetPrototypeType());
125 while (propTypeGT.IsDefault()) { // not find
126 propTypeGT = TSObjectType::GetPropTypeGT(thread, mutablePrototypeType, propName);
127 GlobalTSTypeRef classTypeGT = mutableClassType->GetExtensionGT();
128 if (classTypeGT.IsDefault()) { // end of prototype chain
129 break;
130 }
131
132 JSTaggedValue tmpType = tsManager->GetTSType(classTypeGT).GetTaggedValue();
133 if (tmpType.IsUndefined()) {
134 return GlobalTSTypeRef::Default();
135 }
136 mutableClassType.Update(tmpType);
137 mutablePrototypeType.Update(mutableClassType->GetPrototypeType());
138 }
139 return propTypeGT;
140 }
141
UpdateNonStaticPropTypeGT(JSThread * thread,JSHandle<TSClassType> classType,JSHandle<JSTaggedValue> propName,GlobalTSTypeRef newGT)142 void TSClassType::UpdateNonStaticPropTypeGT(JSThread *thread, JSHandle<TSClassType> classType,
143 JSHandle<JSTaggedValue> propName, GlobalTSTypeRef newGT)
144 {
145 DISALLOW_GARBAGE_COLLECTION;
146 JSHandle<TSObjectType> instanceType(thread, classType->GetInstanceType());
147 TSObjectType::UpdatePropTypeGT(thread, instanceType, propName, newGT);
148 }
149
UpdateStaticPropTypeGT(JSThread * thread,JSHandle<TSClassType> classType,JSHandle<JSTaggedValue> propName,GlobalTSTypeRef newGT)150 void TSClassType::UpdateStaticPropTypeGT(JSThread *thread, JSHandle<TSClassType> classType,
151 JSHandle<JSTaggedValue> propName, GlobalTSTypeRef newGT)
152 {
153 DISALLOW_GARBAGE_COLLECTION;
154 TSManager *tsManager = thread->GetCurrentEcmaContext()->GetTSManager();
155 JSMutableHandle<TSClassType> mutableClassType(thread, classType.GetTaggedValue());
156 JSMutableHandle<TSObjectType> mutableConstructorType(thread, mutableClassType->GetConstructorType());
157 bool hasUpdate = false;
158 while (!hasUpdate) {
159 hasUpdate = TSObjectType::UpdatePropTypeGT(thread, mutableConstructorType, propName, newGT);
160 GlobalTSTypeRef classTypeGT = mutableClassType->GetExtensionGT();
161 if (classTypeGT.IsDefault()) {
162 break;
163 }
164
165 JSTaggedValue tmpType = tsManager->GetTSType(classTypeGT).GetTaggedValue();
166 if (tmpType.IsUndefined()) {
167 break;
168 }
169 mutableClassType.Update(tmpType);
170 mutableConstructorType.Update(mutableClassType->GetConstructorType());
171 }
172 }
173
GetPropTypeGT(JSThread * thread,JSHandle<TSClassInstanceType> classInstanceType,JSHandle<JSTaggedValue> propName)174 GlobalTSTypeRef TSClassInstanceType::GetPropTypeGT(JSThread *thread, JSHandle<TSClassInstanceType> classInstanceType,
175 JSHandle<JSTaggedValue> propName)
176 {
177 DISALLOW_GARBAGE_COLLECTION;
178 TSManager *tsManager = thread->GetCurrentEcmaContext()->GetTSManager();
179 GlobalTSTypeRef classTypeGT = classInstanceType->GetClassGT();
180 JSHandle<JSTaggedValue> type = tsManager->GetTSType(classTypeGT);
181
182 if (type->IsUndefined()) {
183 return GlobalTSTypeRef::Default();
184 }
185
186 ASSERT(type->IsTSClassType());
187 JSHandle<TSClassType> classType(type);
188 GlobalTSTypeRef propTypeGT = TSClassType::GetNonStaticPropTypeGT(thread, classType, propName);
189 return propTypeGT;
190 }
191
GetIndexSignType(JSThread * thread,const JSHandle<TSClassInstanceType> & classInstanceType,const uint32_t typeId)192 GlobalTSTypeRef TSClassInstanceType::GetIndexSignType(JSThread *thread,
193 const JSHandle<TSClassInstanceType> &classInstanceType,
194 const uint32_t typeId)
195 {
196 DISALLOW_GARBAGE_COLLECTION;
197 TSManager *tsManager = thread->GetCurrentEcmaContext()->GetTSManager();
198 GlobalTSTypeRef classTypeGT = classInstanceType->GetClassGT();
199 JSHandle<JSTaggedValue> type = tsManager->GetTSType(classTypeGT);
200 // Es2abc no longer obeys that what is stored in classinstance types must be classtype,
201 // Retains the follwoing branch until they change it.
202 if (!type->IsTSClassType()) {
203 return GlobalTSTypeRef::Default();
204 }
205 JSHandle<TSClassType> classType(type);
206 if (classType->GetIndexSigns().IsUndefined()) {
207 return GlobalTSTypeRef::Default();
208 }
209
210 JSHandle<TSObjLayoutInfo> indexSignInfo(thread, classType->GetIndexSigns());
211 JSTaggedValue valueType = indexSignInfo->TryGetTypeByIndexSign(typeId);
212 if (valueType.IsInt()) {
213 return GlobalTSTypeRef(static_cast<uint32_t>(valueType.GetInt()));
214 }
215 return GlobalTSTypeRef::Default();
216 }
217
GetPropTypeGT(JSThread * thread,JSHandle<TSObjectType> objectType,JSHandle<JSTaggedValue> propName)218 GlobalTSTypeRef TSObjectType::GetPropTypeGT(JSThread *thread, JSHandle<TSObjectType> objectType,
219 JSHandle<JSTaggedValue> propName)
220 {
221 DISALLOW_GARBAGE_COLLECTION;
222 JSHandle<TSObjLayoutInfo> layout(thread, objectType->GetObjLayoutInfo().GetTaggedObject());
223 uint32_t numOfProps = layout->GetNumOfProperties();
224 JSMutableHandle<JSTaggedValue> propKey(thread, JSTaggedValue::Undefined());
225 for (uint32_t i = 0; i < numOfProps; ++i) {
226 propKey.Update(layout->GetKey(i));
227 if (!JSTaggedValue::Equal(thread, propName, propKey)) {
228 continue;
229 }
230 uint32_t gtRawData = static_cast<uint32_t>(layout->GetTypeId(i).GetInt());
231 return GlobalTSTypeRef(gtRawData);
232 }
233
234 return GlobalTSTypeRef::Default();
235 }
236
UpdatePropTypeGT(JSThread * thread,JSHandle<TSObjectType> objectType,JSHandle<JSTaggedValue> propName,GlobalTSTypeRef newGT)237 bool TSObjectType::UpdatePropTypeGT(JSThread *thread, JSHandle<TSObjectType> objectType,
238 JSHandle<JSTaggedValue> propName, GlobalTSTypeRef newGT)
239 {
240 DISALLOW_GARBAGE_COLLECTION;
241 JSHandle<TSObjLayoutInfo> layout(thread, objectType->GetObjLayoutInfo().GetTaggedObject());
242 int propIdx = layout->GetElementIndexByKey(propName.GetTaggedValue());
243 if (!TSObjLayoutInfo::IsValidIndex(propIdx)) {
244 return false;
245 }
246 uint32_t gtRawData = static_cast<uint32_t>(layout->GetTypeId(propIdx).GetInt());
247 if (GlobalTSTypeRef(gtRawData).IsDefault()) {
248 layout->SetTypeId(thread, propIdx, JSTaggedValue(newGT.GetType()));
249 return true;
250 }
251 return false;
252 }
253
GetIndexSignType(JSThread * thread,const JSHandle<TSObjectType> & objectType,const uint32_t typeId)254 GlobalTSTypeRef TSObjectType::GetIndexSignType(JSThread *thread, const JSHandle<TSObjectType> &objectType,
255 const uint32_t typeId)
256 {
257 if (objectType->GetIndexSigns().IsUndefined()) {
258 return GlobalTSTypeRef::Default();
259 }
260 DISALLOW_GARBAGE_COLLECTION;
261 JSHandle<TSObjLayoutInfo> indexSignInfo(thread, objectType->GetIndexSigns());
262 JSTaggedValue valueType = indexSignInfo->TryGetTypeByIndexSign(typeId);
263 if (valueType.IsInt()) {
264 return GlobalTSTypeRef(static_cast<uint32_t>(valueType.GetInt()));
265 }
266 return GlobalTSTypeRef::Default();
267 }
268
GetParameterTypeGT(int index) const269 GlobalTSTypeRef TSFunctionType::GetParameterTypeGT(int index) const
270 {
271 DISALLOW_GARBAGE_COLLECTION;
272 TaggedArray* functionParametersArray = TaggedArray::Cast(GetParameterTypes().GetTaggedObject());
273 JSTaggedValue parameterType = functionParametersArray->Get(index);
274 ASSERT(parameterType.IsInt());
275 uint32_t parameterGTRawData = parameterType.GetInt();
276 return GlobalTSTypeRef(parameterGTRawData);
277 }
278
GetPropTypeGT(JSThread * thread,JSHandle<TSIteratorInstanceType> iteratorInstanceType,JSHandle<JSTaggedValue> propName)279 GlobalTSTypeRef TSIteratorInstanceType::GetPropTypeGT(JSThread *thread,
280 JSHandle<TSIteratorInstanceType> iteratorInstanceType, JSHandle<JSTaggedValue> propName)
281 {
282 DISALLOW_GARBAGE_COLLECTION;
283 TSManager *tsManager = thread->GetCurrentEcmaContext()->GetTSManager();
284 GlobalTSTypeRef kindGt = iteratorInstanceType->GetKindGT();
285 GlobalTSTypeRef elementGt = iteratorInstanceType->GetElementGT();
286
287 JSHandle<JSTaggedValue> tsType = tsManager->GetTSType(kindGt);
288 JSHandle<TSObjectType> objType(tsType);
289 GlobalTSTypeRef propGt = TSObjectType::GetPropTypeGT(thread, objType, propName);
290 if (tsManager->IsTSIterator(kindGt)) {
291 GlobalTSTypeRef iteratorFunctionInstance =
292 tsManager->GetOrCreateTSIteratorInstanceType(static_cast<TSRuntimeType>(propGt.GetLocalId()), elementGt);
293 return iteratorFunctionInstance;
294 }
295
296 if (tsManager->IsTSIteratorResult(kindGt)) {
297 if (propGt.IsDefault()) {
298 #ifndef NDEBUG
299 ASSERT(propName->IsString());
300 JSHandle<JSTaggedValue> valueString = thread->GlobalConstants()->GetHandledValueString();
301 ASSERT(EcmaStringAccessor::StringsAreEqual(*JSHandle<EcmaString>::Cast(propName), EcmaString::Cast(
302 valueString.GetTaggedValue().GetTaggedObject())));
303 #endif
304 propGt = elementGt;
305 }
306 return propGt;
307 }
308 return GlobalTSTypeRef::Default();
309 }
310
GetPropTypeGT(JSThread * thread,JSHandle<TSInterfaceType> interfaceType,JSHandle<JSTaggedValue> propName)311 GlobalTSTypeRef TSInterfaceType::GetPropTypeGT(JSThread *thread, JSHandle<TSInterfaceType> interfaceType,
312 JSHandle<JSTaggedValue> propName)
313 {
314 DISALLOW_GARBAGE_COLLECTION;
315 TSManager *tsManager = thread->GetCurrentEcmaContext()->GetTSManager();
316
317 JSMutableHandle<TSInterfaceType> mutableInterfaceType(thread, interfaceType.GetTaggedValue());
318 JSMutableHandle<TSObjectType> mutableFieldsType(thread, mutableInterfaceType->GetFields());
319 GlobalTSTypeRef propTypeGT = GlobalTSTypeRef::Default();
320 propTypeGT = TSObjectType::GetPropTypeGT(thread, mutableFieldsType, propName);
321
322 TaggedArray* extendsArray = TaggedArray::Cast(mutableInterfaceType->GetExtends().GetTaggedObject());
323 uint32_t extendsLength = extendsArray->GetLength();
324
325 for (uint32_t index = 0; index < extendsLength; index++) {
326 if (!propTypeGT.IsDefault()) {
327 return propTypeGT;
328 }
329
330 JSTaggedValue extendsValue = extendsArray->Get(index);
331 ASSERT(extendsValue.IsInt());
332 uint32_t gtRawData = static_cast<uint32_t>(extendsValue.GetInt());
333 GlobalTSTypeRef extendsGT = GlobalTSTypeRef(gtRawData);
334 JSHandle<JSTaggedValue> extendsType = tsManager->GetTSType(extendsGT);
335 if (extendsType->IsUndefined()) {
336 return GlobalTSTypeRef::Default();
337 }
338 ASSERT(extendsType->IsTSType());
339
340 if (extendsType->IsTSClassType()) {
341 JSHandle<TSClassType> innerClassType(extendsType);
342 propTypeGT = TSClassType::GetNonStaticPropTypeGT(thread, innerClassType, propName);
343 } else if (extendsType->IsTSInterfaceType()) {
344 JSHandle<TSInterfaceType> extendsInterfaceType(extendsType);
345 propTypeGT = TSInterfaceType::GetPropTypeGT(thread, extendsInterfaceType, propName);
346 }
347 }
348
349 return propTypeGT;
350 }
351
GetIndexSignType(JSThread * thread,const JSHandle<TSInterfaceType> & interfaceType,const uint32_t typeId)352 GlobalTSTypeRef TSInterfaceType::GetIndexSignType(JSThread *thread, const JSHandle<TSInterfaceType> &interfaceType,
353 const uint32_t typeId)
354 {
355 if (interfaceType->GetIndexSigns().IsUndefined()) {
356 return GlobalTSTypeRef::Default();
357 }
358 DISALLOW_GARBAGE_COLLECTION;
359 JSHandle<TSObjLayoutInfo> indexSignInfo(thread, interfaceType->GetIndexSigns());
360 JSTaggedValue valueType = indexSignInfo->TryGetTypeByIndexSign(typeId);
361 if (valueType.IsInt()) {
362 return GlobalTSTypeRef(static_cast<uint32_t>(valueType.GetInt()));
363 }
364 return GlobalTSTypeRef::Default();
365 }
366
367
AddKeyAndValue(const JSThread * thread,const JSHandle<TSNamespaceType> & namespaceType,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value)368 void TSNamespaceType::AddKeyAndValue(const JSThread *thread, const JSHandle<TSNamespaceType> &namespaceType,
369 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value)
370 {
371 JSHandle<TSObjLayoutInfo> propLayout(thread, namespaceType->GetPropertyType());
372 if (propLayout->Find(key.GetTaggedValue())) {
373 return;
374 }
375 JSHandle<TSObjLayoutInfo> newPropLayout = TSObjLayoutInfo::PushBack(thread, propLayout, key, value);
376 namespaceType->SetPropertyType(thread, newPropLayout.GetTaggedValue());
377 }
378
GetPropTypeGT(JSThread * thread,const JSHandle<TSNamespaceType> & namespaceType,const JSHandle<JSTaggedValue> & propName)379 GlobalTSTypeRef TSNamespaceType::GetPropTypeGT(JSThread *thread, const JSHandle<TSNamespaceType> &namespaceType,
380 const JSHandle<JSTaggedValue> &propName)
381 {
382 DISALLOW_GARBAGE_COLLECTION;
383 if (namespaceType->GetPropertyType().IsUndefined()) {
384 return GlobalTSTypeRef::Default();
385 }
386
387 JSHandle<JSTaggedValue> properties(thread, namespaceType->GetPropertyType());
388
389 if (properties->IsUndefined()) {
390 return GlobalTSTypeRef::Default();
391 }
392
393 JSHandle<TSObjLayoutInfo> layout(thread, namespaceType->GetPropertyType().GetTaggedObject());
394 uint32_t numOfProps = layout->GetNumOfProperties();
395 JSMutableHandle<JSTaggedValue> propKey(thread, JSTaggedValue::Undefined());
396 for (uint32_t i = 0; i < numOfProps; ++i) {
397 propKey.Update(layout->GetKey(i));
398 if (!JSTaggedValue::Equal(thread, propName, propKey)) {
399 continue;
400 }
401 uint32_t gtRawData = static_cast<uint32_t>(layout->GetTypeId(i).GetInt());
402 return GlobalTSTypeRef(gtRawData);
403 }
404 return GlobalTSTypeRef::Default();
405 }
406 } // namespace panda::ecmascript
407