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