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, [[maybe_unused]] 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 
438 /*
439  * filename: data/storage/el1/bundle/moduleName/ets/modules.abc
440  * Ohmurl:   1. @bundle:bundleName/moduleName@namespace/ets/pages/Index
441  *           2. @package:pkg_modules/.ohpm/pkgName/pkg_modules/pkgName/xxx/xxx
442  *           3. @normalized:N&moduleName&bundleName&entryPath&version
443  *           4. @normalized:N&moduleName&bundleName&entryPath&
444  */
ExecuteSecureWithOhmUrl(JSThread *thread, uint8_t *buffer, size_t size, const CString &filename, const CString &entryPoint)445 Expected<JSTaggedValue, bool> JSPandaFileExecutor::ExecuteSecureWithOhmUrl(JSThread *thread, uint8_t *buffer,
446     size_t size, const CString &filename, const CString &entryPoint)
447 {
448     LOG_ECMA(DEBUG) << "JSPandaFileExecutor::ExecuteSecureWithOhmUrl with secure buffer filename:" << filename <<
449                         ", entryPoint:" << entryPoint;
450     CString traceInfo = "JSPandaFileExecutor::ExecuteSecureWithOhmUrl " + filename;
451     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, traceInfo.c_str());
452 
453     std::shared_ptr<JSPandaFile> jsPandaFile = JSPandaFileManager::GetInstance()->
454         LoadJSPandaFileSecure(thread, filename, entryPoint, buffer, size);
455     if (jsPandaFile == nullptr) {
456 #ifdef FUZZ_TEST
457         CString msg = "jsPandaFile is nullptr";
458         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
459 #else
460         LOG_FULL(FATAL) << "Load current file's panda file failed. Current file is " << filename <<
461                            ", entrypoint is:" << entryPoint;
462 #endif
463     }
464     AbcBufferCacheScope bufferScope(thread, filename, buffer, size, AbcBufferType::SECURE_BUFFER);
465     JSRecordInfo *recordInfo = nullptr;
466     bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(entryPoint, &recordInfo);
467     if (!hasRecord) {
468         CString msg = "Cannot find module '" + entryPoint + "' , which is application Entry Point";
469         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
470     }
471     return CommonExecuteBuffer(thread, filename, entryPoint, jsPandaFile.get());
472 }
473 
ExecuteSpecialModule(JSThread *thread, const CString &recordName, const CString &filename, const JSPandaFile *jsPandaFile, const JSRecordInfo* recordInfo)474 Expected<JSTaggedValue, bool> JSPandaFileExecutor::ExecuteSpecialModule(JSThread *thread, const CString &recordName,
475     const CString &filename, const JSPandaFile *jsPandaFile, const JSRecordInfo* recordInfo)
476 {
477     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
478 
479     if (jsPandaFile->IsCjs(recordInfo)) {
480         moduleManager->ExecuteCjsModule(thread, recordName, jsPandaFile);
481         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, Unexpected(false));
482         return JSTaggedValue::Undefined();
483     }
484     if (jsPandaFile->IsJson(recordInfo)) {
485         moduleManager->ExecuteJsonModule(thread, recordName, filename, jsPandaFile);
486         return JSTaggedValue::Undefined();
487     }
488     UNREACHABLE();
489     LOG_FULL(FATAL) << "this branch is unreachable";
490 }
491 
492 // RecordName is the ohmurl-path of js files.
493 // The first js file executed could be json, cjs, native so or esm.
LazyExecuteModule( JSThread *thread, CString &recordName, const CString &filename, bool isMergedAbc)494 Expected<JSTaggedValue, bool> JSPandaFileExecutor::LazyExecuteModule(
495     JSThread *thread, CString &recordName, const CString &filename, bool isMergedAbc)
496 {
497     LOG_FULL(INFO) << "recordName : " << recordName << ", in abc : " << filename;
498     CString traceInfo = "JSPandaFileExecutor::LazyExecuteModule " + filename;
499     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, traceInfo.c_str());
500     CString newFileName = filename;
501     if (newFileName.empty()) {
502         newFileName = filename;
503     }
504     std::shared_ptr<JSPandaFile> jsPandaFile =
505         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, newFileName, recordName);
506     if (jsPandaFile == nullptr) {
507 #ifdef FUZZ_TEST
508         CString msg = "jsPandaFile is nullptr";
509         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
510 #else
511         LOG_FULL(FATAL) << "Load file with filename '" << newFileName << "' failed, ";
512 #endif
513     }
514 
515     // resolve native module
516     auto [isNative, moduleType] = SourceTextModule::CheckNativeModule(recordName);
517     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
518     if (isNative) {
519         moduleManager->ExecuteNativeModule(thread, recordName);
520         return JSTaggedValue::Undefined();
521     }
522 
523     if (isMergedAbc && !jsPandaFile->HasRecord(recordName)) {
524         CString msg = "cannot find record '" + recordName + "', in lazy load abc: " + newFileName;
525         THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false));
526     }
527 
528     const JSRecordInfo* recordInfo = jsPandaFile->GetRecordInfo(recordName);
529     if (!jsPandaFile->IsModule(recordInfo)) {
530         return JSPandaFileExecutor::ExecuteSpecialModule(thread, recordName, newFileName, jsPandaFile.get(),
531             recordInfo);
532     }
533     [[maybe_unused]] EcmaHandleScope scope(thread);
534     // The first js file should execute at current vm.
535     JSHandle<JSTaggedValue> moduleRecord(thread->GlobalConstants()->GetHandledUndefined());
536     if (isMergedAbc) {
537         moduleRecord = moduleManager->HostResolveImportedModuleWithMerge(newFileName, recordName);
538     } else {
539         moduleRecord = moduleManager->HostResolveImportedModule(newFileName);
540     }
541     SourceTextModule::Instantiate(thread, moduleRecord);
542     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, Unexpected(false));
543     JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleRecord);
544     SourceTextModule::Evaluate(thread, module, nullptr, 0);
545     return JSTaggedValue::Undefined();
546 }
547 
ExecuteAbcFileWithSingletonPatternFlag(JSThread *thread, [[maybe_unused]] const CString &bundleName, const CString &moduleName, const CString &entry, bool isSingletonPattern)548 int JSPandaFileExecutor::ExecuteAbcFileWithSingletonPatternFlag(JSThread *thread,
549     [[maybe_unused]] const CString &bundleName, const CString &moduleName, const CString &entry,
550     bool isSingletonPattern)
551 {
552     CString abcFilePath = ModulePathHelper::ConcatPandaFilePath(moduleName);
553     std::shared_ptr<JSPandaFile> jsPandaFile =
554         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, abcFilePath, entry);
555     if (jsPandaFile == nullptr) {
556         LOG_ECMA(ERROR) << "When the route jump, loading panda file failed. Current file is " << abcFilePath;
557         return ROUTE_URI_ERROR;
558     }
559     CString entryPoint = ModulePathHelper::ConcatFileNameWithMerge(thread, jsPandaFile.get(),
560         abcFilePath, "", entry);
561     JSRecordInfo *recordInfo = nullptr;
562     bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(entryPoint, &recordInfo);
563     if (!hasRecord) {
564         LOG_ECMA(ERROR) << "When the route jump, Cannot find module '" << entryPoint << "'";
565         return ROUTE_URI_ERROR;
566     }
567     ASSERT(jsPandaFile->IsModule(recordInfo));
568     [[maybe_unused]] EcmaHandleScope scope(thread);
569     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
570     JSHandle<JSTaggedValue> moduleRecord(thread->GlobalConstants()->GetHandledUndefined());
571     ASSERT(!jsPandaFile->IsBundlePack());
572     moduleRecord = moduleManager->HostResolveImportedModuleWithMerge(abcFilePath, entryPoint);
573     SourceTextModule::Instantiate(thread, moduleRecord);
574     if (thread->HasPendingException()) {
575         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ROUTE_INTERNAL_ERROR);
576     }
577     JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleRecord);
578     if (!isSingletonPattern) {
579         LOG_ECMA(INFO) << "Route jump to non-singleton page: " << entryPoint;
580         module->SetStatus(ModuleStatus::INSTANTIATED);
581     } else {
582         LOG_ECMA(INFO) << "Route jump to singleton page: " << entryPoint;
583     }
584     SourceTextModule::Evaluate(thread, module, nullptr, 0);
585     if (thread->HasPendingException()) {
586         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ROUTE_INTERNAL_ERROR);
587     }
588     return ROUTE_SUCCESS;
589 }
590 
IsExecuteModuleInAbcFile(JSThread *thread, [[maybe_unused]] const CString &bundleName, const CString &moduleName, const CString &entry)591 bool JSPandaFileExecutor::IsExecuteModuleInAbcFile(JSThread *thread, [[maybe_unused]] const CString &bundleName,
592     const CString &moduleName, const CString &entry)
593 {
594     CString abcFilePath = ModulePathHelper::ConcatPandaFilePath(moduleName);
595     bool isValid = JSPandaFileManager::GetInstance()->CheckFilePath(thread, abcFilePath);
596     if (!isValid) {
597         return false;
598     }
599     std::shared_ptr<JSPandaFile> jsPandaFile =
600         JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, abcFilePath, entry);
601     if (jsPandaFile == nullptr) {
602         LOG_ECMA(ERROR) << "When checking if module is in abc file, loading panda file failed. Current file is " <<
603             abcFilePath;
604         return false;
605     }
606     CString entryPoint = ModulePathHelper::ConcatFileNameWithMerge(thread, jsPandaFile.get(),
607         abcFilePath, "", entry);
608     JSRecordInfo *recordInfo = nullptr;
609     bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(entryPoint, &recordInfo);
610     if (!hasRecord) {
611         LOG_ECMA(ERROR) << "When checking if module is in abc file, Cannot find module '" << entryPoint << "'";
612         return false;
613     }
614     return true;
615 }
616 }  // namespace panda::ecmascript
617