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