• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 
16 #include "ecmascript/jspandafile/js_pandafile_executor.h"
17 
18 #include "ecmascript/js_file_path.h"
19 #include "ecmascript/jspandafile/abc_buffer_cache.h"
20 #include "ecmascript/jspandafile/program_object.h"
21 #include "ecmascript/module/module_path_helper.h"
22 #include "ecmascript/checkpoint/thread_state_transition.h"
23 
24 namespace panda::ecmascript {
25 using PathHelper = base::PathHelper;
26 
27 // use "@bundle" as ohmurl's rules, will be abandon later
ParseAbcEntryPoint(JSThread * thread,const CString & filename,std::string_view entryPoint)28 std::pair<CString, CString> JSPandaFileExecutor::ParseAbcEntryPoint(JSThread *thread, const CString &filename,
29     [[maybe_unused]] std::string_view entryPoint)
30 {
31     CString name;
32     CString entry;
33     [[maybe_unused]] EcmaVM *vm = thread->GetEcmaVM();
34 #if defined(PANDA_TARGET_LINUX) || defined(OHOS_UNIT_TEST) || defined(PANDA_TARGET_MACOS)
35     return {filename, entryPoint.data()};
36 #else
37     CString normalName = PathHelper::NormalizePath(filename);
38     ModulePathHelper::ParseAbcPathAndOhmUrl(vm, normalName, name, entry);
39 #if !defined(PANDA_TARGET_WINDOWS)
40     if (name.empty()) {
41         name = vm->GetAssetPath();
42     }
43 #elif defined(PANDA_TARGET_WINDOWS)
44     CString assetPath = vm->GetAssetPath();
45     name = assetPath + "\\" + JSPandaFile::MERGE_ABC_NAME;
46 #else
47     CString assetPath = vm->GetAssetPath();
48     name = assetPath + "/" + JSPandaFile::MERGE_ABC_NAME;
49 #endif
50 #endif
51     return std::make_pair(name, entry);
52 }
53 
ExecuteFromFile(JSThread * thread,const CString & name,CString entry,bool needUpdate,bool executeFromJob)54 Expected<JSTaggedValue, bool> JSPandaFileExecutor::ExecuteFromFile(JSThread *thread, const CString &name,
55     CString entry, bool needUpdate, bool executeFromJob)
56 {
57     EcmaVM *vm = thread->GetEcmaVM();
58 
59     std::shared_ptr<JSPandaFile> jsPandaFile =
60         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, name, entry, needUpdate);
61     if (jsPandaFile == nullptr) {
62 #ifdef FUZZ_TEST
63         CString msg = "jsPandaFile is nullptr";
64         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
65 #else
66         LOG_FULL(FATAL) << "Load current file's panda file failed. Current file is " << name;
67 #endif
68     }
69     // If it is an old record, delete the bundleName and moduleName
70     if (!jsPandaFile->IsBundlePack() && !vm->IsNormalizedOhmUrlPack() && !executeFromJob &&
71         !vm->GetBundleName().empty()) {
72         jsPandaFile->CheckIsRecordWithBundleName(entry);
73         if (!jsPandaFile->IsRecordWithBundleName()) {
74             PathHelper::AdaptOldIsaRecord(entry);
75         }
76     }
77 
78     JSRecordInfo *recordInfo = nullptr;
79     bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(entry, &recordInfo);
80     if (!hasRecord) {
81         CString msg = "Cannot find module '" + entry + "' , which is application Entry Point";
82         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
83     }
84     if (jsPandaFile->IsModule(recordInfo)) {
85         ThreadManagedScope managedScope(thread);
86         SharedModuleManager* sharedModuleManager = SharedModuleManager::GetInstance();
87         JSHandle<JSTaggedValue> moduleRecord(thread->GlobalConstants()->GetHandledUndefined());
88         if (jsPandaFile->IsBundlePack()) {
89             moduleRecord = sharedModuleManager->ResolveImportedModule(thread, name, executeFromJob);
90         } else {
91             moduleRecord = sharedModuleManager->ResolveImportedModuleWithMerge(thread, name, entry, executeFromJob);
92         }
93 
94         SourceTextModule::Instantiate(thread, moduleRecord, executeFromJob);
95         if (thread->HasPendingException()) {
96             return Unexpected(false);
97         }
98         JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleRecord);
99         module->SetStatus(ModuleStatus::INSTANTIATED);
100         SourceTextModule::Evaluate(thread, module, nullptr, 0, executeFromJob);
101         if (thread->HasPendingException()) {
102             return Unexpected(false);
103         }
104         return JSTaggedValue::Undefined();
105     }
106     return JSPandaFileExecutor::Execute(thread, jsPandaFile.get(), entry.c_str(), executeFromJob);
107 }
108 
ExecuteFromAbsolutePathAbcFile(JSThread * thread,const CString & filename,std::string_view entryPoint,bool needUpdate,bool executeFromJob)109 Expected<JSTaggedValue, bool> JSPandaFileExecutor::ExecuteFromAbsolutePathAbcFile(JSThread *thread,
110     const CString &filename, std::string_view entryPoint, bool needUpdate, bool executeFromJob)
111 {
112     LOG_ECMA(DEBUG) << "JSPandaFileExecutor::ExecuteFromAbsolutePathAbcFile filename " << filename;
113     CString traceInfo = "JSPandaFileExecutor::ExecuteFromAbsolutePathAbcFile " + filename;
114     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, traceInfo.c_str());
115     CString entry = entryPoint.data();
116     CString name = filename;
117 
118     return ExecuteFromFile(thread, name, entry, needUpdate, executeFromJob);
119 }
120 
ExecuteFromAbcFile(JSThread * thread,const CString & filename,std::string_view entryPoint,bool needUpdate,bool executeFromJob)121 Expected<JSTaggedValue, bool> JSPandaFileExecutor::ExecuteFromAbcFile(JSThread *thread, const CString &filename,
122     std::string_view entryPoint, bool needUpdate, bool executeFromJob)
123 {
124     LOG_ECMA(DEBUG) << "JSPandaFileExecutor::ExecuteFromAbcFile filename " << filename;
125     CString traceInfo = "JSPandaFileExecutor::ExecuteFromAbcFile " + filename;
126     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, traceInfo.c_str());
127     CString entry;
128     CString name;
129     EcmaVM *vm = thread->GetEcmaVM();
130     if (!vm->IsBundlePack() && !executeFromJob) {
131         std::tie(name, entry) = ParseAbcEntryPoint(thread, filename, entryPoint);
132     } else {
133         name = filename;
134         entry = entryPoint.data();
135     }
136 
137     return ExecuteFromFile(thread, name, entry, needUpdate, executeFromJob);
138 }
139 
140 // The security interface needs to be modified accordingly.
ExecuteFromBuffer(JSThread * thread,const void * buffer,size_t size,std::string_view entryPoint,const CString & filename,bool needUpdate,bool executeFromJob)141 Expected<JSTaggedValue, bool> JSPandaFileExecutor::ExecuteFromBuffer(JSThread *thread,
142     const void *buffer, size_t size, std::string_view entryPoint, const CString &filename, bool needUpdate,
143     bool executeFromJob)
144 {
145     LOG_ECMA(DEBUG) << "JSPandaFileExecutor::ExecuteFromBuffer filename " << filename;
146     CString traceInfo = "JSPandaFileExecutor::ExecuteFromBuffer " + filename;
147     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, traceInfo.c_str());
148     CString normalName = PathHelper::NormalizePath(filename);
149     std::shared_ptr<JSPandaFile> jsPandaFile =
150         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, normalName, entryPoint, buffer, size, needUpdate);
151     if (jsPandaFile == nullptr) {
152 #ifdef FUZZ_TEST
153         CString msg = "jsPandaFile is nullptr";
154         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
155 #else
156         LOG_FULL(FATAL) << "Load current file's panda file failed. Current file is " << normalName;
157 #endif
158     }
159     AbcBufferCacheScope bufferScope(thread, normalName, buffer, size, AbcBufferType::NORMAL_BUFFER);
160     auto vm = thread->GetEcmaVM();
161 
162     CString entry = entryPoint.data();
163     if (vm->IsNormalizedOhmUrlPack()) {
164         entry = ModulePathHelper::TransformToNormalizedOhmUrl(vm, filename, normalName, entry);
165     }
166     JSRecordInfo *recordInfo = nullptr;
167     bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(entry, &recordInfo);
168     if (!hasRecord) {
169         CString msg = "Cannot find module '" + entry + "' , which is application Entry Point";
170         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
171     }
172     if (jsPandaFile->IsModule(recordInfo)) {
173         bool isBundle = jsPandaFile->IsBundlePack();
174         return CommonExecuteBuffer(thread, isBundle, normalName, entry, buffer, size, executeFromJob);
175     }
176     return JSPandaFileExecutor::Execute(thread, jsPandaFile.get(), entry, executeFromJob);
177 }
178 
179 // The security interface needs to be modified accordingly.
ExecuteModuleBuffer(JSThread * thread,const void * buffer,size_t size,const CString & filename,bool needUpdate)180 Expected<JSTaggedValue, bool> JSPandaFileExecutor::ExecuteModuleBuffer(
181     JSThread *thread, const void *buffer, size_t size, const CString &filename, bool needUpdate)
182 {
183     LOG_ECMA(DEBUG) << "JSPandaFileExecutor::ExecuteModuleBuffer filename " << filename;
184     CString traceInfo = "JSPandaFileExecutor::ExecuteModuleBuffer " + filename;
185     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, traceInfo.c_str());
186     CString name;
187     CString entry;
188     EcmaVM *vm = thread->GetEcmaVM();
189 #if !defined(PANDA_TARGET_WINDOWS)
190     name = vm->GetAssetPath();
191 #elif defined(PANDA_TARGET_WINDOWS)
192     CString assetPath = vm->GetAssetPath();
193     name = assetPath + "\\" + JSPandaFile::MERGE_ABC_NAME;
194 #else
195     CString assetPath = vm->GetAssetPath();
196     name = assetPath + "/" + JSPandaFile::MERGE_ABC_NAME;
197 #endif
198     CString normalName = PathHelper::NormalizePath(filename);
199     ModulePathHelper::ParseAbcPathAndOhmUrl(vm, normalName, name, entry);
200     std::shared_ptr<JSPandaFile> jsPandaFile =
201         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, name, entry, buffer, size, needUpdate);
202     if (jsPandaFile == nullptr) {
203 #ifdef FUZZ_TEST
204         CString msg = "jsPandaFile is nullptr";
205         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
206 #else
207         LOG_FULL(FATAL) << "Load current file's panda file failed. Current file is " << name;
208 #endif
209     }
210     AbcBufferCacheScope bufferScope(thread, name, buffer, size, AbcBufferType::NORMAL_BUFFER);
211     bool isBundle = jsPandaFile->IsBundlePack();
212 
213     // realEntry is used to record the original record, which is easy to throw when there are exceptions
214     const CString realEntry = entry;
215     if (vm->IsNormalizedOhmUrlPack()) {
216         entry = ModulePathHelper::TransformToNormalizedOhmUrl(vm, filename, name, entry);
217     } else if (!isBundle) {
218         jsPandaFile->CheckIsRecordWithBundleName(entry);
219         if (!jsPandaFile->IsRecordWithBundleName()) {
220             PathHelper::AdaptOldIsaRecord(entry);
221         }
222     }
223     JSRecordInfo *recordInfo = nullptr;
224     bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(entry, &recordInfo);
225     if (!hasRecord) {
226         CString msg = "Cannot find module '" + realEntry + "' , which is application Entry Point";
227         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
228     }
229     if (!jsPandaFile->IsModule(recordInfo)) {
230         LOG_ECMA(FATAL) << "Input file is not esmodule";
231     }
232     return CommonExecuteBuffer(thread, isBundle, name, entry, buffer, size);
233 }
234 
235 // The security interface needs to be modified accordingly.
CommonExecuteBuffer(JSThread * thread,bool isBundle,const CString & filename,const CString & entry,const void * buffer,size_t size,bool executeFromJob)236 Expected<JSTaggedValue, bool> JSPandaFileExecutor::CommonExecuteBuffer(JSThread *thread,
237     bool isBundle, const CString &filename, const CString &entry, const void *buffer, size_t size, bool executeFromJob)
238 {
239     [[maybe_unused]] EcmaHandleScope scope(thread);
240     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
241     moduleManager->SetExecuteMode(ModuleExecuteMode::ExecuteBufferMode);
242     JSMutableHandle<JSTaggedValue> moduleRecord(thread, thread->GlobalConstants()->GetUndefined());
243     if (isBundle) {
244         moduleRecord.Update(moduleManager->HostResolveImportedModule(buffer, size, filename));
245     } else {
246         moduleRecord.Update(moduleManager->HostResolveImportedModuleWithMerge(filename, entry, executeFromJob));
247     }
248 
249     SourceTextModule::Instantiate(thread, moduleRecord, executeFromJob);
250     if (thread->HasPendingException()) {
251         return Unexpected(false);
252     }
253 
254     JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleRecord);
255     module->SetStatus(ModuleStatus::INSTANTIATED);
256     SourceTextModule::Evaluate(thread, module, buffer, size, executeFromJob);
257     if (thread->HasPendingException()) {
258         return Unexpected(false);
259     }
260     return JSTaggedValue::Undefined();
261 }
262 
Execute(JSThread * thread,const JSPandaFile * jsPandaFile,std::string_view entryPoint,bool executeFromJob)263 Expected<JSTaggedValue, bool> JSPandaFileExecutor::Execute(JSThread *thread, const JSPandaFile *jsPandaFile,
264                                                            std::string_view entryPoint, bool executeFromJob)
265 {
266     ThreadManagedScope managedScope(thread);
267     bool enableESMTrace = thread->GetEcmaVM()->GetJSOptions().EnableESMTrace();
268     if (enableESMTrace) {
269         CString traceInfo = "FileExecute: " + CString(entryPoint);
270         ECMA_BYTRACE_START_TRACE(HITRACE_TAG_ARK, traceInfo.c_str());
271     }
272     // For Ark application startup
273     EcmaContext *context = thread->GetCurrentEcmaContext();
274 
275     Expected<JSTaggedValue, bool> result;
276 
277     if (context->GetStageOfHotReload() == StageOfHotReload::BEGIN_EXECUTE_PATCHMAIN) {
278         result = context->InvokeEcmaEntrypointForHotReload(jsPandaFile, entryPoint, executeFromJob);
279     } else {
280         QuickFixManager *quickFixManager = thread->GetEcmaVM()->GetQuickFixManager();
281         quickFixManager->LoadPatchIfNeeded(thread, jsPandaFile);
282 
283         result = context->InvokeEcmaEntrypoint(jsPandaFile, entryPoint, executeFromJob);
284     }
285     if (enableESMTrace) {
286         ECMA_BYTRACE_FINISH_TRACE(HITRACE_TAG_ARK);
287     }
288     return result;
289 }
290 
BindPreloadedPandaFilesToAOT(EcmaVM * vm,const std::string & moduleName)291 void JSPandaFileExecutor::BindPreloadedPandaFilesToAOT(EcmaVM *vm, const std::string &moduleName)
292 {
293     ASSERT(vm->GetJSThread()->IsMainThread());
294     if (!vm->GetJSOptions().GetEnableAsmInterpreter()) {
295         return;
296     }
297     // run not via command line
298     if (vm->GetJSOptions().WasAOTOutputFileSet()) {
299         return;
300     }
301     ASSERT(!moduleName.empty());
302     // bind pandafiles loaded in appspawn
303     vm->GetAOTFileManager()->BindPreloadedPandaFilesInAotFile(moduleName);
304 }
305 
BindPandaFileToAot(JSPandaFile * jsPandaFile)306 void JSPandaFileExecutor::BindPandaFileToAot(JSPandaFile *jsPandaFile)
307 {
308     EcmaVM *vm = Runtime::GetInstance()->GetMainThread()->GetEcmaVM();
309     if (vm->GetJSOptions().GetEnableAsmInterpreter()) {
310         std::string aotFileBaseName(vm->GetModuleName());
311         auto *aotFM = vm->GetAOTFileManager();
312         if (vm->GetJSOptions().WasAOTOutputFileSet()) {
313             std::string aotFilename = vm->GetJSOptions().GetAOTOutputFile();
314             aotFileBaseName = JSFilePath::GetBaseName(aotFilename);
315         }
316         aotFM->BindPandaFileInAotFile(aotFileBaseName, jsPandaFile);
317     }
318 }
319 
ExecuteFromBufferSecure(JSThread * thread,uint8_t * buffer,size_t size,std::string_view entryPoint,const CString & filename,bool needUpdate)320 Expected<JSTaggedValue, bool> JSPandaFileExecutor::ExecuteFromBufferSecure(JSThread *thread, uint8_t *buffer,
321     size_t size, std::string_view entryPoint, const CString &filename, bool needUpdate)
322 {
323     LOG_ECMA(DEBUG) << "JSPandaFileExecutor::ExecuteFromBufferSecure with secure buffer filename " << filename;
324     CString traceInfo = "JSPandaFileExecutor::ExecuteFromBufferSecure " + filename;
325     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, traceInfo.c_str());
326     CString normalName = PathHelper::NormalizePath(filename);
327     std::shared_ptr<JSPandaFile> jsPandaFile = JSPandaFileManager::GetInstance()->
328         LoadJSPandaFileSecure(thread, normalName, entryPoint, buffer, size, needUpdate);
329     if (jsPandaFile == nullptr) {
330 #ifdef FUZZ_TEST
331         CString msg = "jsPandaFile is nullptr";
332         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
333 #else
334         LOG_FULL(FATAL) << "Load current file's panda file failed. Current file is " << normalName;
335 #endif
336     }
337     AbcBufferCacheScope bufferScope(thread, normalName, buffer, size, AbcBufferType::SECURE_BUFFER);
338     auto vm = thread->GetEcmaVM();
339 
340     CString entry = entryPoint.data();
341     if (vm->IsNormalizedOhmUrlPack()) {
342         entry = ModulePathHelper::TransformToNormalizedOhmUrl(vm, filename, normalName, entry);
343     }
344     JSRecordInfo *recordInfo = nullptr;
345     bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(entry, &recordInfo);
346     if (!hasRecord) {
347         CString msg = "Cannot find module '" + entry + "' , which is application Entry Point";
348         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
349     }
350     if (jsPandaFile->IsModule(recordInfo)) {
351         return CommonExecuteBuffer(thread, normalName, entry, jsPandaFile.get());
352     }
353     return JSPandaFileExecutor::Execute(thread, jsPandaFile.get(), entry);
354 }
355 
CommonExecuteBuffer(JSThread * thread,const CString & filename,const CString & entry,const JSPandaFile * jsPandaFile)356 Expected<JSTaggedValue, bool> JSPandaFileExecutor::CommonExecuteBuffer(JSThread *thread, const CString &filename,
357     const CString &entry, const JSPandaFile *jsPandaFile)
358 {
359     [[maybe_unused]] EcmaHandleScope scope(thread);
360     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
361     moduleManager->SetExecuteMode(ModuleExecuteMode::ExecuteBufferMode);
362     JSMutableHandle<JSTaggedValue> moduleRecord(thread, thread->GlobalConstants()->GetUndefined());
363     if (jsPandaFile->IsBundlePack()) {
364         moduleRecord.Update(moduleManager->HostResolveImportedModule(jsPandaFile, filename));
365     } else {
366         moduleRecord.Update(moduleManager->HostResolveImportedModuleWithMerge(filename, entry));
367     }
368 
369     SourceTextModule::Instantiate(thread, moduleRecord);
370     if (thread->HasPendingException()) {
371         return Unexpected(false);
372     }
373 
374     JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleRecord);
375     module->SetStatus(ModuleStatus::INSTANTIATED);
376     SourceTextModule::Evaluate(thread, module, nullptr, 0);
377     if (thread->HasPendingException()) {
378         return Unexpected(false);
379     }
380     return JSTaggedValue::Undefined();
381 }
382 
ExecuteModuleBufferSecure(JSThread * thread,uint8_t * buffer,size_t size,const CString & filename,bool needUpdate)383 Expected<JSTaggedValue, bool> JSPandaFileExecutor::ExecuteModuleBufferSecure(JSThread *thread, uint8_t *buffer,
384     size_t size, const CString &filename, bool needUpdate)
385 {
386     LOG_ECMA(DEBUG) << "JSPandaFileExecutor::ExecuteModuleBufferSecure with secure buffer filename " << filename;
387     CString traceInfo = "JSPandaFileExecutor::ExecuteModuleBufferSecure " + filename;
388     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, traceInfo.c_str());
389     CString name;
390     EcmaVM *vm = thread->GetEcmaVM();
391 #if !defined(PANDA_TARGET_WINDOWS)
392     name = vm->GetAssetPath();
393 #elif defined(PANDA_TARGET_WINDOWS)
394     CString assetPath = vm->GetAssetPath();
395     name = assetPath + "\\" + JSPandaFile::MERGE_ABC_NAME;
396 #else
397     CString assetPath = vm->GetAssetPath();
398     name = assetPath + "/" + JSPandaFile::MERGE_ABC_NAME;
399 #endif
400     CString entry;
401     CString normalName = PathHelper::NormalizePath(filename);
402     ModulePathHelper::ParseAbcPathAndOhmUrl(vm, normalName, name, entry);
403     std::shared_ptr<JSPandaFile> jsPandaFile = JSPandaFileManager::GetInstance()->
404         LoadJSPandaFileSecure(thread, name, entry, buffer, size, needUpdate);
405     if (jsPandaFile == nullptr) {
406 #ifdef FUZZ_TEST
407         CString msg = "jsPandaFile is nullptr";
408         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
409 #else
410         LOG_FULL(FATAL) << "Load current file's panda file failed. Current file is " << name;
411 #endif
412     }
413     AbcBufferCacheScope bufferScope(thread, name, buffer, size, AbcBufferType::SECURE_BUFFER);
414     // realEntry is used to record the original record, which is easy to throw when there are exceptions
415     const CString realEntry = entry;
416     if (vm->IsNormalizedOhmUrlPack()) {
417         entry = ModulePathHelper::TransformToNormalizedOhmUrl(vm, filename, name, entry);
418     } else if (!jsPandaFile->IsBundlePack()) {
419         jsPandaFile->CheckIsRecordWithBundleName(entry);
420         if (!jsPandaFile->IsRecordWithBundleName()) {
421             PathHelper::AdaptOldIsaRecord(entry);
422         }
423     }
424 
425     // will be refactored, temporarily use the function IsModule to verify realEntry
426     JSRecordInfo *recordInfo = nullptr;
427     bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(entry, &recordInfo);
428     if (!hasRecord) {
429         CString msg = "Cannot find module '" + realEntry + "' , which is application Entry Point";
430         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
431     }
432     if (!jsPandaFile->IsModule(recordInfo)) {
433         LOG_ECMA(FATAL) << "Input file is not esmodule";
434     }
435     return CommonExecuteBuffer(thread, name, entry, jsPandaFile.get());
436 }
437 
ExecuteSpecialModule(JSThread * thread,const CString & recordName,const CString & filename,const JSPandaFile * jsPandaFile,const JSRecordInfo * recordInfo)438 Expected<JSTaggedValue, bool> JSPandaFileExecutor::ExecuteSpecialModule(JSThread *thread, const CString &recordName,
439     const CString &filename, const JSPandaFile *jsPandaFile, const JSRecordInfo* recordInfo)
440 {
441     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
442 
443     if (jsPandaFile->IsCjs(recordInfo)) {
444         moduleManager->ExecuteCjsModule(thread, recordName, jsPandaFile);
445         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, Unexpected(false));
446         return JSTaggedValue::Undefined();
447     }
448     if (jsPandaFile->IsJson(recordInfo)) {
449         moduleManager->ExecuteJsonModule(thread, recordName, filename, jsPandaFile);
450         return JSTaggedValue::Undefined();
451     }
452     UNREACHABLE();
453     LOG_FULL(FATAL) << "this branch is unreachable";
454 }
455 
456 // RecordName is the ohmurl-path of js files.
457 // The first js file executed could be json, cjs, native so or esm.
LazyExecuteModule(JSThread * thread,CString & recordName,const CString & filename,bool isMergedAbc)458 Expected<JSTaggedValue, bool> JSPandaFileExecutor::LazyExecuteModule(
459     JSThread *thread, CString &recordName, const CString &filename, bool isMergedAbc)
460 {
461     LOG_FULL(INFO) << "recordName : " << recordName << ", in abc : " << filename;
462     CString traceInfo = "JSPandaFileExecutor::LazyExecuteModule " + filename;
463     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, traceInfo.c_str());
464     CString newFileName = filename;
465     if (newFileName.empty()) {
466         newFileName = filename;
467     }
468     std::shared_ptr<JSPandaFile> jsPandaFile =
469         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, newFileName, recordName);
470     if (jsPandaFile == nullptr) {
471 #ifdef FUZZ_TEST
472         CString msg = "jsPandaFile is nullptr";
473         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
474 #else
475         LOG_FULL(FATAL) << "Load file with filename '" << newFileName << "' failed, ";
476 #endif
477     }
478 
479     // resolve native module
480     auto [isNative, moduleType] = SourceTextModule::CheckNativeModule(recordName);
481     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
482     if (isNative) {
483         moduleManager->ExecuteNativeModule(thread, recordName);
484         return JSTaggedValue::Undefined();
485     }
486 
487     if (isMergedAbc && !jsPandaFile->HasRecord(recordName)) {
488         CString msg = "cannot find record '" + recordName + "', in lazy load abc: " + newFileName;
489         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
490     }
491 
492     const JSRecordInfo* recordInfo = jsPandaFile->GetRecordInfo(recordName);
493     if (!jsPandaFile->IsModule(recordInfo)) {
494         return JSPandaFileExecutor::ExecuteSpecialModule(thread, recordName, newFileName, jsPandaFile.get(),
495             recordInfo);
496     }
497     [[maybe_unused]] EcmaHandleScope scope(thread);
498     // The first js file should execute at current vm.
499     JSHandle<JSTaggedValue> moduleRecord(thread->GlobalConstants()->GetHandledUndefined());
500     if (isMergedAbc) {
501         moduleRecord = moduleManager->HostResolveImportedModuleWithMerge(newFileName, recordName);
502     } else {
503         moduleRecord = moduleManager->HostResolveImportedModule(newFileName);
504     }
505     SourceTextModule::Instantiate(thread, moduleRecord);
506     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, Unexpected(false));
507     JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleRecord);
508     SourceTextModule::Evaluate(thread, module, nullptr, 0);
509     return JSTaggedValue::Undefined();
510 }
511 
ExecuteAbcFileWithSingletonPatternFlag(JSThread * thread,const CString & bundleName,const CString & moduleName,const CString & entry,bool isSingletonPattern)512 int JSPandaFileExecutor::ExecuteAbcFileWithSingletonPatternFlag(JSThread *thread,
513     [[maybe_unused]] const CString &bundleName, const CString &moduleName, const CString &entry,
514     bool isSingletonPattern)
515 {
516     CString abcFilePath = ModulePathHelper::ConcatPandaFilePath(moduleName);
517     std::shared_ptr<JSPandaFile> jsPandaFile =
518         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, abcFilePath, entry);
519     if (jsPandaFile == nullptr) {
520         LOG_ECMA(ERROR) << "When the route jump, loading panda file failed. Current file is " << abcFilePath;
521         return ROUTE_URI_ERROR;
522     }
523     CString entryPoint = ModulePathHelper::ConcatFileNameWithMerge(thread, jsPandaFile.get(),
524         abcFilePath, "", entry);
525     JSRecordInfo *recordInfo = nullptr;
526     bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(entryPoint, &recordInfo);
527     if (!hasRecord) {
528         LOG_ECMA(ERROR) << "When the route jump, Cannot find module '" << entryPoint << "'";
529         return ROUTE_URI_ERROR;
530     }
531     ASSERT(jsPandaFile->IsModule(recordInfo));
532     [[maybe_unused]] EcmaHandleScope scope(thread);
533     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
534     JSHandle<JSTaggedValue> moduleRecord(thread->GlobalConstants()->GetHandledUndefined());
535     ASSERT(!jsPandaFile->IsBundlePack());
536     moduleRecord = moduleManager->HostResolveImportedModuleWithMerge(abcFilePath, entryPoint);
537     SourceTextModule::Instantiate(thread, moduleRecord);
538     if (thread->HasPendingException()) {
539         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ROUTE_INTERNAL_ERROR);
540     }
541     JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleRecord);
542     if (!isSingletonPattern) {
543         LOG_ECMA(INFO) << "Route jump to non-singleton page: " << entryPoint;
544         module->SetStatus(ModuleStatus::INSTANTIATED);
545     } else {
546         LOG_ECMA(INFO) << "Route jump to singleton page: " << entryPoint;
547     }
548     SourceTextModule::Evaluate(thread, module, nullptr, 0);
549     if (thread->HasPendingException()) {
550         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ROUTE_INTERNAL_ERROR);
551     }
552     return ROUTE_SUCCESS;
553 }
554 
IsExecuteModuleInAbcFile(JSThread * thread,const CString & bundleName,const CString & moduleName,const CString & entry)555 bool JSPandaFileExecutor::IsExecuteModuleInAbcFile(JSThread *thread, [[maybe_unused]] const CString &bundleName,
556     const CString &moduleName, const CString &entry)
557 {
558     CString abcFilePath = ModulePathHelper::ConcatPandaFilePath(moduleName);
559     bool isValid = JSPandaFileManager::GetInstance()->CheckFilePath(thread, abcFilePath);
560     if (!isValid) {
561         return false;
562     }
563     std::shared_ptr<JSPandaFile> jsPandaFile =
564         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, abcFilePath, entry);
565     if (jsPandaFile == nullptr) {
566         LOG_ECMA(ERROR) << "When checking if module is in abc file, loading panda file failed. Current file is " <<
567             abcFilePath;
568         return false;
569     }
570     CString entryPoint = ModulePathHelper::ConcatFileNameWithMerge(thread, jsPandaFile.get(),
571         abcFilePath, "", entry);
572     JSRecordInfo *recordInfo = nullptr;
573     bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(entryPoint, &recordInfo);
574     if (!hasRecord) {
575         LOG_ECMA(ERROR) << "When checking if module is in abc file, Cannot find module '" << entryPoint << "'";
576         return false;
577     }
578     return true;
579 }
580 }  // namespace panda::ecmascript
581