• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/module/js_module_manager.h"
16 
17 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/interpreter/fast_runtime_stub-inl.h"
20 #include "ecmascript/interpreter/frame_handler.h"
21 #include "ecmascript/js_array.h"
22 #include "ecmascript/jspandafile/js_pandafile.h"
23 #include "ecmascript/jspandafile/js_pandafile_executor.h"
24 #include "ecmascript/jspandafile/js_pandafile_manager.h"
25 #include "ecmascript/linked_hash_table.h"
26 #include "ecmascript/module/js_module_deregister.h"
27 #include "ecmascript/module/js_module_source_text.h"
28 #include "ecmascript/module/module_data_extractor.h"
29 #include "ecmascript/module/module_path_helper.h"
30 #include "ecmascript/require/js_cjs_module.h"
31 #include "ecmascript/tagged_dictionary.h"
32 #ifdef PANDA_TARGET_WINDOWS
33 #include <algorithm>
34 #endif
35 
36 namespace panda::ecmascript {
37 using StringHelper = base::StringHelper;
38 using JSPandaFile = ecmascript::JSPandaFile;
39 using JSRecordInfo = ecmascript::JSPandaFile::JSRecordInfo;
40 
ModuleManager(EcmaVM * vm)41 ModuleManager::ModuleManager(EcmaVM *vm) : vm_(vm)
42 {
43     resolvedModules_ = NameDictionary::Create(vm_->GetJSThread(), DEAULT_DICTIONART_CAPACITY).GetTaggedValue();
44 }
45 
GetCurrentModule()46 JSTaggedValue ModuleManager::GetCurrentModule()
47 {
48     FrameHandler frameHandler(vm_->GetJSThread());
49     JSTaggedValue currentFunc = frameHandler.GetFunction();
50     return JSFunction::Cast(currentFunc.GetTaggedObject())->GetModule();
51 }
52 
GetModuleValueInner(int32_t index)53 JSTaggedValue ModuleManager::GetModuleValueInner(int32_t index)
54 {
55     JSTaggedValue currentModule = GetCurrentModule();
56     if (currentModule.IsUndefined()) {
57         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
58     }
59     return SourceTextModule::Cast(currentModule.GetTaggedObject())->GetModuleValue(vm_->GetJSThread(), index, false);
60 }
61 
GetModuleValueInner(int32_t index,JSTaggedValue jsFunc)62 JSTaggedValue ModuleManager::GetModuleValueInner(int32_t index, JSTaggedValue jsFunc)
63 {
64     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule();
65     if (currentModule.IsUndefined()) {
66         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
67     }
68     return SourceTextModule::Cast(currentModule.GetTaggedObject())->GetModuleValue(vm_->GetJSThread(), index, false);
69 }
70 
GetModuleValueInner(int32_t index,JSHandle<JSTaggedValue> currentModule)71 JSTaggedValue ModuleManager::GetModuleValueInner(int32_t index, JSHandle<JSTaggedValue> currentModule)
72 {
73     if (currentModule->IsUndefined()) {
74         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
75     }
76     return SourceTextModule::Cast(currentModule->GetTaggedObject())->GetModuleValue(vm_->GetJSThread(), index, false);
77 }
78 
GetModuleValueOutter(int32_t index)79 JSTaggedValue ModuleManager::GetModuleValueOutter(int32_t index)
80 {
81     JSTaggedValue currentModule = GetCurrentModule();
82     return GetModuleValueOutterInternal(index, currentModule);
83 }
84 
GetModuleValueOutter(int32_t index,JSTaggedValue jsFunc)85 JSTaggedValue ModuleManager::GetModuleValueOutter(int32_t index, JSTaggedValue jsFunc)
86 {
87     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule();
88     return GetModuleValueOutterInternal(index, currentModule);
89 }
90 
GetModuleValueOutter(int32_t index,JSHandle<JSTaggedValue> currentModule)91 JSTaggedValue ModuleManager::GetModuleValueOutter(int32_t index, JSHandle<JSTaggedValue> currentModule)
92 {
93     return GetModuleValueOutterInternal(index, currentModule.GetTaggedValue());
94 }
95 
GetModuleValueOutterInternal(int32_t index,JSTaggedValue currentModule)96 JSTaggedValue ModuleManager::GetModuleValueOutterInternal(int32_t index, JSTaggedValue currentModule)
97 {
98     JSThread *thread = vm_->GetJSThread();
99     if (currentModule.IsUndefined()) {
100         LOG_FULL(FATAL) << "GetModuleValueOutter currentModule failed";
101         UNREACHABLE();
102     }
103     JSTaggedValue moduleEnvironment = SourceTextModule::Cast(currentModule.GetTaggedObject())->GetEnvironment();
104     if (moduleEnvironment.IsUndefined()) {
105         return thread->GlobalConstants()->GetUndefined();
106     }
107     ASSERT(moduleEnvironment.IsTaggedArray());
108     JSTaggedValue resolvedBinding = TaggedArray::Cast(moduleEnvironment.GetTaggedObject())->Get(index);
109     if (resolvedBinding.IsResolvedIndexBinding()) {
110         ResolvedIndexBinding *binding = ResolvedIndexBinding::Cast(resolvedBinding.GetTaggedObject());
111         JSTaggedValue resolvedModule = binding->GetModule();
112         ASSERT(resolvedModule.IsSourceTextModule());
113         SourceTextModule *module = SourceTextModule::Cast(resolvedModule.GetTaggedObject());
114 
115         ModuleTypes moduleType = module->GetTypes();
116         if (SourceTextModule::IsNativeModule(moduleType)) {
117             return GetNativeModuleValue(thread, currentModule, resolvedModule, binding);
118         }
119         if (module->GetTypes() == ModuleTypes::CJS_MODULE) {
120             return GetCJSModuleValue(thread, currentModule, resolvedModule, binding);
121         }
122         return SourceTextModule::Cast(
123             resolvedModule.GetTaggedObject())->GetModuleValue(thread, binding->GetIndex(), false);
124     }
125     ResolvedBinding *binding = ResolvedBinding::Cast(resolvedBinding.GetTaggedObject());
126     JSTaggedValue resolvedModule = binding->GetModule();
127     SourceTextModule *module = SourceTextModule::Cast(resolvedModule.GetTaggedObject());
128     if (module->GetTypes() == ModuleTypes::CJS_MODULE) {
129         JSHandle<JSTaggedValue> cjsModuleName(thread, SourceTextModule::GetModuleName(JSTaggedValue(module)));
130         return CjsModule::SearchFromModuleCache(thread, cjsModuleName).GetTaggedValue();
131     }
132     LOG_ECMA(FATAL) << "Get module value failed, mistaken ResolvedBinding";
133     UNREACHABLE();
134 }
135 
GetNativeModuleValue(JSThread * thread,JSTaggedValue currentModule,JSTaggedValue resolvedModule,ResolvedIndexBinding * binding)136 JSTaggedValue ModuleManager::GetNativeModuleValue(JSThread *thread, JSTaggedValue currentModule,
137     JSTaggedValue resolvedModule, ResolvedIndexBinding *binding)
138 {
139     JSHandle<JSTaggedValue> nativeModuleName(thread, SourceTextModule::GetModuleName(resolvedModule));
140     JSHandle<JSTaggedValue> nativeExports = JSHandle<JSTaggedValue>(thread,
141         SourceTextModule::Cast(resolvedModule.GetTaggedObject())->GetModuleValue(thread, 0, false));
142     if (!nativeExports->IsJSObject()) {
143         JSHandle<JSTaggedValue> curModuleName(thread, SourceTextModule::Cast(
144             currentModule.GetTaggedObject())->GetEcmaModuleFilename());
145         LOG_FULL(WARN) << "GetNativeModuleValue: currentModule " + ConvertToString(curModuleName.GetTaggedValue()) +
146             ", find requireModule " + ConvertToString(nativeModuleName.GetTaggedValue()) + " failed";
147         return nativeExports.GetTaggedValue();
148     }
149     return GetValueFromExportObject(nativeExports, binding->GetIndex());
150 }
151 
GetCJSModuleValue(JSThread * thread,JSTaggedValue currentModule,JSTaggedValue resolvedModule,ResolvedIndexBinding * binding)152 JSTaggedValue ModuleManager::GetCJSModuleValue(JSThread *thread, JSTaggedValue currentModule,
153     JSTaggedValue resolvedModule, ResolvedIndexBinding *binding)
154 {
155     JSHandle<JSTaggedValue> cjsModuleName(thread, SourceTextModule::GetModuleName(resolvedModule));
156     JSHandle<JSTaggedValue> cjsExports = CjsModule::SearchFromModuleCache(thread, cjsModuleName);
157     // if cjsModule is not JSObject, means cjs uses default exports.
158     if (!cjsExports->IsJSObject()) {
159         if (cjsExports->IsHole()) {
160             ObjectFactory *factory = vm_->GetFactory();
161             JSHandle<JSTaggedValue> curModuleName(thread, SourceTextModule::Cast(
162                 currentModule.GetTaggedObject())->GetEcmaModuleFilename());
163             CString errorMsg = "GetCJSModuleValue: currentModule" + ConvertToString(curModuleName.GetTaggedValue()) +
164                                 "find requireModule" + ConvertToString(cjsModuleName.GetTaggedValue()) + "failed";
165             JSHandle<JSObject> syntaxError =
166                 factory->GetJSError(base::ErrorType::SYNTAX_ERROR, errorMsg.c_str());
167             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, syntaxError.GetTaggedValue(), JSTaggedValue::Exception());
168         }
169         return cjsExports.GetTaggedValue();
170     }
171     return GetValueFromExportObject(cjsExports, binding->GetIndex());
172 }
173 
GetValueFromExportObject(JSHandle<JSTaggedValue> & exportObject,int32_t index)174 JSTaggedValue ModuleManager::GetValueFromExportObject(JSHandle<JSTaggedValue> &exportObject, int32_t index)
175 {
176     if (index == SourceTextModule::UNDEFINED_INDEX) {
177         return exportObject.GetTaggedValue();
178     }
179     JSTaggedValue value = JSTaggedValue::Hole();
180     JSObject *obj = JSObject::Cast(exportObject.GetTaggedValue());
181     TaggedArray *properties = TaggedArray::Cast(obj->GetProperties().GetTaggedObject());
182     if (!properties->IsDictionaryMode()) {
183         JSHClass *jsHclass = obj->GetJSHClass();
184         LayoutInfo *layoutInfo = LayoutInfo::Cast(jsHclass->GetLayout().GetTaggedObject());
185         PropertyAttributes attr = layoutInfo->GetAttr(index);
186         value = obj->GetProperty(jsHclass, attr);
187     } else {
188         NameDictionary *dict = NameDictionary::Cast(properties);
189         value = dict->GetValue(index);
190     }
191     if (UNLIKELY(value.IsAccessor())) {
192         return FastRuntimeStub::CallGetter(vm_->GetJSThread(), JSTaggedValue(obj), JSTaggedValue(obj), value);
193     }
194     ASSERT(!value.IsAccessor());
195     return value;
196 }
197 
StoreModuleValue(int32_t index,JSTaggedValue value)198 void ModuleManager::StoreModuleValue(int32_t index, JSTaggedValue value)
199 {
200     JSThread *thread = vm_->GetJSThread();
201     JSHandle<SourceTextModule> currentModule(thread, GetCurrentModule());
202     StoreModuleValueInternal(currentModule, index, value);
203 }
204 
StoreModuleValue(int32_t index,JSTaggedValue value,JSTaggedValue jsFunc)205 void ModuleManager::StoreModuleValue(int32_t index, JSTaggedValue value, JSTaggedValue jsFunc)
206 {
207     JSThread *thread = vm_->GetJSThread();
208     JSHandle<SourceTextModule> currentModule(thread, JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule());
209     StoreModuleValueInternal(currentModule, index, value);
210 }
211 
StoreModuleValueInternal(JSHandle<SourceTextModule> & currentModule,int32_t index,JSTaggedValue value)212 void ModuleManager::StoreModuleValueInternal(JSHandle<SourceTextModule> &currentModule,
213                                              int32_t index, JSTaggedValue value)
214 {
215     if (currentModule.GetTaggedValue().IsUndefined()) {
216         LOG_FULL(FATAL) << "StoreModuleValue currentModule failed";
217         UNREACHABLE();
218     }
219     JSThread *thread = vm_->GetJSThread();
220     JSHandle<JSTaggedValue> valueHandle(thread, value);
221     currentModule->StoreModuleValue(thread, index, valueHandle);
222 }
223 
GetModuleValueInner(JSTaggedValue key)224 JSTaggedValue ModuleManager::GetModuleValueInner(JSTaggedValue key)
225 {
226     JSTaggedValue currentModule = GetCurrentModule();
227     if (currentModule.IsUndefined()) {
228         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
229         UNREACHABLE();
230     }
231     return SourceTextModule::Cast(currentModule.GetTaggedObject())->GetModuleValue(vm_->GetJSThread(), key, false);
232 }
233 
GetModuleValueInner(JSTaggedValue key,JSTaggedValue jsFunc)234 JSTaggedValue ModuleManager::GetModuleValueInner(JSTaggedValue key, JSTaggedValue jsFunc)
235 {
236     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule();
237     if (currentModule.IsUndefined()) {
238         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
239         UNREACHABLE();
240     }
241     return SourceTextModule::Cast(currentModule.GetTaggedObject())->GetModuleValue(vm_->GetJSThread(), key, false);
242 }
243 
GetModuleValueOutter(JSTaggedValue key)244 JSTaggedValue ModuleManager::GetModuleValueOutter(JSTaggedValue key)
245 {
246     JSTaggedValue currentModule = GetCurrentModule();
247     return GetModuleValueOutterInternal(key, currentModule);
248 }
249 
GetModuleValueOutter(JSTaggedValue key,JSTaggedValue jsFunc)250 JSTaggedValue ModuleManager::GetModuleValueOutter(JSTaggedValue key, JSTaggedValue jsFunc)
251 {
252     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule();
253     return GetModuleValueOutterInternal(key, currentModule);
254 }
255 
GetModuleValueOutterInternal(JSTaggedValue key,JSTaggedValue currentModule)256 JSTaggedValue ModuleManager::GetModuleValueOutterInternal(JSTaggedValue key, JSTaggedValue currentModule)
257 {
258     JSThread *thread = vm_->GetJSThread();
259     if (currentModule.IsUndefined()) {
260         LOG_FULL(FATAL) << "GetModuleValueOutter currentModule failed";
261         UNREACHABLE();
262     }
263     JSTaggedValue moduleEnvironment = SourceTextModule::Cast(currentModule.GetTaggedObject())->GetEnvironment();
264     if (moduleEnvironment.IsUndefined()) {
265         return thread->GlobalConstants()->GetUndefined();
266     }
267     int entry = NameDictionary::Cast(moduleEnvironment.GetTaggedObject())->FindEntry(key);
268     if (entry == -1) {
269         return thread->GlobalConstants()->GetUndefined();
270     }
271     JSTaggedValue resolvedBinding = NameDictionary::Cast(moduleEnvironment.GetTaggedObject())->GetValue(entry);
272     ASSERT(resolvedBinding.IsResolvedBinding());
273     ResolvedBinding *binding = ResolvedBinding::Cast(resolvedBinding.GetTaggedObject());
274     JSTaggedValue resolvedModule = binding->GetModule();
275     ASSERT(resolvedModule.IsSourceTextModule());
276     SourceTextModule *module = SourceTextModule::Cast(resolvedModule.GetTaggedObject());
277     if (module->GetTypes() == ModuleTypes::CJS_MODULE) {
278         JSHandle<JSTaggedValue> cjsModuleName(thread, SourceTextModule::GetModuleName(JSTaggedValue(module)));
279         return CjsModule::SearchFromModuleCache(thread, cjsModuleName).GetTaggedValue();
280     }
281     return module->GetModuleValue(thread, binding->GetBindingName(), false);
282 }
283 
StoreModuleValue(JSTaggedValue key,JSTaggedValue value)284 void ModuleManager::StoreModuleValue(JSTaggedValue key, JSTaggedValue value)
285 {
286     JSThread *thread = vm_->GetJSThread();
287     JSHandle<SourceTextModule> currentModule(thread, GetCurrentModule());
288     StoreModuleValueInternal(currentModule, key, value);
289 }
290 
StoreModuleValue(JSTaggedValue key,JSTaggedValue value,JSTaggedValue jsFunc)291 void ModuleManager::StoreModuleValue(JSTaggedValue key, JSTaggedValue value, JSTaggedValue jsFunc)
292 {
293     JSThread *thread = vm_->GetJSThread();
294     JSHandle<SourceTextModule> currentModule(thread, JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule());
295     StoreModuleValueInternal(currentModule, key, value);
296 }
297 
StoreModuleValueInternal(JSHandle<SourceTextModule> & currentModule,JSTaggedValue key,JSTaggedValue value)298 void ModuleManager::StoreModuleValueInternal(JSHandle<SourceTextModule> &currentModule,
299                                              JSTaggedValue key, JSTaggedValue value)
300 {
301     if (currentModule.GetTaggedValue().IsUndefined()) {
302         LOG_FULL(FATAL) << "StoreModuleValue currentModule failed";
303         UNREACHABLE();
304     }
305     JSThread *thread = vm_->GetJSThread();
306     JSHandle<JSTaggedValue> keyHandle(thread, key);
307     JSHandle<JSTaggedValue> valueHandle(thread, value);
308     currentModule->StoreModuleValue(thread, keyHandle, valueHandle);
309 }
310 
HostGetImportedModule(const CString & referencingModule)311 JSHandle<SourceTextModule> ModuleManager::HostGetImportedModule(const CString &referencingModule)
312 {
313     ObjectFactory *factory = vm_->GetFactory();
314     JSHandle<EcmaString> referencingHandle = factory->NewFromUtf8(referencingModule);
315     return HostGetImportedModule(referencingHandle.GetTaggedValue());
316 }
317 
HostGetImportedModule(JSTaggedValue referencing)318 JSHandle<SourceTextModule> ModuleManager::HostGetImportedModule(JSTaggedValue referencing)
319 {
320     NameDictionary *dict = NameDictionary::Cast(resolvedModules_.GetTaggedObject());
321     int entry = dict->FindEntry(referencing);
322     LOG_ECMA_IF(entry == -1, FATAL) << "Can not get module: "
323                                     << ConvertToString(referencing);
324     JSTaggedValue result = dict->GetValue(entry);
325     return JSHandle<SourceTextModule>(vm_->GetJSThread(), result);
326 }
327 
HostGetImportedModule(void * src)328 JSHandle<SourceTextModule> ModuleManager::HostGetImportedModule(void *src)
329 {
330     const char *str = reinterpret_cast<char *>(src);
331     const uint8_t *strData = reinterpret_cast<uint8_t *>(src);
332     LOG_FULL(INFO) << "current str during module deregister process : " << str;
333     NameDictionary *dict = NameDictionary::Cast(resolvedModules_.GetTaggedObject());
334     int entry = dict->FindEntry(strData, strlen(str));
335     LOG_ECMA_IF(entry == -1, FATAL) << "Can not get deregister module: " << str;
336     JSTaggedValue result = dict->GetValue(entry);
337     return JSHandle<SourceTextModule>(vm_->GetJSThread(), result);
338 }
339 
IsImportedModuleLoaded(JSTaggedValue referencing)340 bool ModuleManager::IsImportedModuleLoaded(JSTaggedValue referencing)
341 {
342     int entry = NameDictionary::Cast(resolvedModules_.GetTaggedObject())->FindEntry(referencing);
343     return (entry != -1);
344 }
345 
SkipDefaultBundleFile(const CString & moduleFileName) const346 bool ModuleManager::SkipDefaultBundleFile(const CString &moduleFileName) const
347 {
348     // relative file path like "../../xxxx" can't be loaded rightly in aot compilation phase
349     const char relativeFilePath[] = "..";
350     // just to skip misunderstanding error log in LoadJSPandaFile when we ignore Module Resolving Failure.
351     return !vm_->EnableReportModuleResolvingFailure() &&
352         (base::StringHelper::StringStartWith(moduleFileName, ModulePathHelper::BUNDLE_INSTALL_PATH) ||
353         base::StringHelper::StringStartWith(moduleFileName, relativeFilePath));
354 }
355 
ResolveModuleInMergedABC(JSThread * thread,const JSPandaFile * jsPandaFile,const CString & recordName,bool excuteFromJob)356 JSHandle<JSTaggedValue> ModuleManager::ResolveModuleInMergedABC(JSThread *thread, const JSPandaFile *jsPandaFile,
357     const CString &recordName, bool excuteFromJob)
358 {
359     // In static parse Phase, due to lack of some parameters, we will create a empty SourceTextModule which will
360     // be marked as INSTANTIATED to skip Dfs traversal of this import branch.
361     if (!vm_->EnableReportModuleResolvingFailure() && (jsPandaFile == nullptr ||
362         (jsPandaFile != nullptr && !jsPandaFile->HasRecord(recordName)))) {
363         return CreateEmptyModule();
364     } else {
365         return ResolveModuleWithMerge(thread, jsPandaFile, recordName, excuteFromJob);
366     }
367 }
368 
HostResolveImportedModuleWithMerge(const CString & moduleFileName,const CString & recordName,bool excuteFromJob)369 JSHandle<JSTaggedValue> ModuleManager::HostResolveImportedModuleWithMerge(const CString &moduleFileName,
370     const CString &recordName, bool excuteFromJob)
371 {
372     JSThread *thread = vm_->GetJSThread();
373     ObjectFactory *factory = vm_->GetFactory();
374 
375     JSHandle<EcmaString> recordNameHandle = factory->NewFromUtf8(recordName);
376     NameDictionary *dict = NameDictionary::Cast(resolvedModules_.GetTaggedObject());
377     int entry = dict->FindEntry(recordNameHandle.GetTaggedValue());
378     if (entry != -1) {
379         return JSHandle<JSTaggedValue>(thread, dict->GetValue(entry));
380     }
381     std::shared_ptr<JSPandaFile> jsPandaFile = SkipDefaultBundleFile(moduleFileName) ? nullptr :
382         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, moduleFileName, recordName, false);
383     if (jsPandaFile == nullptr) {
384         // In Aot Module Instantiate, we miss some runtime parameters from framework like bundleName or moduleName
385         // which may cause wrong recordName parsing and we also can't load files not in this app hap. But in static
386         // phase, these should not be an error, just skip it is ok.
387         if (vm_->EnableReportModuleResolvingFailure()) {
388             CString msg = "Load file with filename '" + moduleFileName + "' failed, recordName '" + recordName + "'";
389             THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, JSTaggedValue, msg.c_str());
390         }
391     }
392 
393     JSHandle<JSTaggedValue> moduleRecord = ResolveModuleInMergedABC(thread,
394         jsPandaFile.get(), recordName, excuteFromJob);
395     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
396     JSHandle<NameDictionary> handleDict(thread, resolvedModules_);
397     resolvedModules_ = NameDictionary::Put(thread, handleDict, JSHandle<JSTaggedValue>(recordNameHandle),
398         moduleRecord, PropertyAttributes::Default()).GetTaggedValue();
399 
400     return moduleRecord;
401 }
402 
CreateEmptyModule()403 JSHandle<JSTaggedValue> ModuleManager::CreateEmptyModule()
404 {
405     if (!cachedEmptyModule_.IsHole()) {
406         return JSHandle<JSTaggedValue>(vm_->GetJSThread(), cachedEmptyModule_);
407     }
408     ObjectFactory *factory = vm_->GetFactory();
409     JSHandle<SourceTextModule> tmpModuleRecord = factory->NewSourceTextModule();
410     tmpModuleRecord->SetStatus(ModuleStatus::INSTANTIATED);
411     tmpModuleRecord->SetTypes(ModuleTypes::ECMA_MODULE);
412     tmpModuleRecord->SetIsNewBcVersion(true);
413     cachedEmptyModule_ = tmpModuleRecord.GetTaggedValue();
414     return JSHandle<JSTaggedValue>::Cast(tmpModuleRecord);
415 }
416 
HostResolveImportedModule(const CString & referencingModule,bool excuteFromJob)417 JSHandle<JSTaggedValue> ModuleManager::HostResolveImportedModule(const CString &referencingModule, bool excuteFromJob)
418 {
419     JSThread *thread = vm_->GetJSThread();
420     ObjectFactory *factory = vm_->GetFactory();
421 
422     JSHandle<EcmaString> referencingHandle = factory->NewFromUtf8(referencingModule);
423     CString moduleFileName = referencingModule;
424     if (vm_->IsBundlePack()) {
425         if (AOTFileManager::GetAbsolutePath(referencingModule, moduleFileName)) {
426             referencingHandle = factory->NewFromUtf8(moduleFileName);
427         } else {
428             CString msg = "Parse absolute " + referencingModule + " path failed";
429             THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, JSTaggedValue, msg.c_str());
430         }
431     }
432 
433     NameDictionary *dict = NameDictionary::Cast(resolvedModules_.GetTaggedObject());
434     int entry = dict->FindEntry(referencingHandle.GetTaggedValue());
435     if (entry != -1) {
436         return JSHandle<JSTaggedValue>(thread, dict->GetValue(entry));
437     }
438 
439     std::shared_ptr<JSPandaFile> jsPandaFile =
440         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, moduleFileName, JSPandaFile::ENTRY_MAIN_FUNCTION);
441     if (jsPandaFile == nullptr) {
442         CString msg = "Load file with filename '" + moduleFileName + "' failed";
443         THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, JSTaggedValue, msg.c_str());
444     }
445 
446     return ResolveModule(thread, jsPandaFile.get(), excuteFromJob);
447 }
448 
449 // The security interface needs to be modified accordingly.
HostResolveImportedModule(const void * buffer,size_t size,const CString & filename)450 JSHandle<JSTaggedValue> ModuleManager::HostResolveImportedModule(const void *buffer, size_t size,
451                                                                  const CString &filename)
452 {
453     JSThread *thread = vm_->GetJSThread();
454     ObjectFactory *factory = vm_->GetFactory();
455 
456     JSHandle<EcmaString> referencingHandle = factory->NewFromUtf8(filename);
457     NameDictionary *dict = NameDictionary::Cast(resolvedModules_.GetTaggedObject());
458     int entry = dict->FindEntry(referencingHandle.GetTaggedValue());
459     if (entry != -1) {
460         return JSHandle<JSTaggedValue>(thread, dict->GetValue(entry));
461     }
462 
463     std::shared_ptr<JSPandaFile> jsPandaFile =
464         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, filename,
465                                                            JSPandaFile::ENTRY_MAIN_FUNCTION, buffer, size);
466     if (jsPandaFile == nullptr) {
467         CString msg = "Load file with filename '" + filename + "' failed";
468         THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, JSTaggedValue, msg.c_str());
469     }
470 
471     return ResolveModule(thread, jsPandaFile.get());
472 }
473 
ResolveModule(JSThread * thread,const JSPandaFile * jsPandaFile,bool excuteFromJob)474 JSHandle<JSTaggedValue> ModuleManager::ResolveModule(JSThread *thread, const JSPandaFile *jsPandaFile,
475     bool excuteFromJob)
476 {
477     ObjectFactory *factory = vm_->GetFactory();
478     CString moduleFileName = jsPandaFile->GetJSPandaFileDesc();
479     JSHandle<JSTaggedValue> moduleRecord = thread->GlobalConstants()->GetHandledUndefined();
480     JSRecordInfo recordInfo = const_cast<JSPandaFile *>(jsPandaFile)->FindRecordInfo(JSPandaFile::ENTRY_FUNCTION_NAME);
481     if (jsPandaFile->IsModule(recordInfo)) {
482         moduleRecord = ModuleDataExtractor::ParseModule(thread, jsPandaFile, moduleFileName, moduleFileName);
483     } else if (jsPandaFile->IsJson(recordInfo)) {
484         moduleRecord = ModuleDataExtractor::ParseJsonModule(thread, jsPandaFile, moduleFileName);
485     } else {
486         ASSERT(jsPandaFile->IsCjs(recordInfo));
487         moduleRecord = ModuleDataExtractor::ParseCjsModule(thread, jsPandaFile);
488     }
489     ModuleDeregister::InitForDeregisterModule(moduleRecord, excuteFromJob);
490     JSHandle<NameDictionary> dict(thread, resolvedModules_);
491     JSHandle<JSTaggedValue> referencingHandle = JSHandle<JSTaggedValue>::Cast(factory->NewFromUtf8(moduleFileName));
492     resolvedModules_ =
493         NameDictionary::Put(thread, dict, referencingHandle, moduleRecord, PropertyAttributes::Default())
494         .GetTaggedValue();
495     return moduleRecord;
496 }
497 
ResolveNativeModule(const CString & moduleRequestName,ModuleTypes moduleType)498 JSHandle<JSTaggedValue> ModuleManager::ResolveNativeModule(const CString &moduleRequestName, ModuleTypes moduleType)
499 {
500     ObjectFactory *factory = vm_->GetFactory();
501     JSThread *thread = vm_->GetJSThread();
502 
503     JSHandle<JSTaggedValue> referencingModule(factory->NewFromUtf8(moduleRequestName));
504     JSHandle<JSTaggedValue> moduleRecord = ModuleDataExtractor::ParseNativeModule(thread,
505         moduleRequestName, moduleType);
506     JSHandle<NameDictionary> dict(thread, resolvedModules_);
507     resolvedModules_ = NameDictionary::Put(thread, dict, referencingModule, moduleRecord,
508         PropertyAttributes::Default()).GetTaggedValue();
509     return moduleRecord;
510 }
511 
ResolveModuleWithMerge(JSThread * thread,const JSPandaFile * jsPandaFile,const CString & recordName,bool excuteFromJob)512 JSHandle<JSTaggedValue> ModuleManager::ResolveModuleWithMerge(
513     JSThread *thread, const JSPandaFile *jsPandaFile, const CString &recordName, bool excuteFromJob)
514 {
515     ObjectFactory *factory = vm_->GetFactory();
516     CString moduleFileName = jsPandaFile->GetJSPandaFileDesc();
517     JSHandle<JSTaggedValue> moduleRecord = thread->GlobalConstants()->GetHandledUndefined();
518     JSRecordInfo recordInfo;
519     bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(recordName, recordInfo);
520     if (!hasRecord) {
521         CString msg = "cannot find record '" + recordName + "', please check the request path.'"
522                       + moduleFileName + "'.";
523         LOG_FULL(ERROR) << msg;
524         THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, JSTaggedValue, msg.c_str());
525     }
526     if (jsPandaFile->IsModule(recordInfo)) {
527         RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
528         moduleRecord = ModuleDataExtractor::ParseModule(thread, jsPandaFile, recordName, moduleFileName);
529     } else if (jsPandaFile->IsJson(recordInfo)) {
530         moduleRecord = ModuleDataExtractor::ParseJsonModule(thread, jsPandaFile, moduleFileName, recordName);
531     } else {
532         ASSERT(jsPandaFile->IsCjs(recordInfo));
533         RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
534         moduleRecord = ModuleDataExtractor::ParseCjsModule(thread, jsPandaFile);
535     }
536 
537     JSHandle<JSTaggedValue> recordNameHandle = JSHandle<JSTaggedValue>::Cast(factory->NewFromUtf8(recordName));
538     JSHandle<SourceTextModule>::Cast(moduleRecord)->SetEcmaModuleRecordName(thread, recordNameHandle);
539     ModuleDeregister::InitForDeregisterModule(moduleRecord, excuteFromJob);
540     return moduleRecord;
541 }
542 
AddResolveImportedModule(const JSPandaFile * jsPandaFile,const CString & referencingModule)543 void ModuleManager::AddResolveImportedModule(const JSPandaFile *jsPandaFile, const CString &referencingModule)
544 {
545     JSThread *thread = vm_->GetJSThread();
546     JSHandle<JSTaggedValue> moduleRecord =
547         ModuleDataExtractor::ParseModule(thread, jsPandaFile, referencingModule, referencingModule);
548     AddResolveImportedModule(referencingModule, moduleRecord);
549 }
550 
AddResolveImportedModule(const CString & referencingModule,JSHandle<JSTaggedValue> moduleRecord)551 void ModuleManager::AddResolveImportedModule(const CString &referencingModule, JSHandle<JSTaggedValue> moduleRecord)
552 {
553     JSThread *thread = vm_->GetJSThread();
554     ObjectFactory *factory = vm_->GetFactory();
555     JSHandle<JSTaggedValue> referencingHandle(factory->NewFromUtf8(referencingModule));
556     JSHandle<NameDictionary> dict(thread, resolvedModules_);
557     resolvedModules_ =
558         NameDictionary::Put(thread, dict, referencingHandle, moduleRecord, PropertyAttributes::Default())
559         .GetTaggedValue();
560 }
561 
GetModuleNamespace(int32_t index)562 JSTaggedValue ModuleManager::GetModuleNamespace(int32_t index)
563 {
564     JSTaggedValue currentModule = GetCurrentModule();
565     return GetModuleNamespaceInternal(index, currentModule);
566 }
567 
GetModuleNamespace(int32_t index,JSTaggedValue currentFunc)568 JSTaggedValue ModuleManager::GetModuleNamespace(int32_t index, JSTaggedValue currentFunc)
569 {
570     JSTaggedValue currentModule = JSFunction::Cast(currentFunc.GetTaggedObject())->GetModule();
571     return GetModuleNamespaceInternal(index, currentModule);
572 }
573 
GetModuleNamespaceInternal(int32_t index,JSTaggedValue currentModule)574 JSTaggedValue ModuleManager::GetModuleNamespaceInternal(int32_t index, JSTaggedValue currentModule)
575 {
576     if (currentModule.IsUndefined()) {
577         LOG_FULL(FATAL) << "GetModuleNamespace currentModule failed";
578         UNREACHABLE();
579     }
580     JSThread *thread = vm_->GetJSThread();
581     SourceTextModule *module = SourceTextModule::Cast(currentModule.GetTaggedObject());
582     JSTaggedValue requestedModule = module->GetRequestedModules();
583     JSTaggedValue moduleName = TaggedArray::Cast(requestedModule.GetTaggedObject())->Get(index);
584     JSTaggedValue moduleRecordName = module->GetEcmaModuleRecordName();
585     JSHandle<JSTaggedValue> requiredModule;
586     if (moduleRecordName.IsUndefined()) {
587         requiredModule = SourceTextModule::HostResolveImportedModule(thread,
588             JSHandle<SourceTextModule>(thread, module), JSHandle<JSTaggedValue>(thread, moduleName));
589     } else {
590         ASSERT(moduleRecordName.IsString());
591         requiredModule = SourceTextModule::HostResolveImportedModuleWithMerge(thread,
592             JSHandle<SourceTextModule>(thread, module), JSHandle<JSTaggedValue>(thread, moduleName));
593     }
594     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
595     JSHandle<SourceTextModule> requiredModuleST = JSHandle<SourceTextModule>::Cast(requiredModule);
596     ModuleTypes moduleType = requiredModuleST->GetTypes();
597     // if requiredModuleST is Native module
598     if (SourceTextModule::IsNativeModule(moduleType)) {
599         return SourceTextModule::Cast(requiredModuleST.GetTaggedValue())->GetModuleValue(thread, 0, false);
600     }
601     // if requiredModuleST is CommonJS
602     if (moduleType == ModuleTypes::CJS_MODULE) {
603         JSHandle<JSTaggedValue> cjsModuleName(thread,
604             SourceTextModule::GetModuleName(requiredModuleST.GetTaggedValue()));
605         return CjsModule::SearchFromModuleCache(thread, cjsModuleName).GetTaggedValue();
606     }
607     // if requiredModuleST is ESM
608     JSHandle<JSTaggedValue> moduleNamespace = SourceTextModule::GetModuleNamespace(thread, requiredModuleST);
609     ASSERT(moduleNamespace->IsModuleNamespace());
610     return moduleNamespace.GetTaggedValue();
611 }
612 
GetModuleNamespace(JSTaggedValue localName)613 JSTaggedValue ModuleManager::GetModuleNamespace(JSTaggedValue localName)
614 {
615     JSTaggedValue currentModule = GetCurrentModule();
616     return GetModuleNamespaceInternal(localName, currentModule);
617 }
618 
GetModuleNamespace(JSTaggedValue localName,JSTaggedValue currentFunc)619 JSTaggedValue ModuleManager::GetModuleNamespace(JSTaggedValue localName, JSTaggedValue currentFunc)
620 {
621     JSTaggedValue currentModule = JSFunction::Cast(currentFunc.GetTaggedObject())->GetModule();
622     return GetModuleNamespaceInternal(localName, currentModule);
623 }
624 
GetModuleNamespaceInternal(JSTaggedValue localName,JSTaggedValue currentModule)625 JSTaggedValue ModuleManager::GetModuleNamespaceInternal(JSTaggedValue localName, JSTaggedValue currentModule)
626 {
627     if (currentModule.IsUndefined()) {
628         LOG_FULL(FATAL) << "GetModuleNamespace currentModule failed";
629         UNREACHABLE();
630     }
631     JSTaggedValue moduleEnvironment = SourceTextModule::Cast(currentModule.GetTaggedObject())->GetEnvironment();
632     if (moduleEnvironment.IsUndefined()) {
633         return vm_->GetJSThread()->GlobalConstants()->GetUndefined();
634     }
635     int entry = NameDictionary::Cast(moduleEnvironment.GetTaggedObject())->FindEntry(localName);
636     if (entry == -1) {
637         return vm_->GetJSThread()->GlobalConstants()->GetUndefined();
638     }
639     JSTaggedValue moduleNamespace = NameDictionary::Cast(moduleEnvironment.GetTaggedObject())->GetValue(entry);
640     ASSERT(moduleNamespace.IsModuleNamespace());
641     return moduleNamespace;
642 }
643 
Iterate(const RootVisitor & v)644 void ModuleManager::Iterate(const RootVisitor &v)
645 {
646     v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&resolvedModules_)));
647     v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&cachedEmptyModule_)));
648 }
649 
GetRecordName(JSTaggedValue module)650 CString ModuleManager::GetRecordName(JSTaggedValue module)
651 {
652     CString entry = "";
653     if (module.IsString()) {
654         entry = ConvertToString(module);
655     }
656     if (module.IsSourceTextModule()) {
657         SourceTextModule *sourceTextModule = SourceTextModule::Cast(module.GetTaggedObject());
658         if (sourceTextModule->GetEcmaModuleRecordName().IsString()) {
659             entry = ConvertToString(sourceTextModule->GetEcmaModuleRecordName());
660         }
661     }
662     return entry;
663 }
664 
GetExportObjectIndex(EcmaVM * vm,JSHandle<SourceTextModule> ecmaModule,const std::string & key)665 int ModuleManager::GetExportObjectIndex(EcmaVM *vm, JSHandle<SourceTextModule> ecmaModule,
666                                         const std::string &key)
667 {
668     JSThread *thread = vm->GetJSThread();
669     JSHandle<TaggedArray> localExportEntries(thread, ecmaModule->GetLocalExportEntries());
670     size_t exportEntriesLen = localExportEntries->GetLength();
671     // 0: There's only one export value "default"
672     int index = 0;
673     JSMutableHandle<LocalExportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
674     if (exportEntriesLen > 1) { // 1:  The number of export objects exceeds 1
675         for (size_t idx = 0; idx < exportEntriesLen; idx++) {
676             ee.Update(localExportEntries->Get(idx));
677             if (EcmaStringAccessor(ee->GetExportName()).ToStdString() == key) {
678                 ASSERT(idx <= static_cast<size_t>(INT_MAX));
679                 index = static_cast<int>(ee->GetLocalIndex());
680                 break;
681             }
682         }
683     }
684     return index;
685 }
686 
HostResolveImportedModule(const JSPandaFile * jsPandaFile,const CString & filename)687 JSHandle<JSTaggedValue> ModuleManager::HostResolveImportedModule(const JSPandaFile *jsPandaFile,
688                                                                  const CString &filename)
689 {
690     JSThread *thread = vm_->GetJSThread();
691     JSHandle<EcmaString> referencingHandle = vm_->GetFactory()->NewFromUtf8(filename);
692     NameDictionary *dict = NameDictionary::Cast(resolvedModules_.GetTaggedObject());
693     int entry = dict->FindEntry(referencingHandle.GetTaggedValue());
694     if (entry != -1) {
695         return JSHandle<JSTaggedValue>(thread, dict->GetValue(entry));
696     }
697 
698     if (jsPandaFile == nullptr) {
699         CString msg = "Faild to resolve file '" + filename + "', please check the request path.";
700         THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, JSTaggedValue, msg.c_str());
701     }
702     return ResolveModule(thread, jsPandaFile);
703 }
704 } // namespace panda::ecmascript
705