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