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> ¤tModule,
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> ¤tModule,
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