• 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/ts_types/ts_type_parser.h"
17 
18 #include "ecmascript/base/path_helper.h"
19 #include "ecmascript/jspandafile/js_pandafile_manager.h"
20 #include "ecmascript/jspandafile/literal_data_extractor.h"
21 #include "ecmascript/module/js_module_manager.h"
22 
23 #include "libpandafile/annotation_data_accessor.h"
24 #include "libpandafile/class_data_accessor-inl.h"
25 
26 namespace panda::ecmascript {
CreateGT(const JSPandaFile * jsPandaFile,const CString & recordName,uint32_t typeId)27 GlobalTSTypeRef TSTypeParser::CreateGT(const JSPandaFile *jsPandaFile, const CString &recordName, uint32_t typeId)
28 {
29     if (typeId <= BUILDIN_TYPE_OFFSET) {
30         return GlobalTSTypeRef(TSModuleTable::PRIMITIVE_TABLE_ID, typeId);
31     }
32 
33     if (typeId <= USER_DEFINED_TYPE_OFFSET) {
34         return ParseBuiltinObjType(typeId);
35     }
36 
37     if (tsManager_->HasCreatedGT(jsPandaFile, typeId)) {
38         return tsManager_->GetGTFromOffset(jsPandaFile, typeId);
39     }
40     return ParseType(jsPandaFile, recordName, typeId);
41 }
42 
ParseBuiltinObjType(uint32_t typeId)43 GlobalTSTypeRef TSTypeParser::ParseBuiltinObjType(uint32_t typeId)
44 {
45     if (!tsManager_->IsBuiltinsDTSEnabled()) {
46         return GlobalTSTypeRef(TSModuleTable::BUILTINS_TABLE_ID, typeId);
47     }
48     const JSPandaFile *builtinjsPandaFile = tsManager_->GetBuiltinPandaFile();
49     if (builtinjsPandaFile == nullptr) {
50         LOG_COMPILER(FATAL) << "load lib_ark_builtins.d.ts failed";
51     }
52     uint32_t offset = tsManager_->GetBuiltinOffset(typeId);
53     return CreateGT(builtinjsPandaFile, tsManager_->GetBuiltinRecordName(), offset);
54 }
55 
ParseType(const JSPandaFile * jsPandaFile,const CString & recordName,uint32_t typeId)56 GlobalTSTypeRef TSTypeParser::ParseType(const JSPandaFile *jsPandaFile, const CString &recordName, uint32_t typeId)
57 {
58     panda_file::File::EntityId offset(typeId);
59     JSHandle<TaggedArray> literal = LiteralDataExtractor::GetTypeLiteral(thread_, jsPandaFile, offset);
60     if (literal->GetLength() == 0) {  // typeLiteral maybe hole in d.abc
61         return GetAndStoreGT(jsPandaFile, typeId, recordName);
62     }
63     TSTypeKind kind = static_cast<TSTypeKind>(literal->Get(TYPE_KIND_INDEX_IN_LITERAL).GetInt());
64     if (kind == TSTypeKind::IMPORT) {
65         return ResolveImportType(jsPandaFile, recordName, literal, typeId);
66     }
67 
68     uint32_t moduleId = tableGenerator_.TryGetModuleId(recordName);
69     if (UNLIKELY(!GlobalTSTypeRef::IsVaildModuleId(moduleId))) {
70         LOG_COMPILER(DEBUG) << "The maximum number of TSTypeTables is reached. All TSTypes in the record "
71                             << recordName << " will not be parsed and will be treated as any.";
72         return GetAndStoreGT(jsPandaFile, typeId, recordName);
73     }
74 
75     JSHandle<TSTypeTable> table = tableGenerator_.GetOrGenerateTSTypeTable(jsPandaFile, recordName, moduleId);
76     uint32_t localId = tableGenerator_.TryGetLocalId(table);
77     if (UNLIKELY(!GlobalTSTypeRef::IsVaildLocalId(localId))) {
78         LOG_COMPILER(DEBUG) << "The maximum number of TSTypes in TSTypeTable " << moduleId << " is reached. "
79                             << "The TSType with typeId " << typeId << " in the record " << recordName
80                             << " will not be parsed and will be treated as any.";
81         return GetAndStoreGT(jsPandaFile, typeId, recordName);
82     }
83 
84     table->SetNumberOfTypes(thread_, localId);
85     GlobalTSTypeRef gt = GetAndStoreGT(jsPandaFile, typeId, recordName, moduleId, localId);
86     JSHandle<JSTaggedValue> type = ParseNonImportType(jsPandaFile, recordName, literal, kind, typeId);
87     if (UNLIKELY(type->IsUndefined())) {
88         return GetAndStoreGT(jsPandaFile, typeId, recordName);
89     }
90 
91     SetTSType(table, type, gt);
92     tsManager_->CollectTypeOffsets(gt);  // collect types that need to generate hclasses
93     return gt;
94 }
95 
ResolveImportType(const JSPandaFile * jsPandaFile,const CString & recordName,JSHandle<TaggedArray> literal,uint32_t typeId)96 GlobalTSTypeRef TSTypeParser::ResolveImportType(const JSPandaFile *jsPandaFile, const CString &recordName,
97                                                 JSHandle<TaggedArray> literal, uint32_t typeId)
98 {
99     JSHandle<EcmaString> importVarNamePath(thread_, literal->Get(IMPORT_PATH_OFFSET_IN_LITERAL)); // #A#./A
100     JSHandle<EcmaString> relativePath = GenerateImportRelativePath(importVarNamePath);
101     CString cstringRelativePath = ConvertToString(*relativePath);
102     // skip @ohos:|@app:|@native: prefixed imports
103     auto [isNative, _] = ModuleManager::CheckNativeModule(cstringRelativePath);
104     if (isNative) {
105         return GetAndStoreGT(jsPandaFile, typeId, recordName);
106     }
107 
108     CString baseFileName = jsPandaFile->GetJSPandaFileDesc();
109     CString entryPoint =
110         base::PathHelper::ConcatFileNameWithMerge(thread_, jsPandaFile, baseFileName, recordName, cstringRelativePath);
111     ASSERT_PRINT(!entryPoint.empty(),
112         "EntryPoint is empty. Please check whether concating file name is correct or "
113         "whether the module request recorded in the import-type literal is correct.");
114     // skip files without type information
115     if (UNLIKELY(!jsPandaFile->HasTypeSummaryOffset(entryPoint))) {
116         return GetAndStoreGT(jsPandaFile, typeId, recordName);
117     }
118 
119     uint32_t moduleId = tableGenerator_.TryGetModuleId(entryPoint);
120     if (UNLIKELY(!GlobalTSTypeRef::IsVaildModuleId(moduleId))) {
121         LOG_COMPILER(DEBUG) << "The maximum number of TSTypeTables is reached. All TSTypes in the recored "
122                             << entryPoint << " will not be parsed and will be treated as any.";
123         return GetAndStoreGT(jsPandaFile, typeId, recordName);
124     }
125 
126     JSHandle<TSTypeTable> table = tableGenerator_.GetOrGenerateTSTypeTable(jsPandaFile, entryPoint, moduleId);
127     JSHandle<JSTaggedValue> exportTable = GenerateExportTableFromRecord(jsPandaFile, entryPoint, table);
128     JSHandle<TaggedArray> arrayWithGT(exportTable);
129     JSHandle<EcmaString> targetVarName = GenerateImportVar(importVarNamePath);
130     GlobalTSTypeRef importedGT = GetExportGTByName(targetVarName, arrayWithGT);
131     return GetAndStoreImportGT(jsPandaFile, typeId, recordName, importedGT);
132 }
133 
ParseNonImportType(const JSPandaFile * jsPandaFile,const CString & recordName,JSHandle<TaggedArray> literal,TSTypeKind kind,uint32_t typeId)134 JSHandle<JSTaggedValue> TSTypeParser::ParseNonImportType(const JSPandaFile *jsPandaFile, const CString &recordName,
135     JSHandle<TaggedArray> literal, TSTypeKind kind, uint32_t typeId)
136 {
137     switch (kind) {
138         case TSTypeKind::CLASS: {
139             JSHandle<TSClassType> classType = ParseClassType(jsPandaFile, recordName, literal, typeId);
140             return JSHandle<JSTaggedValue>(classType);
141         }
142         case TSTypeKind::CLASS_INSTANCE: {
143             JSHandle<TSClassInstanceType> classInstanceType = ParseClassInstanceType(jsPandaFile, recordName, literal);
144             return JSHandle<JSTaggedValue>(classInstanceType);
145         }
146         case TSTypeKind::INTERFACE_KIND: {
147             JSHandle<TSInterfaceType> interfaceType = ParseInterfaceType(jsPandaFile, recordName, literal);
148             return JSHandle<JSTaggedValue>(interfaceType);
149         }
150         case TSTypeKind::UNION: {
151             JSHandle<TSUnionType> unionType = ParseUnionType(jsPandaFile, recordName, literal);
152             return JSHandle<JSTaggedValue>(unionType);
153         }
154         case TSTypeKind::FUNCTION: {
155             JSHandle<TSFunctionType> functionType = ParseFunctionType(jsPandaFile, recordName, literal);
156             return JSHandle<JSTaggedValue>(functionType);
157         }
158         case TSTypeKind::ARRAY: {
159             JSHandle<TSArrayType> arrayType = ParseArrayType(jsPandaFile, recordName, literal);
160             return JSHandle<JSTaggedValue>(arrayType);
161         }
162         case TSTypeKind::OBJECT: {
163             JSHandle<TSObjectType> objectType = ParseObjectType(jsPandaFile, recordName, literal);
164             return JSHandle<JSTaggedValue>(objectType);
165         }
166         default: {
167             LOG_COMPILER(DEBUG) << "Do not support parse types with kind " << static_cast<uint32_t>(kind) << ". "
168                                 << "Please check whether the type literal " << typeId
169                                 << " recorded in the record " << recordName << " is correct.";
170             return thread_->GlobalConstants()->GetHandledUndefined();
171         }
172     }
173 }
174 
ParseClassType(const JSPandaFile * jsPandaFile,const CString & recordName,const JSHandle<TaggedArray> & literal,uint32_t typeId)175 JSHandle<TSClassType> TSTypeParser::ParseClassType(const JSPandaFile *jsPandaFile, const CString &recordName,
176                                                    const JSHandle<TaggedArray> &literal, uint32_t typeId)
177 {
178     JSHandle<TSClassType> classType = factory_->NewTSClassType();
179 
180     std::string className = tsManager_->GetClassNameByOffset(jsPandaFile, typeId);
181     JSHandle<EcmaString> classEcmaString = factory_->NewFromStdString(className);
182     classType->SetName(thread_, classEcmaString.GetTaggedValue());
183 
184     uint32_t index = 0;
185     ASSERT(static_cast<TSTypeKind>(literal->Get(index).GetInt()) == TSTypeKind::CLASS);
186 
187     const uint32_t ignoreLength = 2;  // 2: ignore accessFlag and readonly
188     index += ignoreLength;
189     int extendsTypeId = literal->Get(index++).GetInt();
190     if (TSClassType::IsBaseClassType(extendsTypeId)) {
191         classType->SetHasLinked(true);
192     } else {
193         auto extensionGT = CreateGT(jsPandaFile, recordName, extendsTypeId);
194         classType->SetExtensionGT(extensionGT);
195         if (extensionGT == GlobalTSTypeRef::Default()) {
196             classType->SetHasLinked(true);
197         }
198     }
199 
200     // ignore implement
201     uint32_t numImplement = literal->Get(index++).GetInt();
202     index += numImplement;
203 
204     // resolve instance type
205     uint32_t numFields = static_cast<uint32_t>(literal->Get(index++).GetInt());
206 
207     JSHandle<TSObjectType> instanceType = factory_->NewTSObjectType(numFields);
208     JSHandle<TSObjLayoutInfo> instanceTypeInfo(thread_, instanceType->GetObjLayoutInfo());
209     ASSERT(instanceTypeInfo->GetPropertiesCapacity() == numFields);
210     FillPropertyTypes(jsPandaFile, recordName, instanceTypeInfo, literal, 0, numFields, index, true);
211     classType->SetInstanceType(thread_, instanceType);
212 
213     // resolve prototype type
214     uint32_t numNonStatic = literal->Get(index++).GetInt();
215     JSHandle<TSObjectType> prototypeType = factory_->NewTSObjectType(numNonStatic);
216 
217     JSHandle<TSObjLayoutInfo> nonStaticTypeInfo(thread_, prototypeType->GetObjLayoutInfo());
218     ASSERT(nonStaticTypeInfo->GetPropertiesCapacity() == static_cast<uint32_t>(numNonStatic));
219     FillPropertyTypes(jsPandaFile, recordName, nonStaticTypeInfo, literal, 0, numNonStatic, index, false);
220     classType->SetPrototypeType(thread_, prototypeType);
221 
222     // resolve constructor type
223     // static include fields and methods, which the former takes up 4 spaces and the latter takes up 2 spaces.
224     uint32_t numStaticFields = literal->Get(index++).GetInt();
225     uint32_t numStaticMethods = literal->Get(index + numStaticFields * TSClassType::FIELD_LENGTH).GetInt();
226     uint32_t numStatic = numStaticFields + numStaticMethods;
227     // new function type when support it
228     JSHandle<TSObjectType> constructorType = factory_->NewTSObjectType(numStatic);
229 
230     JSHandle<TSObjLayoutInfo> staticTypeInfo(thread_, constructorType->GetObjLayoutInfo());
231     ASSERT(staticTypeInfo->GetPropertiesCapacity() == static_cast<uint32_t>(numStatic));
232     FillPropertyTypes(jsPandaFile, recordName, staticTypeInfo, literal, 0, numStaticFields, index, true);
233     index++;  // jmp over numStaticMethods
234     // static methods
235     FillPropertyTypes(jsPandaFile, recordName, staticTypeInfo, literal, numStaticFields, numStatic, index, false);
236     classType->SetConstructorType(thread_, constructorType);
237     return classType;
238 }
239 
ParseClassInstanceType(const JSPandaFile * jsPandaFile,const CString & recordName,const JSHandle<TaggedArray> & literal)240 JSHandle<TSClassInstanceType> TSTypeParser::ParseClassInstanceType(const JSPandaFile *jsPandaFile,
241                                                                    const CString &recordName,
242                                                                    const JSHandle<TaggedArray> &literal)
243 {
244     ASSERT(static_cast<TSTypeKind>(literal->Get(TYPE_KIND_INDEX_IN_LITERAL).GetInt()) ==
245                                    TSTypeKind::CLASS_INSTANCE);
246     JSHandle<TSClassInstanceType> classInstanceType = factory_->NewTSClassInstanceType();
247     uint32_t classTypeId = static_cast<uint32_t>(literal->Get(TSClassInstanceType::CREATE_CLASS_OFFSET).GetInt());
248     auto classGT = CreateGT(jsPandaFile, recordName, classTypeId);
249     classInstanceType->SetClassGT(classGT);
250     return classInstanceType;
251 }
252 
ParseInterfaceType(const JSPandaFile * jsPandaFile,const CString & recordName,const JSHandle<TaggedArray> & literal)253 JSHandle<TSInterfaceType> TSTypeParser::ParseInterfaceType(const JSPandaFile *jsPandaFile, const CString &recordName,
254                                                            const JSHandle<TaggedArray> &literal)
255 {
256     uint32_t index = 0;
257     JSHandle<TSInterfaceType> interfaceType = factory_->NewTSInterfaceType();
258     ASSERT(static_cast<TSTypeKind>(literal->Get(index).GetInt()) == TSTypeKind::INTERFACE_KIND);
259 
260     index++;
261     // resolve extends of interface
262     uint32_t numExtends = literal->Get(index++).GetInt();
263     JSHandle<TaggedArray> extendsId = factory_->NewTaggedArray(numExtends);
264     JSMutableHandle<JSTaggedValue> extendsType(thread_, JSTaggedValue::Undefined());
265     for (uint32_t extendsIndex = 0; extendsIndex < numExtends; extendsIndex++) {
266         auto typeId = literal->Get(index++).GetInt();
267         auto extendGT = CreateGT(jsPandaFile, recordName, typeId);
268         extendsType.Update(JSTaggedValue(extendGT.GetType()));
269         extendsId->Set(thread_, extendsIndex, extendsType);
270     }
271     interfaceType->SetExtends(thread_, extendsId);
272 
273     // resolve fields and methods of interface
274     uint32_t numFields = literal->Get(index++).GetInt();
275     // field takes up 4 spaces and method takes up 2 spaces.
276     uint32_t numMethods = static_cast<uint32_t>(literal->Get(index +
277                                                              numFields * TSInterfaceType::FIELD_LENGTH).GetInt());
278     uint32_t totalFields = numFields + numMethods;
279 
280     JSHandle<TSObjectType> fieldsType = factory_->NewTSObjectType(totalFields);
281     JSHandle<TSObjLayoutInfo> fieldsTypeInfo(thread_, fieldsType->GetObjLayoutInfo());
282     ASSERT(fieldsTypeInfo->GetPropertiesCapacity() == static_cast<uint32_t>(totalFields));
283     FillPropertyTypes(jsPandaFile, recordName, fieldsTypeInfo, literal, 0, numFields, index, true);
284     index++;  // jmp over numMethod
285     FillInterfaceMethodTypes(jsPandaFile, recordName, fieldsTypeInfo, literal, numFields, totalFields, index);
286     interfaceType->SetFields(thread_, fieldsType);
287     return interfaceType;
288 }
289 
ParseUnionType(const JSPandaFile * jsPandaFile,const CString & recordName,const JSHandle<TaggedArray> & literal)290 JSHandle<TSUnionType> TSTypeParser::ParseUnionType(const JSPandaFile *jsPandaFile, const CString &recordName,
291                                                    const JSHandle<TaggedArray> &literal)
292 {
293     uint32_t literalIndex = 0;
294     ASSERT(static_cast<TSTypeKind>(literal->Get(literalIndex).GetInt()) == TSTypeKind::UNION);
295     literalIndex++;
296     uint32_t numOfUnionMembers = literal->Get(literalIndex++).GetInt();
297 
298     JSHandle<TSUnionType> unionType = factory_->NewTSUnionType(numOfUnionMembers);
299     JSHandle<TaggedArray> components(thread_, unionType->GetComponents());
300     for (uint32_t index = 0; index < numOfUnionMembers; ++index) {
301         uint32_t componentTypeId = literal->Get(literalIndex++).GetInt();
302         auto componentGT = CreateGT(jsPandaFile, recordName, componentTypeId);
303         components->Set(thread_, index, JSTaggedValue(componentGT.GetType()));
304     }
305     unionType->SetComponents(thread_, components);
306     return unionType;
307 }
308 
ParseFunctionType(const JSPandaFile * jsPandaFile,const CString & recordName,const JSHandle<TaggedArray> & literal)309 JSHandle<TSFunctionType> TSTypeParser::ParseFunctionType(const JSPandaFile *jsPandaFile, const CString &recordName,
310                                                          const JSHandle<TaggedArray> &literal)
311 {
312     uint32_t index = 0;
313     ASSERT(static_cast<TSTypeKind>(literal->Get(index).GetInt()) == TSTypeKind::FUNCTION);
314     index++;
315 
316     int32_t bitField = literal->Get(index++).GetInt();
317 
318     JSHandle<JSTaggedValue> functionName(thread_, literal->Get(index++));
319     bool hasThisType = static_cast<bool>(literal->Get(index++).GetInt());
320     int32_t thisTypeId = 0;
321     if (hasThisType) {
322         thisTypeId = literal->Get(index++).GetInt();
323     }
324 
325     int32_t length = literal->Get(index++).GetInt();
326     JSHandle<TSFunctionType> functionType = factory_->NewTSFunctionType(length);
327     JSHandle<TaggedArray> parameterTypes(thread_, functionType->GetParameterTypes());
328     JSMutableHandle<JSTaggedValue> parameterTypeRef(thread_, JSTaggedValue::Undefined());
329     for (int32_t i = 0; i < length; ++i) {
330         auto typeId = literal->Get(index++).GetInt();
331         auto parameterGT = CreateGT(jsPandaFile, recordName, typeId);
332         if (tsManager_->IsClassTypeKind(parameterGT)) {
333             parameterGT = tsManager_->CreateClassInstanceType(parameterGT);
334         }
335         parameterTypeRef.Update(JSTaggedValue(parameterGT.GetType()));
336         parameterTypes->Set(thread_, i, parameterTypeRef);
337     }
338     int32_t returntypeId = literal->Get(index++).GetInt();
339 
340     functionType->SetName(thread_, functionName);
341     if (hasThisType) {
342         auto thisGT = CreateGT(jsPandaFile, recordName, thisTypeId);
343         functionType->SetThisGT(thisGT);
344     }
345 
346     functionType->SetParameterTypes(thread_, parameterTypes);
347     auto returnGT = CreateGT(jsPandaFile, recordName, returntypeId);
348     functionType->SetReturnGT(returnGT);
349     functionType->SetBitField(bitField);
350 
351     return functionType;
352 }
353 
ParseArrayType(const JSPandaFile * jsPandaFile,const CString & recordName,const JSHandle<TaggedArray> & literal)354 JSHandle<TSArrayType> TSTypeParser::ParseArrayType(const JSPandaFile *jsPandaFile, const CString &recordName,
355                                                    const JSHandle<TaggedArray> &literal)
356 {
357     uint32_t index = 0;
358     ASSERT(static_cast<TSTypeKind>(literal->Get(index).GetInt()) == TSTypeKind::ARRAY);
359     index++;
360     JSHandle<JSTaggedValue> elementTypeId(thread_, literal->Get(index++));
361     ASSERT(elementTypeId->IsInt());
362     JSHandle<TSArrayType> arrayType = factory_->NewTSArrayType();
363     auto elemetnGT = CreateGT(jsPandaFile, recordName, elementTypeId->GetInt());
364     if (tsManager_->IsClassTypeKind(elemetnGT)) {
365         elemetnGT = tsManager_->CreateClassInstanceType(elemetnGT);
366     }
367     arrayType->SetElementGT(elemetnGT);
368     return arrayType;
369 }
370 
ParseObjectType(const JSPandaFile * jsPandaFile,const CString & recordName,const JSHandle<TaggedArray> & literal)371 JSHandle<TSObjectType> TSTypeParser::ParseObjectType(const JSPandaFile *jsPandaFile, const CString &recordName,
372                                                      const JSHandle<TaggedArray> &literal)
373 {
374     uint32_t index = 0;
375     ASSERT(static_cast<TSTypeKind>(literal->Get(index).GetInt()) == TSTypeKind::OBJECT);
376     index++;
377     uint32_t length = literal->Get(index++).GetInt();
378     JSHandle<TSObjectType> objectType = factory_->NewTSObjectType(length);
379     JSHandle<TSObjLayoutInfo> propertyTypeInfo(thread_, objectType->GetObjLayoutInfo());
380     ASSERT(propertyTypeInfo->GetPropertiesCapacity() == static_cast<uint32_t>(length));
381     FillPropertyTypes(jsPandaFile, recordName, propertyTypeInfo, literal, 0, length, index, false);
382     objectType->SetObjLayoutInfo(thread_, propertyTypeInfo);
383     return objectType;
384 }
385 
FillPropertyTypes(const JSPandaFile * jsPandaFile,const CString & recordName,JSHandle<TSObjLayoutInfo> & layout,const JSHandle<TaggedArray> & literal,uint32_t startIndex,uint32_t lastIndex,uint32_t & index,bool isField)386 void TSTypeParser::FillPropertyTypes(const JSPandaFile *jsPandaFile, const CString &recordName,
387                                      JSHandle<TSObjLayoutInfo> &layout, const JSHandle<TaggedArray> &literal,
388                                      uint32_t startIndex, uint32_t lastIndex, uint32_t &index, bool isField)
389 {
390     JSMutableHandle<JSTaggedValue> key(thread_, JSTaggedValue::Undefined());
391     JSMutableHandle<JSTaggedValue> value(thread_, JSTaggedValue::Undefined());
392     for (uint32_t fieldIndex = startIndex; fieldIndex < lastIndex; ++fieldIndex) {
393         key.Update(literal->Get(index++));
394         ASSERT(key->IsString());
395         auto gt = CreateGT(jsPandaFile, recordName, literal->Get(index++).GetInt());
396         if (tsManager_->IsClassTypeKind(gt)) {
397             gt = tsManager_->CreateClassInstanceType(gt);
398         }
399         value.Update(JSTaggedValue(gt.GetType()));
400         layout->AddKeyAndType(thread_, key.GetTaggedValue(), value.GetTaggedValue());
401         if (isField) {
402             index += 2;  // 2: ignore accessFlag and readonly
403         }
404     }
405 }
406 
FillInterfaceMethodTypes(const JSPandaFile * jsPandaFile,const CString & recordName,JSHandle<TSObjLayoutInfo> & layout,const JSHandle<TaggedArray> & literal,uint32_t startIndex,uint32_t lastIndex,uint32_t & index)407 void TSTypeParser::FillInterfaceMethodTypes(const JSPandaFile *jsPandaFile, const CString &recordName,
408                                             JSHandle<TSObjLayoutInfo> &layout, const JSHandle<TaggedArray> &literal,
409                                             uint32_t startIndex, uint32_t lastIndex, uint32_t &index)
410 {
411     JSMutableHandle<JSTaggedValue> key(thread_, JSTaggedValue::Undefined());
412     JSMutableHandle<JSTaggedValue> value(thread_, JSTaggedValue::Undefined());
413     for (uint32_t methodIndex = startIndex; methodIndex < lastIndex; ++methodIndex) {
414         auto gt = CreateGT(jsPandaFile, recordName, literal->Get(index++).GetInt());
415         value.Update(JSTaggedValue(gt.GetType()));
416 
417         if (tsManager_->IsFunctionTypeKind(gt)) {
418             JSHandle<JSTaggedValue> tsType = tsManager_->GetTSType(gt);
419             ASSERT(tsType->IsTSFunctionType());
420 
421             JSHandle<TSFunctionType> functionType(tsType);
422             key.Update(functionType->GetName());
423         };
424 
425         layout->AddKeyAndType(thread_, key.GetTaggedValue(), value.GetTaggedValue());
426     }
427 }
428 
GetExportDataFromRecord(const JSPandaFile * jsPandaFile,const CString & recordName)429 JSHandle<TaggedArray> TSTypeParser::GetExportDataFromRecord(const JSPandaFile *jsPandaFile,
430                                                             const CString &recordName)
431 {
432     const panda_file::File &pf = *jsPandaFile->GetPandaFile();
433     panda_file::File::EntityId methodId(jsPandaFile->GetMainMethodIndex(recordName));
434     panda_file::MethodDataAccessor mda(pf, methodId);
435 
436     const char *symbolTypes;
437     auto *fileName = pf.GetFilename().c_str();
438     if (::strcmp(TSTypeTable::BUILTINS_TABLE_NAME, fileName) == 0) {
439         symbolTypes = DECLARED_SYMBOL_TYPES;
440     } else {
441         symbolTypes = EXPORTED_SYMBOL_TYPES;
442     }
443 
444     JSHandle<TaggedArray> typeOfExportedSymbols(thread_, thread_->GlobalConstants()->GetEmptyArray());
445     mda.EnumerateAnnotations([&](panda_file::File::EntityId annotation_id) {
446         panda_file::AnnotationDataAccessor ada(pf, annotation_id);
447         auto *annotationName = reinterpret_cast<const char *>(pf.GetStringData(ada.GetClassId()).data);
448         ASSERT(annotationName != nullptr);
449         if (::strcmp("L_ESTypeAnnotation;", annotationName) != 0) {
450             return;
451         }
452         uint32_t length = ada.GetCount();
453         for (uint32_t i = 0; i < length; i++) {
454             panda_file::AnnotationDataAccessor::Elem adae = ada.GetElement(i);
455             auto *elemName = reinterpret_cast<const char *>(pf.GetStringData(adae.GetNameId()).data);
456             ASSERT(elemName != nullptr);
457 
458             if (::strcmp(symbolTypes, elemName) != 0) {
459                 continue;
460             }
461 
462             panda_file::ScalarValue sv = adae.GetScalarValue();
463             panda_file::File::EntityId literalOffset(sv.GetValue());
464             typeOfExportedSymbols = LiteralDataExtractor::GetTypeLiteral(thread_, jsPandaFile, literalOffset);
465             // typeOfExprotedSymbols: "symbol0", "type0", "symbol1", "type1" ...
466         }
467     });
468 
469     return typeOfExportedSymbols;
470 }
471 
GenerateExportTableFromRecord(const JSPandaFile * jsPandaFile,const CString & recordName,const JSHandle<TSTypeTable> & table)472 JSHandle<JSTaggedValue> TSTypeParser::GenerateExportTableFromRecord(const JSPandaFile *jsPandaFile,
473                                                                     const CString &recordName,
474                                                                     const JSHandle<TSTypeTable> &table)
475 {
476     JSHandle<JSTaggedValue> exportValeTable = TSTypeTable::GetExportValueTable(thread_, table);
477     if (exportValeTable->IsUndefined()) {
478         // Read export-data from annotation of the .abc File
479         JSHandle<TaggedArray> exportTable = GetExportDataFromRecord(jsPandaFile, recordName);
480         uint32_t length = exportTable->GetLength();
481 
482         // Replace typeIds with GT
483         JSTaggedValue target;
484         for (uint32_t i = 1; i < length; i += 2) {  // 2: skip a pair of key and value
485             target = exportTable->Get(i);
486             // Create GT based on typeId, and wrapped it into a JSTaggedValue
487             uint32_t typeId = static_cast<uint32_t>(target.GetInt());
488             GlobalTSTypeRef typeGT = CreateGT(jsPandaFile, recordName, typeId);
489             // Set the wrapped GT to exportTable
490             exportTable->Set(thread_, i, JSTaggedValue(typeGT.GetType()));
491         }
492         TSTypeTable::SetExportValueTable(thread_, table, exportTable);
493         return JSHandle<JSTaggedValue>(exportTable);
494     }
495     ASSERT(exportValeTable->IsTaggedArray());
496     return exportValeTable;
497 }
498 
GenerateImportRelativePath(JSHandle<EcmaString> importRel) const499 JSHandle<EcmaString> TSTypeParser::GenerateImportRelativePath(JSHandle<EcmaString> importRel) const
500 {
501     // importNamePath #A#./A
502     CString importNamePath = ConvertToString(importRel.GetTaggedValue());
503     auto lastPos = importNamePath.find_last_of('#');
504     CString path = importNamePath.substr(lastPos + 1, importNamePath.size() - lastPos - 1);
505     return factory_->NewFromUtf8(path); // #A#./A -> ./A
506 }
507 
GenerateImportVar(JSHandle<EcmaString> import) const508 JSHandle<EcmaString> TSTypeParser::GenerateImportVar(JSHandle<EcmaString> import) const
509 {
510     // importNamePath #A#./A
511     CString importVarNamePath = ConvertToString(import.GetTaggedValue());
512     auto firstPos = importVarNamePath.find_first_of('#');
513     auto lastPos = importVarNamePath.find_last_of('#');
514     CString target = importVarNamePath.substr(firstPos + 1, lastPos - firstPos - 1);
515     return factory_->NewFromUtf8(target); // #A#./A -> A
516 }
517 
GetExportGTByName(JSHandle<EcmaString> target,JSHandle<TaggedArray> & exportTable) const518 GlobalTSTypeRef TSTypeParser::GetExportGTByName(JSHandle<EcmaString> target, JSHandle<TaggedArray> &exportTable) const
519 {
520     uint32_t length = exportTable->GetLength();
521     // the exportTable is arranged as follows ["A", "101", "B", "102"]
522     // get GT of a export type specified by its descriptor/name
523     for (uint32_t i = 0; i < length; i = i + 2) {  // 2: symbol and symbolType
524         EcmaString *valueString = EcmaString::Cast(exportTable->Get(i).GetTaggedObject());
525         if (EcmaStringAccessor::StringsAreEqual(*target, valueString)) {
526             // Transform raw data of JSTaggedValue to GT
527             return GlobalTSTypeRef(exportTable->Get(i + 1).GetInt());
528         }
529     }
530     return GlobalTSTypeRef::Default();
531 }
532 }  // namespace panda::ecmascript
533