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