• 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/interpreter/frame_handler.h"
18 #include "ecmascript/jspandafile/js_pandafile_executor.h"
19 #include "ecmascript/module/js_shared_module_manager.h"
20 #include "ecmascript/module/module_data_extractor.h"
21 #include "ecmascript/module/module_manager_helper.h"
22 #include "ecmascript/module/module_path_helper.h"
23 #include "ecmascript/module/module_tools.h"
24 #include "ecmascript/module/module_resolver.h"
25 #include "ecmascript/require/js_cjs_module.h"
26 
27 namespace panda::ecmascript {
28 using StringHelper = base::StringHelper;
29 using JSPandaFile = ecmascript::JSPandaFile;
30 using JSRecordInfo = ecmascript::JSPandaFile::JSRecordInfo;
31 
ModuleManager(EcmaVM * vm)32 ModuleManager::ModuleManager(EcmaVM *vm) : vm_(vm) {}
33 
GetCurrentModule()34 JSTaggedValue ModuleManager::GetCurrentModule()
35 {
36     FrameHandler frameHandler(vm_->GetJSThread());
37     JSTaggedValue currentFunc = frameHandler.GetFunction();
38     JSTaggedValue module = JSFunction::Cast(currentFunc.GetTaggedObject())->GetModule();
39     if (SourceTextModule::IsSendableFunctionModule(module)) {
40         CString recordNameStr = SourceTextModule::GetModuleName(module);
41         return HostGetImportedModule(recordNameStr).GetTaggedValue();
42     }
43     return module;
44 }
45 
GenerateSendableFuncModule(const JSHandle<JSTaggedValue> & module)46 JSHandle<JSTaggedValue> ModuleManager::GenerateSendableFuncModule(const JSHandle<JSTaggedValue> &module)
47 {
48     // Clone isolate module at shared-heap to mark sendable class.
49     return SendableClassModule::GenerateSendableFuncModule(vm_->GetJSThread(), module);
50 }
51 
GetModuleValueInner(int32_t index)52 JSTaggedValue ModuleManager::GetModuleValueInner(int32_t index)
53 {
54     JSTaggedValue currentModule = GetCurrentModule();
55     if (currentModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
56         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
57     }
58     return SourceTextModule::Cast(currentModule.GetTaggedObject())->GetModuleValue(vm_->GetJSThread(), index, false);
59 }
60 
GetModuleValueInner(int32_t index,JSTaggedValue jsFunc)61 JSTaggedValue ModuleManager::GetModuleValueInner(int32_t index, JSTaggedValue jsFunc)
62 {
63     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule();
64     if (currentModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
65         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
66     }
67     return SourceTextModule::Cast(currentModule.GetTaggedObject())->GetModuleValue(vm_->GetJSThread(), index, false);
68 }
69 
GetModuleValueInner(int32_t index,JSHandle<JSTaggedValue> currentModule)70 JSTaggedValue ModuleManager::GetModuleValueInner(int32_t index, JSHandle<JSTaggedValue> currentModule)
71 {
72     if (currentModule->IsUndefined()) { // LCOV_EXCL_BR_LINE
73         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
74     }
75     return SourceTextModule::Cast(currentModule->GetTaggedObject())->GetModuleValue(vm_->GetJSThread(), index, false);
76 }
77 
GetModuleValueOutter(int32_t index)78 JSTaggedValue ModuleManager::GetModuleValueOutter(int32_t index)
79 {
80     JSTaggedValue currentModule = GetCurrentModule();
81     return GetModuleValueOutterInternal(index, currentModule);
82 }
83 
GetModuleValueOutter(int32_t index,JSTaggedValue jsFunc)84 JSTaggedValue ModuleManager::GetModuleValueOutter(int32_t index, JSTaggedValue jsFunc)
85 {
86     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule();
87     return GetModuleValueOutterInternal(index, currentModule);
88 }
89 
GetModuleValueOutter(int32_t index,JSHandle<JSTaggedValue> currentModule)90 JSTaggedValue ModuleManager::GetModuleValueOutter(int32_t index, JSHandle<JSTaggedValue> currentModule)
91 {
92     return GetModuleValueOutterInternal(index, currentModule.GetTaggedValue());
93 }
94 
GetModuleValueOutterInternal(int32_t index,JSTaggedValue currentModule)95 JSTaggedValue ModuleManager::GetModuleValueOutterInternal(int32_t index, JSTaggedValue currentModule)
96 {
97     JSThread *thread = vm_->GetJSThread();
98     if (currentModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
99         LOG_FULL(FATAL) << "GetModuleValueOutter currentModule failed";
100         UNREACHABLE();
101     }
102     JSHandle<SourceTextModule> currentModuleHdl(thread, currentModule);
103     JSTaggedValue moduleEnvironment = currentModuleHdl->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     ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
110     if (moduleLogger != nullptr) {
111         return ModuleTools::ProcessModuleLoadInfo(thread, currentModuleHdl, resolvedBinding, index);
112     }
113     if (resolvedBinding.IsResolvedIndexBinding()) {
114         ResolvedIndexBinding *binding = ResolvedIndexBinding::Cast(resolvedBinding.GetTaggedObject());
115         JSTaggedValue resolvedModule = binding->GetModule();
116         JSHandle<SourceTextModule> module(thread, resolvedModule);
117         ASSERT(resolvedModule.IsSourceTextModule());
118 
119         // Support for only modifying var value of HotReload.
120         // Cause patchFile exclude the record of importing modifying var. Can't reresolve moduleRecord.
121         EcmaContext *context = thread->GetCurrentEcmaContext();
122         if (context->GetStageOfHotReload() == StageOfHotReload::LOAD_END_EXECUTE_PATCHMAIN) {
123             const JSHandle<JSTaggedValue> resolvedModuleOfHotReload =
124                 context->FindPatchModule(module->GetEcmaModuleRecordNameString());
125             if (!resolvedModuleOfHotReload->IsHole()) {
126                 resolvedModule = resolvedModuleOfHotReload.GetTaggedValue();
127                 JSHandle<SourceTextModule> moduleOfHotReload(thread, resolvedModule);
128                 return ModuleManagerHelper::GetModuleValue(thread, moduleOfHotReload, binding->GetIndex());
129             }
130         }
131         return ModuleManagerHelper::GetModuleValue(thread, module, binding->GetIndex());
132     }
133     if (resolvedBinding.IsResolvedBinding()) {
134         ResolvedBinding *binding = ResolvedBinding::Cast(resolvedBinding.GetTaggedObject());
135         JSTaggedValue resolvedModule = binding->GetModule();
136         JSHandle<SourceTextModule> module(thread, resolvedModule);
137         if (SourceTextModule::IsNativeModule(module->GetTypes()) || SourceTextModule::IsCjsModule(module->GetTypes())) {
138             return ModuleManagerHelper::UpdateBindingAndGetModuleValue(
139                 thread, currentModuleHdl, module, index, binding->GetBindingName());
140         }
141     }
142     if (resolvedBinding.IsResolvedRecordIndexBinding()) {
143         return ModuleManagerHelper::GetModuleValueFromIndexBinding(thread, currentModuleHdl, resolvedBinding);
144     }
145     if (resolvedBinding.IsResolvedRecordBinding()) { // LCOV_EXCL_BR_LINE
146         return ModuleManagerHelper::GetModuleValueFromRecordBinding(thread, currentModuleHdl, resolvedBinding);
147     }
148 
149     std::ostringstream oss;
150     currentModule.Dump(oss);
151     LOG_ECMA(FATAL) << "Get module value failed, mistaken ResolvedBinding"
152         << ", index: " << index << ", currentModule: " << oss.str();
153     UNREACHABLE();
154 }
155 
GetLazyModuleValueOutter(int32_t index,JSTaggedValue jsFunc)156 JSTaggedValue ModuleManager::GetLazyModuleValueOutter(int32_t index, JSTaggedValue jsFunc)
157 {
158     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule();
159     return GetLazyModuleValueOutterInternal(index, currentModule);
160 }
161 
GetLazyModuleValueOutterInternal(int32_t index,JSTaggedValue currentModule)162 JSTaggedValue ModuleManager::GetLazyModuleValueOutterInternal(int32_t index, JSTaggedValue currentModule)
163 {
164     JSThread *thread = vm_->GetJSThread();
165     if (currentModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
166         LOG_FULL(FATAL) << "GetLazyModuleValueOutter currentModule failed";
167         UNREACHABLE();
168     }
169     JSHandle<SourceTextModule> currentModuleHdl(thread, currentModule);
170     JSTaggedValue moduleEnvironment = currentModuleHdl->GetEnvironment();
171     if (moduleEnvironment.IsUndefined()) {
172         return thread->GlobalConstants()->GetUndefined();
173     }
174     ASSERT(moduleEnvironment.IsTaggedArray());
175     JSTaggedValue resolvedBinding = TaggedArray::Cast(moduleEnvironment.GetTaggedObject())->Get(index);
176     ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
177     if (moduleLogger != nullptr) {
178         return ModuleTools::ProcessLazyModuleLoadInfo(thread, currentModuleHdl, resolvedBinding, index);
179     }
180     if (resolvedBinding.IsResolvedIndexBinding()) {
181         JSHandle<ResolvedIndexBinding> binding(thread, resolvedBinding);
182         JSTaggedValue resolvedModule = binding->GetModule();
183         JSMutableHandle<SourceTextModule> module(thread, resolvedModule);
184         ASSERT(resolvedModule.IsSourceTextModule());
185         // Support for only modifying var value of HotReload.
186         // Cause patchFile exclude the record of importing modifying var. Can't reresolve moduleRecord.
187         EcmaContext *context = thread->GetCurrentEcmaContext();
188         if (context->GetStageOfHotReload() == StageOfHotReload::LOAD_END_EXECUTE_PATCHMAIN) {
189             const JSHandle<JSTaggedValue> resolvedModuleOfHotReload =
190                 context->FindPatchModule(module->GetEcmaModuleRecordNameString());
191             if (!resolvedModuleOfHotReload->IsHole()) {
192                 resolvedModule = resolvedModuleOfHotReload.GetTaggedValue();
193                 module.Update(resolvedModule);
194             }
195         }
196         if (module->GetStatus() < ModuleStatus::EVALUATED) {
197             SourceTextModule::Evaluate(thread, module, nullptr, 0, ExecuteTypes::LAZY);
198         }
199         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
200         return ModuleManagerHelper::GetModuleValue(thread, module, binding->GetIndex());
201     }
202     if (resolvedBinding.IsResolvedBinding()) {
203         JSHandle<ResolvedBinding> binding(thread, resolvedBinding);
204         JSTaggedValue resolvedModule = binding->GetModule();
205         JSHandle<SourceTextModule> module(thread, resolvedModule);
206         ModuleTypes moduleType = module->GetTypes();
207         if (SourceTextModule::IsNativeModule(moduleType)) {
208             SourceTextModule::EvaluateNativeModule(thread, module, moduleType);
209             return ModuleManagerHelper::UpdateBindingAndGetModuleValue(
210                 thread, currentModuleHdl, module, index, binding->GetBindingName());
211         }
212         if (SourceTextModule::IsCjsModule(moduleType)) {
213             ModuleStatus status = module->GetStatus();
214             if (status < ModuleStatus::EVALUATED) {
215                 SourceTextModule::ModuleExecution(thread, module, nullptr, 0);
216                 SourceTextModule::RecordEvaluatedOrError(thread, module);
217                 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
218             }
219             return ModuleManagerHelper::UpdateBindingAndGetModuleValue(
220                 thread, currentModuleHdl, module, index, binding->GetBindingName());
221         }
222     }
223     if (resolvedBinding.IsResolvedRecordIndexBinding()) {
224         return ModuleManagerHelper::GetLazyModuleValueFromIndexBinding(thread, currentModuleHdl, resolvedBinding);
225     }
226     if (resolvedBinding.IsResolvedRecordBinding()) { // LCOV_EXCL_BR_LINE
227         return ModuleManagerHelper::GetLazyModuleValueFromRecordBinding(thread, currentModuleHdl, resolvedBinding);
228     }
229     LOG_ECMA(FATAL) << "Get module value failed, mistaken ResolvedBinding";
230     UNREACHABLE();
231 }
232 
StoreModuleValue(int32_t index,JSTaggedValue value)233 void ModuleManager::StoreModuleValue(int32_t index, JSTaggedValue value)
234 {
235     JSThread *thread = vm_->GetJSThread();
236     JSHandle<SourceTextModule> currentModule(thread, GetCurrentModule());
237     StoreModuleValueInternal(currentModule, index, value);
238 }
239 
StoreModuleValue(int32_t index,JSTaggedValue value,JSTaggedValue jsFunc)240 void ModuleManager::StoreModuleValue(int32_t index, JSTaggedValue value, JSTaggedValue jsFunc)
241 {
242     JSThread *thread = vm_->GetJSThread();
243     JSHandle<SourceTextModule> currentModule(thread, JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule());
244     StoreModuleValueInternal(currentModule, index, value);
245 }
246 
StoreModuleValueInternal(JSHandle<SourceTextModule> & currentModule,int32_t index,JSTaggedValue value)247 void ModuleManager::StoreModuleValueInternal(JSHandle<SourceTextModule> &currentModule,
248                                              int32_t index, JSTaggedValue value)
249 {
250     if (currentModule.GetTaggedValue().IsUndefined()) { // LCOV_EXCL_BR_LINE
251         LOG_FULL(FATAL) << "StoreModuleValue currentModule failed";
252         UNREACHABLE();
253     }
254     JSThread *thread = vm_->GetJSThread();
255     JSHandle<JSTaggedValue> valueHandle(thread, value);
256     SourceTextModule::StoreModuleValue(thread, currentModule, index, valueHandle);
257 }
258 
GetModuleValueInner(JSTaggedValue key)259 JSTaggedValue ModuleManager::GetModuleValueInner(JSTaggedValue key)
260 {
261     JSTaggedValue currentModule = GetCurrentModule();
262     if (currentModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
263         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
264         UNREACHABLE();
265     }
266     return SourceTextModule::Cast(currentModule.GetTaggedObject())->GetModuleValue(vm_->GetJSThread(), key, false);
267 }
268 
GetModuleValueInner(JSTaggedValue key,JSTaggedValue jsFunc)269 JSTaggedValue ModuleManager::GetModuleValueInner(JSTaggedValue key, JSTaggedValue jsFunc)
270 {
271     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule();
272     if (currentModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
273         LOG_FULL(FATAL) << "GetModuleValueInner currentModule failed";
274         UNREACHABLE();
275     }
276     return SourceTextModule::Cast(currentModule.GetTaggedObject())->GetModuleValue(vm_->GetJSThread(), key, false);
277 }
278 
GetModuleValueOutter(JSTaggedValue key)279 JSTaggedValue ModuleManager::GetModuleValueOutter(JSTaggedValue key)
280 {
281     JSTaggedValue currentModule = GetCurrentModule();
282     return GetModuleValueOutterInternal(key, currentModule);
283 }
284 
GetModuleValueOutter(JSTaggedValue key,JSTaggedValue jsFunc)285 JSTaggedValue ModuleManager::GetModuleValueOutter(JSTaggedValue key, JSTaggedValue jsFunc)
286 {
287     JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule();
288     return GetModuleValueOutterInternal(key, currentModule);
289 }
290 
GetModuleValueOutterInternal(JSTaggedValue key,JSTaggedValue currentModule)291 JSTaggedValue ModuleManager::GetModuleValueOutterInternal(JSTaggedValue key, JSTaggedValue currentModule)
292 {
293     JSThread *thread = vm_->GetJSThread();
294     if (currentModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
295         LOG_FULL(FATAL) << "GetModuleValueOutter currentModule failed";
296         UNREACHABLE();
297     }
298     JSTaggedValue moduleEnvironment = SourceTextModule::Cast(currentModule.GetTaggedObject())->GetEnvironment();
299     if (moduleEnvironment.IsUndefined()) {
300         return thread->GlobalConstants()->GetUndefined();
301     }
302     int entry = NameDictionary::Cast(moduleEnvironment.GetTaggedObject())->FindEntry(key);
303     if (entry == -1) {
304         return thread->GlobalConstants()->GetUndefined();
305     }
306     JSTaggedValue resolvedBinding = NameDictionary::Cast(moduleEnvironment.GetTaggedObject())->GetValue(entry);
307     ASSERT(resolvedBinding.IsResolvedBinding());
308     ResolvedBinding *binding = ResolvedBinding::Cast(resolvedBinding.GetTaggedObject());
309     JSTaggedValue resolvedModule = binding->GetModule();
310     ASSERT(resolvedModule.IsSourceTextModule());
311     SourceTextModule *module = SourceTextModule::Cast(resolvedModule.GetTaggedObject());
312     if (module->GetTypes() == ModuleTypes::CJS_MODULE) {
313         CString cjsModuleName = SourceTextModule::GetModuleName(JSTaggedValue(module));
314         JSHandle<JSTaggedValue> moduleNameHandle(thread->GetEcmaVM()->GetFactory()->NewFromUtf8(cjsModuleName));
315         return CjsModule::SearchFromModuleCache(thread, moduleNameHandle).GetTaggedValue();
316     }
317     return module->GetModuleValue(thread, binding->GetBindingName(), false);
318 }
319 
StoreModuleValue(JSTaggedValue key,JSTaggedValue value)320 void ModuleManager::StoreModuleValue(JSTaggedValue key, JSTaggedValue value)
321 {
322     JSThread *thread = vm_->GetJSThread();
323     JSHandle<SourceTextModule> currentModule(thread, GetCurrentModule());
324     StoreModuleValueInternal(currentModule, key, value);
325 }
326 
StoreModuleValue(JSTaggedValue key,JSTaggedValue value,JSTaggedValue jsFunc)327 void ModuleManager::StoreModuleValue(JSTaggedValue key, JSTaggedValue value, JSTaggedValue jsFunc)
328 {
329     JSThread *thread = vm_->GetJSThread();
330     JSHandle<SourceTextModule> currentModule(thread, JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule());
331     StoreModuleValueInternal(currentModule, key, value);
332 }
333 
StoreModuleValueInternal(JSHandle<SourceTextModule> & currentModule,JSTaggedValue key,JSTaggedValue value)334 void ModuleManager::StoreModuleValueInternal(JSHandle<SourceTextModule> &currentModule,
335                                              JSTaggedValue key, JSTaggedValue value)
336 {
337     if (currentModule.GetTaggedValue().IsUndefined()) { // LCOV_EXCL_BR_LINE
338         LOG_FULL(FATAL) << "StoreModuleValue currentModule failed";
339         UNREACHABLE();
340     }
341     JSThread *thread = vm_->GetJSThread();
342     JSHandle<JSTaggedValue> keyHandle(thread, key);
343     JSHandle<JSTaggedValue> valueHandle(thread, value);
344     SourceTextModule::StoreModuleValue(thread, currentModule, keyHandle, valueHandle);
345 }
GetImportedModule(const CString & referencing)346 JSHandle<SourceTextModule> ModuleManager::GetImportedModule(const CString &referencing)
347 {
348     auto thread = vm_->GetJSThread();
349     if (!IsLocalModuleLoaded(referencing)) {
350         return SharedModuleManager::GetInstance()->GetSModule(thread, referencing);
351     } else {
352         return HostGetImportedModule(referencing);
353     }
354 }
355 
HostGetImportedModule(const CString & referencing)356 JSHandle<SourceTextModule> ModuleManager::HostGetImportedModule(const CString &referencing)
357 {
358     auto entry = resolvedModules_.find(referencing);
359     if (entry == resolvedModules_.end()) { // LCOV_EXCL_BR_LINE
360         LOG_ECMA(FATAL) << "Can not get module: " << referencing;
361     }
362     return JSHandle<SourceTextModule>(vm_->GetJSThread(), entry->second);
363 }
364 
HostGetImportedModule(void * src)365 JSTaggedValue ModuleManager::HostGetImportedModule(void *src)
366 {
367     const char *str = reinterpret_cast<char *>(src);
368     CString referencing(str, strlen(str));
369     LOG_FULL(INFO) << "current str during module deregister process : " << referencing;
370     auto entry = resolvedModules_.find(referencing);
371     if (entry == resolvedModules_.end()) {
372         LOG_FULL(INFO) << "The module has been unloaded, " << referencing;
373         return JSTaggedValue::Undefined();
374     }
375     JSTaggedValue result = entry->second;
376     return result;
377 }
378 
IsLocalModuleLoaded(const CString & referencing)379 bool ModuleManager::IsLocalModuleLoaded(const CString& referencing)
380 {
381     auto entry = resolvedModules_.find(referencing);
382     if (entry == resolvedModules_.end()) {
383         return false;
384     }
385     return true;
386 }
387 
IsSharedModuleLoaded(const CString & referencing)388 bool ModuleManager::IsSharedModuleLoaded(const CString &referencing)
389 {
390     SharedModuleManager* sharedModuleManager = SharedModuleManager::GetInstance();
391     return sharedModuleManager->SearchInSModuleManager(vm_->GetJSThread(), referencing);
392 }
393 
IsModuleLoaded(const CString & referencing)394 bool ModuleManager::IsModuleLoaded(const CString &referencing)
395 {
396     if (IsLocalModuleLoaded(referencing)) {
397         return true;
398     }
399     SharedModuleManager* sharedModuleManager = SharedModuleManager::GetInstance();
400     return sharedModuleManager->SearchInSModuleManager(vm_->GetJSThread(), referencing);
401 }
402 
IsEvaluatedModule(const CString & referencing)403 bool ModuleManager::IsEvaluatedModule(const CString &referencing)
404 {
405     auto entry = resolvedModules_.find(referencing);
406     if (entry == resolvedModules_.end()) {
407         return false;
408     }
409     JSTaggedValue result = entry->second;
410     // ModuleStatus == (EVALUATED || ERRORED).
411     if (SourceTextModule::Cast(result.GetTaggedObject())->GetStatus() >= ModuleStatus::EVALUATED) {
412         return true;
413     }
414     return false;
415 }
416 
417 // This function assumes that referencing already existed in resolvedModules_/resolvedSharedModules_.
IsInstantiatedModule(const CString & referencing)418 bool ModuleManager::IsInstantiatedModule(const CString &referencing)
419 {
420     JSHandle<SourceTextModule> module = GetImportedModule(referencing);
421     return module->GetStatus() == ModuleStatus::INSTANTIATED;
422 }
423 
IsLocalModuleInstantiated(const CString & referencing)424 bool ModuleManager::IsLocalModuleInstantiated(const CString &referencing)
425 {
426     JSHandle<SourceTextModule> module = HostGetImportedModule(referencing);
427     return module->GetStatus() == ModuleStatus::INSTANTIATED;
428 }
429 
NeedExecuteModule(const CString & referencing)430 bool ModuleManager::NeedExecuteModule(const CString &referencing)
431 {
432     if (IsModuleLoaded(referencing)) {
433         JSHandle<SourceTextModule> module = GetImportedModule(referencing);
434         return module->GetStatus() == ModuleStatus::INSTANTIATED;
435     }
436     return true;
437 }
438 
AddToInstantiatingSModuleList(const CString & record)439 void ModuleManager::AddToInstantiatingSModuleList(const CString &record)
440 {
441     InstantiatingSModuleList_.push_back(record);
442 }
443 
GetInstantiatingSModuleList()444 CVector<CString> ModuleManager::GetInstantiatingSModuleList()
445 {
446     return InstantiatingSModuleList_;
447 }
448 
ClearInstantiatingSModuleList()449 void ModuleManager::ClearInstantiatingSModuleList()
450 {
451     InstantiatingSModuleList_.clear();
452 }
453 
GetModuleNamespace(int32_t index)454 JSTaggedValue ModuleManager::GetModuleNamespace(int32_t index)
455 {
456     JSTaggedValue currentModule = GetCurrentModule();
457     return GetModuleNamespaceInternal(index, currentModule);
458 }
459 
GetModuleNamespace(int32_t index,JSTaggedValue currentFunc)460 JSTaggedValue ModuleManager::GetModuleNamespace(int32_t index, JSTaggedValue currentFunc)
461 {
462     JSTaggedValue currentModule = JSFunction::Cast(currentFunc.GetTaggedObject())->GetModule();
463     return GetModuleNamespaceInternal(index, currentModule);
464 }
465 
GetModuleNamespaceInternal(int32_t index,JSTaggedValue currentModule)466 JSTaggedValue ModuleManager::GetModuleNamespaceInternal(int32_t index, JSTaggedValue currentModule)
467 {
468     if (currentModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
469         LOG_FULL(FATAL) << "GetModuleNamespace currentModule failed";
470         UNREACHABLE();
471     }
472     JSThread *thread = vm_->GetJSThread();
473     JSHandle<SourceTextModule> module(thread, SourceTextModule::Cast(currentModule));
474     JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules());
475     JSHandle<SourceTextModule> requiredModule = JSHandle<SourceTextModule>::Cast(
476         SourceTextModule::GetRequestedModule(thread, module, requestedModules, index));
477     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
478 
479     ModuleLogger *moduleLogger = thread->GetCurrentEcmaContext()->GetModuleLogger();
480     if (moduleLogger != nullptr) {
481         return ModuleTools::ProcessModuleNameSpaceLoadInfo(thread, module, requiredModule);
482     }
483     ModuleTypes moduleType = requiredModule->GetTypes();
484     // if requiredModule is Native module
485     if (SourceTextModule::IsNativeModule(moduleType)) {
486         return requiredModule->GetModuleValue(thread, 0, false);
487     }
488     // if requiredModule is CommonJS
489     if (SourceTextModule::IsCjsModule(moduleType)) {
490         CString cjsModuleName = SourceTextModule::GetModuleName(requiredModule.GetTaggedValue());
491         JSHandle<JSTaggedValue> moduleNameHandle(thread->GetEcmaVM()->GetFactory()->NewFromUtf8(cjsModuleName));
492         return CjsModule::SearchFromModuleCache(thread, moduleNameHandle).GetTaggedValue();
493     }
494     // if requiredModule is ESM
495     JSHandle<JSTaggedValue> moduleNamespace = SourceTextModule::GetModuleNamespace(thread, requiredModule);
496     ASSERT(moduleNamespace->IsModuleNamespace());
497     return moduleNamespace.GetTaggedValue();
498 }
499 
GetModuleNamespace(JSTaggedValue localName)500 JSTaggedValue ModuleManager::GetModuleNamespace(JSTaggedValue localName)
501 {
502     JSTaggedValue currentModule = GetCurrentModule();
503     return GetModuleNamespaceInternal(localName, currentModule);
504 }
505 
GetModuleNamespace(JSTaggedValue localName,JSTaggedValue currentFunc)506 JSTaggedValue ModuleManager::GetModuleNamespace(JSTaggedValue localName, JSTaggedValue currentFunc)
507 {
508     JSTaggedValue currentModule = JSFunction::Cast(currentFunc.GetTaggedObject())->GetModule();
509     return GetModuleNamespaceInternal(localName, currentModule);
510 }
511 
GetModuleNamespaceInternal(JSTaggedValue localName,JSTaggedValue currentModule)512 JSTaggedValue ModuleManager::GetModuleNamespaceInternal(JSTaggedValue localName, JSTaggedValue currentModule)
513 {
514     if (currentModule.IsUndefined()) { // LCOV_EXCL_BR_LINE
515         LOG_FULL(FATAL) << "GetModuleNamespace currentModule failed";
516         UNREACHABLE();
517     }
518     JSTaggedValue moduleEnvironment = SourceTextModule::Cast(currentModule.GetTaggedObject())->GetEnvironment();
519     if (moduleEnvironment.IsUndefined()) {
520         return vm_->GetJSThread()->GlobalConstants()->GetUndefined();
521     }
522     int entry = NameDictionary::Cast(moduleEnvironment.GetTaggedObject())->FindEntry(localName);
523     if (entry == -1) {
524         return vm_->GetJSThread()->GlobalConstants()->GetUndefined();
525     }
526     JSTaggedValue moduleNamespace = NameDictionary::Cast(moduleEnvironment.GetTaggedObject())->GetValue(entry);
527     ASSERT(moduleNamespace.IsModuleNamespace());
528     return moduleNamespace;
529 }
530 
Iterate(RootVisitor & v)531 void ModuleManager::Iterate(RootVisitor &v)
532 {
533     for (auto &it : resolvedModules_) {
534         ObjectSlot slot(reinterpret_cast<uintptr_t>(&it.second));
535         v.VisitRoot(Root::ROOT_VM, slot);
536         ASSERT(slot.GetTaggedValue() == it.second);
537     }
538 }
539 
GetRecordName(JSTaggedValue module)540 CString ModuleManager::GetRecordName(JSTaggedValue module)
541 {
542     CString entry = "";
543     if (module.IsString()) {
544         entry = ModulePathHelper::Utf8ConvertToString(module);
545     }
546     if (module.IsSourceTextModule()) {
547         SourceTextModule *sourceTextModule = SourceTextModule::Cast(module.GetTaggedObject());
548         CString recordName = sourceTextModule->GetEcmaModuleRecordNameString();
549         if (!recordName.empty()) {
550             return recordName;
551         }
552     }
553     return entry;
554 }
555 
GetExportObjectIndex(EcmaVM * vm,JSHandle<SourceTextModule> ecmaModule,const CString & key)556 int ModuleManager::GetExportObjectIndex(EcmaVM *vm, JSHandle<SourceTextModule> ecmaModule,
557                                         const CString &key)
558 {
559     JSThread *thread = vm->GetJSThread();
560     if (ecmaModule->GetLocalExportEntries().IsUndefined()) {
561         CString msg = "No export named '" + key;
562         if (!ecmaModule->GetEcmaModuleRecordNameString().empty()) {
563             msg += "' which exported by '" + ecmaModule->GetEcmaModuleRecordNameString() + "'";
564         } else {
565             msg += "' which exported by '" + ecmaModule->GetEcmaModuleFilenameString() + "'";
566         }
567         ObjectFactory *factory = vm->GetFactory();
568         JSTaggedValue error = factory->GetJSError(ErrorType::SYNTAX_ERROR, msg.c_str(),
569                                                   StackCheck::NO).GetTaggedValue();
570         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, 0);
571     }
572     JSHandle<TaggedArray> localExportEntries(thread, ecmaModule->GetLocalExportEntries());
573     size_t exportEntriesLen = localExportEntries->GetLength();
574     // 0: There's only one export value "default"
575     int index = 0;
576     JSMutableHandle<LocalExportEntry> ee(thread, thread->GlobalConstants()->GetUndefined());
577     if (exportEntriesLen > 1) { // 1:  The number of export objects exceeds 1
578         for (size_t idx = 0; idx < exportEntriesLen; idx++) {
579             ee.Update(localExportEntries->Get(idx));
580             if (EcmaStringAccessor(ee->GetExportName()).Utf8ConvertToString() == key) {
581                 ASSERT(idx <= static_cast<size_t>(INT_MAX));
582                 index = static_cast<int>(ee->GetLocalIndex());
583                 break;
584             }
585         }
586     }
587     return index;
588 }
589 
LoadNativeModule(JSThread * thread,const CString & key)590 JSHandle<JSTaggedValue> ModuleManager::LoadNativeModule(JSThread *thread, const CString &key)
591 {
592     JSHandle<SourceTextModule> ecmaModule = JSHandle<SourceTextModule>::Cast(ExecuteNativeModule(thread, key));
593     ASSERT(ecmaModule->GetIsNewBcVersion());
594     int index = GetExportObjectIndex(vm_, ecmaModule, key);
595     JSTaggedValue result = ecmaModule->GetModuleValue(thread, index, false);
596     return JSHandle<JSTaggedValue>(thread, result);
597 }
598 
ExecuteNativeModuleMayThrowError(JSThread * thread,const CString & recordName)599 JSHandle<JSTaggedValue> ModuleManager::ExecuteNativeModuleMayThrowError(JSThread *thread, const CString &recordName)
600 {
601     JSMutableHandle<JSTaggedValue> requiredModule(thread, thread->GlobalConstants()->GetUndefined());
602     if (IsEvaluatedModule(recordName)) {
603         JSHandle<SourceTextModule> moduleRecord = HostGetImportedModule(recordName);
604         return JSHandle<JSTaggedValue>(thread, moduleRecord->GetModuleValue(thread, 0, false));
605     }
606 
607     ModuleTypes moduleType = SourceTextModule::GetNativeModuleType(recordName);
608     JSHandle<JSTaggedValue> moduleRecord = ModuleDataExtractor::ParseNativeModule(thread,
609         recordName, "", moduleType);
610     JSHandle<SourceTextModule> nativeModule =
611         JSHandle<SourceTextModule>::Cast(moduleRecord);
612     auto exportObject = SourceTextModule::LoadNativeModuleMayThrowError(thread, nativeModule, moduleType);
613     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread,
614         JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
615     SourceTextModule::RecordEvaluatedOrError(thread, nativeModule);
616     nativeModule->SetLoadingTypes(LoadingTypes::STABLE_MODULE);
617     SourceTextModule::StoreModuleValue(thread, nativeModule, 0, JSNApiHelper::ToJSHandle(exportObject));
618     AddResolveImportedModule(recordName, moduleRecord.GetTaggedValue());
619     return JSNApiHelper::ToJSHandle(exportObject);
620 }
621 
ExecuteNativeModule(JSThread * thread,const CString & recordName)622 JSHandle<JSTaggedValue> ModuleManager::ExecuteNativeModule(JSThread *thread, const CString &recordName)
623 {
624     JSMutableHandle<JSTaggedValue> requiredModule(thread, thread->GlobalConstants()->GetUndefined());
625     if (IsEvaluatedModule(recordName)) {
626         JSHandle<SourceTextModule> moduleRecord = HostGetImportedModule(recordName);
627         requiredModule.Update(moduleRecord);
628     } else if (IsLocalModuleLoaded(recordName)) {
629         JSHandle<SourceTextModule> nativeModule = HostGetImportedModule(recordName);
630         SourceTextModule::EvaluateNativeModule(thread, nativeModule, nativeModule->GetTypes());
631         nativeModule->SetLoadingTypes(LoadingTypes::STABLE_MODULE);
632         requiredModule.Update(nativeModule);
633     } else {
634         ModuleTypes moduleType = SourceTextModule::GetNativeModuleType(recordName);
635         JSHandle<JSTaggedValue> nativeModuleHandle =
636             ModuleResolver::ResolveNativeModule(thread, recordName, "", moduleType);
637         JSHandle<SourceTextModule> nativeModule =
638             JSHandle<SourceTextModule>::Cast(nativeModuleHandle);
639         SourceTextModule::EvaluateNativeModule(thread, nativeModule, moduleType);
640         nativeModule->SetLoadingTypes(LoadingTypes::STABLE_MODULE);
641         requiredModule.Update(nativeModule);
642     }
643     AddResolveImportedModule(recordName, requiredModule.GetTaggedValue());
644     return requiredModule;
645 }
646 
ExecuteJsonModule(JSThread * thread,const CString & recordName,const CString & filename,const JSPandaFile * jsPandaFile)647 JSHandle<JSTaggedValue> ModuleManager::ExecuteJsonModule(JSThread *thread, const CString &recordName,
648     const CString &filename, const JSPandaFile *jsPandaFile)
649 {
650     JSMutableHandle<JSTaggedValue> requiredModule(thread, thread->GlobalConstants()->GetUndefined());
651     if (IsEvaluatedModule(recordName)) {
652         JSHandle<SourceTextModule> moduleRecord = HostGetImportedModule(recordName);
653         requiredModule.Update(moduleRecord);
654     } else {
655         JSHandle<SourceTextModule> moduleRecord =
656             JSHandle<SourceTextModule>::Cast(ModuleDataExtractor::ParseJsonModule(thread, jsPandaFile, filename,
657                                                                                   recordName));
658         SourceTextModule::RecordEvaluatedOrError(thread, moduleRecord);
659         requiredModule.Update(moduleRecord);
660         UpdateResolveImportedModule(recordName, moduleRecord.GetTaggedValue());
661     }
662     return requiredModule;
663 }
664 
ExecuteCjsModule(JSThread * thread,const CString & recordName,const JSPandaFile * jsPandaFile)665 JSHandle<JSTaggedValue> ModuleManager::ExecuteCjsModule(JSThread *thread, const CString &recordName,
666     const JSPandaFile *jsPandaFile)
667 {
668     CString entryPoint = JSPandaFile::ENTRY_FUNCTION_NAME;
669     CString moduleRecord = jsPandaFile->GetJSPandaFileDesc();
670     if (!jsPandaFile->IsBundlePack()) {
671         entryPoint = recordName;
672         moduleRecord = recordName;
673     }
674 
675     JSMutableHandle<JSTaggedValue> requiredModule(thread, thread->GlobalConstants()->GetUndefined());
676     if (IsEvaluatedModule(moduleRecord)) {
677         requiredModule.Update(HostGetImportedModule(moduleRecord));
678     } else {
679         JSHandle<SourceTextModule> module =
680             JSHandle<SourceTextModule>::Cast(ModuleDataExtractor::ParseCjsModule(thread, jsPandaFile));
681         module->SetEcmaModuleRecordNameString(moduleRecord);
682         requiredModule.Update(module);
683         AddResolveImportedModule(recordName, module.GetTaggedValue());
684         JSPandaFileExecutor::Execute(thread, jsPandaFile, entryPoint);
685         SourceTextModule::RecordEvaluatedOrError(thread, JSHandle<SourceTextModule>::Cast(requiredModule));
686         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, requiredModule);
687         UpdateResolveImportedModule(recordName, module.GetTaggedValue());
688     }
689     return requiredModule;
690 }
691 
TryGetImportedModule(const CString & referencing)692 JSHandle<JSTaggedValue> ModuleManager::TryGetImportedModule(const CString& referencing)
693 {
694     JSThread *thread = vm_->GetJSThread();
695     auto entry = resolvedModules_.find(referencing);
696     if (entry == resolvedModules_.end()) {
697         return thread->GlobalConstants()->GetHandledUndefined();
698     }
699     return JSHandle<JSTaggedValue>(thread, entry->second);
700 }
701 
RemoveModuleFromCache(const CString & recordName)702 void ModuleManager::RemoveModuleFromCache(const CString& recordName)
703 {
704     auto entry = resolvedModules_.find(recordName);
705     if (entry == resolvedModules_.end()) { // LCOV_EXCL_BR_LINE
706         LOG_ECMA(FATAL) << "Can not get module: " << recordName <<
707             ", when try to remove the module";
708     }
709     JSTaggedValue result = entry->second;
710     SourceTextModule::Cast(result)->DestoryLazyImportArray();
711     SourceTextModule::Cast(result)->DestoryEcmaModuleFilenameString();
712     SourceTextModule::Cast(result)->DestoryEcmaModuleRecordNameString();
713     resolvedModules_.erase(recordName);
714 }
715 
716 // this function only remove module's name from resolvedModules List, it's content still needed by sharedmodule
RemoveModuleNameFromList(const CString & recordName)717 void ModuleManager::RemoveModuleNameFromList(const CString& recordName)
718 {
719     auto entry = resolvedModules_.find(recordName);
720     if (entry == resolvedModules_.end()) { // LCOV_EXCL_BR_LINE
721         LOG_ECMA(FATAL) << "Can not get module: " << recordName <<
722             ", when try to remove the module";
723     }
724     resolvedModules_.erase(recordName);
725 }
726 } // namespace panda::ecmascript
727