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