• 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/jspandafile/accessor/module_data_accessor.h"
17 #include "ecmascript/base/string_helper.h"
18 #include "ecmascript/builtins/builtins_json.h"
19 #include "ecmascript/ecma_string.h"
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/jspandafile/js_pandafile_manager.h"
22 #include "ecmascript/tagged_array-inl.h"
23 #include "ecmascript/module/js_module_manager.h"
24 #include "ecmascript/module/module_data_extractor.h"
25 
26 #include "libpandafile/literal_data_accessor-inl.h"
27 
28 namespace panda::ecmascript {
29 using StringData = panda_file::StringData;
30 using BuiltinsJson = builtins::BuiltinsJson;
31 using JSRecordInfo = ecmascript::JSPandaFile::JSRecordInfo;
32 
ParseModule(JSThread * thread,const JSPandaFile * jsPandaFile,const CString & descriptor,const CString & moduleFilename)33 JSHandle<JSTaggedValue> ModuleDataExtractor::ParseModule(JSThread *thread, const JSPandaFile *jsPandaFile,
34                                                          const CString &descriptor, const CString &moduleFilename)
35 {
36     int moduleIdx = jsPandaFile->GetModuleRecordIdx(descriptor);
37     ASSERT(moduleIdx != -1);
38 
39     panda_file::File::EntityId moduleId;
40     if (jsPandaFile->IsNewVersion()) {  // new pandafile version use new literal offset mechanism
41         moduleId = panda_file::File::EntityId(static_cast<uint32_t>(moduleIdx));
42     } else {
43         panda_file::LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
44         moduleId = lda.GetLiteralArrayId(static_cast<size_t>(moduleIdx));
45     }
46 
47     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
48     JSHandle<SourceTextModule> moduleRecord = factory->NewSourceTextModule();
49     ModuleDataExtractor::ExtractModuleDatas(thread, jsPandaFile, moduleId, moduleRecord);
50 
51     bool hasTLA = jsPandaFile->GetHasTopLevelAwait(descriptor);
52     moduleRecord->SetHasTLA(hasTLA);
53 
54     JSHandle<EcmaString> ecmaModuleFilename = factory->NewFromUtf8(moduleFilename);
55     moduleRecord->SetEcmaModuleFilename(thread, ecmaModuleFilename);
56 
57     moduleRecord->SetStatus(ModuleStatus::UNINSTANTIATED);
58     moduleRecord->SetTypes(ModuleTypes::ECMA_MODULE);
59     moduleRecord->SetIsNewBcVersion(jsPandaFile->IsNewVersion());
60 
61     return JSHandle<JSTaggedValue>::Cast(moduleRecord);
62 }
63 
ExtractModuleDatas(JSThread * thread,const JSPandaFile * jsPandaFile,panda_file::File::EntityId moduleId,JSHandle<SourceTextModule> & moduleRecord)64 void ModuleDataExtractor::ExtractModuleDatas(JSThread *thread, const JSPandaFile *jsPandaFile,
65                                              panda_file::File::EntityId moduleId,
66                                              JSHandle<SourceTextModule> &moduleRecord)
67 {
68     [[maybe_unused]] EcmaHandleScope scope(thread);
69     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
70     ModuleDataAccessor mda(jsPandaFile, moduleId);
71     const std::vector<uint32_t> &requestModules = mda.getRequestModules();
72     size_t len = requestModules.size();
73     JSHandle<TaggedArray> requestModuleArray = factory->NewTaggedArray(len);
74     for (size_t idx = 0; idx < len; idx++) {
75         StringData sd = jsPandaFile->GetStringData(panda_file::File::EntityId(requestModules[idx]));
76         JSTaggedValue value(factory->GetRawStringFromStringTable(sd));
77         requestModuleArray->Set(thread, idx, value);
78     }
79     if (len > 0) {
80         moduleRecord->SetRequestedModules(thread, requestModuleArray);
81     }
82 
83     // note the order can't change
84     mda.EnumerateImportEntry(thread, requestModuleArray, moduleRecord);
85     mda.EnumerateLocalExportEntry(thread, moduleRecord);
86     mda.EnumerateIndirectExportEntry(thread, requestModuleArray, moduleRecord);
87     mda.EnumerateStarExportEntry(thread, requestModuleArray, moduleRecord);
88 }
89 
ParseCjsModule(JSThread * thread,const JSPandaFile * jsPandaFile)90 JSHandle<JSTaggedValue> ModuleDataExtractor::ParseCjsModule(JSThread *thread, const JSPandaFile *jsPandaFile)
91 {
92     const CString &descriptor = jsPandaFile->GetJSPandaFileDesc();
93     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
94     JSHandle<SourceTextModule> moduleRecord = factory->NewSourceTextModule();
95 
96     JSHandle<EcmaString> cjsModuleFilename = factory->NewFromUtf8(descriptor);
97     moduleRecord->SetEcmaModuleFilename(thread, cjsModuleFilename);
98 
99     JSHandle<JSTaggedValue> defaultName = thread->GlobalConstants()->GetHandledDefaultString();
100     JSHandle<LocalExportEntry> localExportEntry = factory->NewLocalExportEntry(defaultName,
101         defaultName, LocalExportEntry::LOCAL_DEFAULT_INDEX);
102     SourceTextModule::AddLocalExportEntry(thread, moduleRecord, localExportEntry, 0, 1); // 1 means len
103     moduleRecord->SetStatus(ModuleStatus::UNINSTANTIATED);
104     moduleRecord->SetTypes(ModuleTypes::CJS_MODULE);
105     moduleRecord->SetIsNewBcVersion(jsPandaFile->IsNewVersion());
106 
107     return JSHandle<JSTaggedValue>::Cast(moduleRecord);
108 }
109 
ParseJsonModule(JSThread * thread,const JSPandaFile * jsPandaFile,const CString & moduleFilename,const CString & recordName)110 JSHandle<JSTaggedValue> ModuleDataExtractor::ParseJsonModule(JSThread *thread, const JSPandaFile *jsPandaFile,
111                                                              const CString &moduleFilename, const CString &recordName)
112 {
113     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
114     JSHandle<SourceTextModule> moduleRecord = factory->NewSourceTextModule();
115 
116     JSHandle<JSTaggedValue> defaultName = thread->GlobalConstants()->GetHandledDefaultString();
117     JSHandle<LocalExportEntry> localExportEntry = factory->NewLocalExportEntry(defaultName,
118         defaultName, LocalExportEntry::LOCAL_DEFAULT_INDEX);
119     SourceTextModule::AddLocalExportEntry(thread, moduleRecord, localExportEntry, 0, 1); // 1 means len
120     JSTaggedValue jsonData = JsonParse(thread, jsPandaFile, recordName);
121     moduleRecord->StoreModuleValue(thread, 0, JSHandle<JSTaggedValue>(thread, jsonData)); // index = 0
122 
123     JSHandle<EcmaString> ecmaModuleFilename = factory->NewFromUtf8(moduleFilename);
124     moduleRecord->SetEcmaModuleFilename(thread, ecmaModuleFilename);
125 
126     moduleRecord->SetStatus(ModuleStatus::UNINSTANTIATED);
127     moduleRecord->SetTypes(ModuleTypes::JSON_MODULE);
128     moduleRecord->SetIsNewBcVersion(jsPandaFile->IsNewVersion());
129 
130     return JSHandle<JSTaggedValue>::Cast(moduleRecord);
131 }
132 
ParseNativeModule(JSThread * thread,const CString & moduleRequestName,ModuleTypes moduleType)133 JSHandle<JSTaggedValue> ModuleDataExtractor::ParseNativeModule(JSThread *thread, const CString &moduleRequestName,
134                                                                ModuleTypes moduleType)
135 {
136     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
137     JSHandle<SourceTextModule> moduleRecord = factory->NewSourceTextModule();
138 
139     // set moduleRecordName as non-undefined to distinguish between merge and non-merge mode
140     JSHandle<EcmaString> falsyRecordName = factory->NewFromUtf8(moduleRequestName);
141     moduleRecord->SetEcmaModuleRecordName(thread, falsyRecordName);
142     JSHandle<JSTaggedValue> defaultName = thread->GlobalConstants()->GetHandledDefaultString();
143     JSHandle<LocalExportEntry> localExportEntry = factory->NewLocalExportEntry(defaultName,
144         defaultName, LocalExportEntry::LOCAL_DEFAULT_INDEX);
145     SourceTextModule::AddLocalExportEntry(thread, moduleRecord, localExportEntry, 0, 1);
146     moduleRecord->SetTypes(moduleType);
147     moduleRecord->SetIsNewBcVersion(true);
148     moduleRecord->SetStatus(ModuleStatus::INSTANTIATED);
149     moduleRecord->StoreModuleValue(thread, 0, thread->GlobalConstants()->GetHandledUndefined());
150 
151     return JSHandle<JSTaggedValue>::Cast(moduleRecord);
152 }
153 
JsonParse(JSThread * thread,const JSPandaFile * jsPandaFile,CString entryPoint)154 JSTaggedValue ModuleDataExtractor::JsonParse(JSThread *thread, const JSPandaFile *jsPandaFile, CString entryPoint)
155 {
156     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
157     EcmaRuntimeCallInfo *info =
158         EcmaInterpreter::NewRuntimeCallInfo(
159             thread, undefined, undefined, undefined, 1); // 1 : argument numbers
160     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
161     JSRecordInfo recordInfo;
162     bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(entryPoint, recordInfo);
163     if (!hasRecord) {
164         CString msg = "cannot find record '" + entryPoint + "', please check the request path.";
165         LOG_FULL(ERROR) << msg;
166         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), JSTaggedValue::Exception());
167     }
168     StringData sd = jsPandaFile->GetStringData(EntityId(recordInfo.jsonStringId));
169     JSTaggedValue value(thread->GetEcmaVM()->GetFactory()->GetRawStringFromStringTable(sd));
170     info->SetCallArg(value);
171     return BuiltinsJson::Parse(info);
172 }
173 }  // namespace panda::ecmascript
174