• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 "frameworks/bridge/js_frontend/engine/jsi/ark_js_runtime.h"
17 
18 #include <unistd.h>
19 
20 #include "ecmascript/napi/include/dfx_jsnapi.h"
21 #include "frameworks/bridge/common/utils/utils.h"
22 #include "frameworks/bridge/js_frontend/engine/jsi/ark_js_value.h"
23 #include "frameworks/core/common/ace_application_info.h"
24 #include "frameworks/core/common/connect_server_manager.h"
25 #include "frameworks/core/common/hdc_register.h"
26 
27 // NOLINTNEXTLINE(readability-identifier-naming)
28 namespace OHOS::Ace::Framework {
29 // NOLINTNEXTLINE(readability-identifier-naming)
30 static constexpr auto PANDA_MAIN_FUNCTION = "_GLOBAL::func_main_0";
31 #if !defined(PREVIEW)
32 constexpr auto DEBUGGER = "@Debugger";
33 #endif
34 
FunctionCallback(panda::JsiRuntimeCallInfo * info)35 Local<JSValueRef> FunctionCallback(panda::JsiRuntimeCallInfo* info)
36 {
37     auto package = reinterpret_cast<PandaFunctionData*>(info->GetData());
38     if (package == nullptr) {
39         return JSValueRef::Undefined(info->GetVM());
40     }
41     return package->Callback(info);
42 }
43 
FunctionDeleter(void * env,void * nativePointer,void * data)44 void FunctionDeleter(void *env, void *nativePointer, void *data)
45 {
46     auto info = reinterpret_cast<PandaFunctionData*>(data);
47     if (info != nullptr) {
48         delete info;
49     }
50 }
51 
52 thread_local EcmaVM* ArkJSRuntime::threadVm_ = nullptr;
53 
Initialize(const std::string & libraryPath,bool isDebugMode,int32_t instanceId)54 bool ArkJSRuntime::Initialize(const std::string& libraryPath, bool isDebugMode, int32_t instanceId)
55 {
56     RuntimeOption option;
57     option.SetGcType(RuntimeOption::GC_TYPE::GEN_GC);
58 #ifdef OHOS_PLATFORM
59     option.SetArkProperties(SystemProperties::GetArkProperties());
60     option.SetArkBundleName(SystemProperties::GetArkBundleName());
61     option.SetMemConfigProperty(SystemProperties::GetMemConfigProperty());
62     option.SetGcThreadNum(SystemProperties::GetGcThreadNum());
63     option.SetLongPauseTime(SystemProperties::GetLongPauseTime());
64     option.SetEnableAsmInterpreter(SystemProperties::GetAsmInterpreterEnabled());
65     option.SetAsmOpcodeDisableRange(SystemProperties::GetAsmOpcodeDisableRange());
66     LOGI("Initialize ark properties = %{public}d, bundlename = %{public}s", SystemProperties::GetArkProperties(),
67         SystemProperties::GetArkBundleName().c_str());
68 #endif
69     const int64_t poolSize = 0x10000000; // 256M
70     option.SetGcPoolSize(poolSize);
71     option.SetLogLevel(RuntimeOption::LOG_LEVEL::FOLLOW);
72     option.SetLogBufPrint(print_);
73     option.SetDebuggerLibraryPath(libraryPath);
74     libPath_ = libraryPath;
75     isDebugMode_ = isDebugMode;
76     instanceId_ = instanceId;
77 
78     vm_ = JSNApi::CreateJSVM(option);
79 #if defined(PREVIEW)
80     if (!pkgNameMap_.empty()) {
81         JSNApi::SetPkgNameList(vm_, pkgNameMap_);
82     }
83     if (!pkgAliasMap_.empty()) {
84         JSNApi::SetPkgAliasList(vm_, pkgAliasMap_);
85     }
86     if (!pkgContextInfoMap_.empty()) {
87         JSNApi::SetpkgContextInfoList(vm_, pkgContextInfoMap_);
88     }
89 #endif
90     return vm_ != nullptr;
91 }
92 
InitializeFromExistVM(EcmaVM * vm)93 bool ArkJSRuntime::InitializeFromExistVM(EcmaVM* vm)
94 {
95     vm_ = vm;
96     usingExistVM_ = true;
97     return vm_ != nullptr;
98 }
99 
Reset()100 void ArkJSRuntime::Reset()
101 {
102     if (vm_ != nullptr) {
103         if (!usingExistVM_) {
104 #if !defined(PREVIEW)
105 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
106             HdcRegister::Get().StopHdcRegister(instanceId_);
107             ConnectServerManager::Get().RemoveInstance(instanceId_);
108 #endif
109             JSNApi::StopDebugger(vm_);
110 #endif
111             JSNApi::DestroyJSVM(vm_);
112             vm_ = nullptr;
113         }
114     }
115 #if defined(PREVIEW)
116     previewComponents_.clear();
117 #endif
118 }
119 
SetLogPrint(LOG_PRINT out)120 void ArkJSRuntime::SetLogPrint(LOG_PRINT out)
121 {
122     print_ = out;
123 }
124 
125 #if !defined(PREVIEW) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
ParseHdcRegisterOption(std::string & option)126 static int ParseHdcRegisterOption(std::string& option)
127 {
128     LOGI("hdc option is %{public}s ", option.c_str());
129     if (option.find(":") == std::string::npos) {
130         return -1;
131     }
132     std::size_t pos = option.find_first_of(":");
133     std::string idStr = option.substr(pos + 1);
134     if (idStr.find(DEBUGGER) == std::string::npos) {
135         return -1;
136     }
137     pos = idStr.find(DEBUGGER);
138     idStr = idStr.substr(0, pos);
139     if (idStr.find("@") != std::string::npos) {
140         pos = idStr.find("@");
141         idStr = idStr.substr(pos + 1);
142     }
143     return static_cast<uint32_t>(std::atol(idStr.c_str()));
144 }
145 
StartDebuggerForSocketPair(std::string & option,uint32_t socketFd)146 void ArkJSRuntime::StartDebuggerForSocketPair(std::string& option, uint32_t socketFd)
147 {
148     CHECK_NULL_VOID(vm_);
149     int identifierId = ParseHdcRegisterOption(option);
150     panda::JSNApi::StartDebuggerForSocketPair(identifierId, socketFd);
151 }
152 #endif
153 
StartDebugger()154 bool ArkJSRuntime::StartDebugger()
155 {
156     bool ret = false;
157 #if !defined(PREVIEW)
158     if (!libPath_.empty()) {
159         bool isDebugApp = AceApplicationInfo::GetInstance().IsDebugVersion();
160 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
161         auto callback = [weak = weak_from_this(), isDebugApp](int socketFd, std::string option) {
162             LOGI("HdcRegister callback socket %{public}d, option %{public}s.", socketFd, option.c_str());
163             if (option.find(DEBUGGER) == std::string::npos) {
164                 if (isDebugApp) {
165                     ConnectServerManager::Get().StopConnectServer();
166                 }
167                 ConnectServerManager::Get().StartConnectServerWithSocketPair(socketFd);
168             } else {
169                 auto runtime = weak.lock();
170                 CHECK_NULL_VOID(runtime);
171                 if (isDebugApp) {
172                     JSNApi::StopDebugger(ParseHdcRegisterOption(option));
173                 }
174                 runtime->StartDebuggerForSocketPair(option, socketFd);
175             }
176         };
177 
178         HdcRegister::Get().StartHdcRegister(instanceId_, callback);
179         ConnectServerManager::Get().SetDebugMode();
180 #endif
181         //FA:true port:-1
182         JSNApi::DebugOption debugOption = { libPath_.c_str(), isDebugApp ? isDebugMode_ : false, -1, true };
183 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
184         ConnectServerManager::Get().AddInstance(gettid(), language_);
185         ret = JSNApi::NotifyDebugMode(gettid(), vm_, debugOption, gettid(), debuggerPostTask_, isDebugApp);
186 #elif defined(ANDROID_PLATFORM)
187         ret = JSNApi::StartDebugger(vm_, debugOption, instanceId_, debuggerPostTask_);
188 #endif
189     }
190 #if defined(IOS_PLATFORM)
191     JSNApi::DebugOption debugOption = { nullptr, isDebugMode_, -1, true }; //FA:true port:-1
192     ret = JSNApi::StartDebugger(vm_, debugOption, instanceId_, debuggerPostTask_);
193 #endif
194 #endif
195     return ret;
196 }
197 
IsExecuteModuleInAbcFile(const std::string & bundleName,const std::string & moduleName,const std::string & ohmurl)198 bool ArkJSRuntime::IsExecuteModuleInAbcFile(
199     const std::string &bundleName, const std::string &moduleName, const std::string &ohmurl)
200 {
201     JSExecutionScope executionScope(vm_);
202     LocalScope scope(vm_);
203     panda::TryCatch trycatch(vm_);
204     bool ret = JSNApi::IsExecuteModuleInAbcFile(vm_, bundleName, moduleName, ohmurl);
205     HandleUncaughtException(trycatch);
206     return ret;
207 }
208 
IsStaticOrInvalidFile(const uint8_t * data,int32_t size)209 bool ArkJSRuntime::IsStaticOrInvalidFile(const uint8_t *data, int32_t size)
210 {
211     JSExecutionScope executionScope(vm_);
212     LocalScope scope(vm_);
213     panda::TryCatch trycatch(vm_);
214     JSNApi::PandaFileType fileType = JSNApi::GetFileType(data, size);
215     bool ret;
216     switch (fileType) {
217         case JSNApi::PandaFileType::FILE_DYNAMIC:
218             ret = false;
219             LOGI("ArkJSRuntime::IsStaticOrInvalidFile, file is dynamic");
220             break;
221         case JSNApi::PandaFileType::FILE_STATIC:
222             ret = true;
223             LOGI("ArkJSRuntime::IsStaticOrInvalidFile, file is static");
224             break;
225         case JSNApi::PandaFileType::FILE_FORMAT_INVALID:
226             ret = true;
227             LOGE("ArkJSRuntime::IsStaticOrInvalidFile, file is invalid. reason is param invalid");
228             break;
229         default:
230             ret = true;
231             LOGE("ArkJSRuntime::IsStaticOrInvalidFile, file is invalid");
232     }
233 
234     HandleUncaughtException(trycatch);
235     return ret;
236 }
237 
ExecuteModuleBuffer(const uint8_t * data,int32_t size,const std::string & filename,bool needUpdate)238 bool ArkJSRuntime::ExecuteModuleBuffer(const uint8_t* data, int32_t size, const std::string& filename, bool needUpdate)
239 {
240     JSExecutionScope executionScope(vm_);
241     LocalScope scope(vm_);
242     panda::TryCatch trycatch(vm_);
243     bool ret = JSNApi::ExecuteModuleBuffer(vm_, data, size, filename, needUpdate);
244     HandleUncaughtException(trycatch);
245     return ret;
246 }
247 
EvaluateJsCode(const std::string & src)248 shared_ptr<JsValue> ArkJSRuntime::EvaluateJsCode([[maybe_unused]] const std::string& src)
249 {
250     return NewUndefined();
251 }
252 
EvaluateJsCode(const uint8_t * buffer,int32_t size,const std::string & filePath,bool needUpdate)253 bool ArkJSRuntime::EvaluateJsCode(const uint8_t* buffer, int32_t size, const std::string& filePath, bool needUpdate)
254 {
255     JSExecutionScope executionScope(vm_);
256     LocalScope scope(vm_);
257     panda::TryCatch trycatch(vm_);
258     bool ret = JSNApi::Execute(vm_, buffer, size, PANDA_MAIN_FUNCTION, filePath, needUpdate);
259     HandleUncaughtException(trycatch);
260     return ret;
261 }
262 
ExecuteJsBin(const std::string & fileName,const std::function<void (const std::string &,int32_t)> & errorCallback)263 bool ArkJSRuntime::ExecuteJsBin(const std::string& fileName,
264     const std::function<void(const std::string&, int32_t)>& errorCallback)
265 {
266     JSExecutionScope executionScope(vm_);
267     LocalScope scope(vm_);
268     panda::TryCatch trycatch(vm_);
269     bool ret = JSNApi::Execute(vm_, fileName, PANDA_MAIN_FUNCTION);
270     HandleUncaughtException(trycatch, errorCallback);
271     return ret;
272 }
273 
ExecuteJsBinForAOT(const std::string & fileName,const std::function<void (const std::string &,int32_t)> & errorCallback)274 bool ArkJSRuntime::ExecuteJsBinForAOT(const std::string& fileName,
275     const std::function<void(const std::string&, int32_t)>& errorCallback)
276 {
277     JSExecutionScope executionScope(vm_);
278     LocalScope scope(vm_);
279     panda::TryCatch trycatch(vm_);
280     bool ret = JSNApi::ExecuteForAbsolutePath(vm_, fileName, PANDA_MAIN_FUNCTION);
281     HandleUncaughtException(trycatch, errorCallback);
282     return ret;
283 }
284 
GetGlobal()285 shared_ptr<JsValue> ArkJSRuntime::GetGlobal()
286 {
287     LocalScope scope(vm_);
288     return std::make_shared<ArkJSValue>(shared_from_this(), JSNApi::GetGlobalObject(vm_));
289 }
290 
GetGlobal(ArkNativeEngine * nativeArkEngine)291 shared_ptr<JsValue> ArkJSRuntime::GetGlobal(ArkNativeEngine* nativeArkEngine)
292 {
293     LocalScope scope(vm_);
294     CHECK_NULL_RETURN(nativeArkEngine, nullptr);
295     return std::make_shared<ArkJSValue>(
296         shared_from_this(), JSNApi::GetGlobalObject(vm_, nativeArkEngine->GetContext()));
297 }
298 
RunGC()299 void ArkJSRuntime::RunGC()
300 {
301     JSExecutionScope executionScope(vm_);
302     LocalScope scope(vm_);
303     JSNApi::HintGC(vm_, JSNApi::MemoryReduceDegree::LOW, panda::ecmascript::GCReason::TRIGGER_BY_ARKUI);
304 }
305 
RunFullGC()306 void ArkJSRuntime::RunFullGC()
307 {
308     JSExecutionScope executionScope(vm_);
309     LocalScope scope(vm_);
310     JSNApi::HintGC(vm_, JSNApi::MemoryReduceDegree::HIGH, panda::ecmascript::GCReason::TRIGGER_BY_ARKUI);
311 }
312 
NewInt32(int32_t value)313 shared_ptr<JsValue> ArkJSRuntime::NewInt32(int32_t value)
314 {
315     LocalScope scope(vm_);
316     return std::make_shared<ArkJSValue>(shared_from_this(), IntegerRef::New(vm_, value));
317 }
318 
NewBoolean(bool value)319 shared_ptr<JsValue> ArkJSRuntime::NewBoolean(bool value)
320 {
321     LocalScope scope(vm_);
322     return std::make_shared<ArkJSValue>(shared_from_this(), BooleanRef::New(vm_, value));
323 }
324 
NewNumber(double d)325 shared_ptr<JsValue> ArkJSRuntime::NewNumber(double d)
326 {
327     LocalScope scope(vm_);
328     return std::make_shared<ArkJSValue>(shared_from_this(), NumberRef::New(vm_, d));
329 }
330 
NewNull()331 shared_ptr<JsValue> ArkJSRuntime::NewNull()
332 {
333     LocalScope scope(vm_);
334     return std::make_shared<ArkJSValue>(shared_from_this(), JSValueRef::Null(vm_));
335 }
336 
NewUndefined()337 shared_ptr<JsValue> ArkJSRuntime::NewUndefined()
338 {
339     LocalScope scope(vm_);
340     return std::make_shared<ArkJSValue>(shared_from_this(), JSValueRef::Undefined(vm_));
341 }
342 
NewString(const std::string & str)343 shared_ptr<JsValue> ArkJSRuntime::NewString(const std::string& str)
344 {
345     LocalScope scope(vm_);
346     return std::make_shared<ArkJSValue>(shared_from_this(), StringRef::NewFromUtf8(vm_, str.c_str()));
347 }
348 
ParseJson(const std::string & str)349 shared_ptr<JsValue> ArkJSRuntime::ParseJson(const std::string& str)
350 {
351     LocalScope scope(vm_);
352     Local<StringRef> string = StringRef::NewFromUtf8(vm_, str.c_str());
353     return std::make_shared<ArkJSValue>(shared_from_this(), JSON::Parse(vm_, string));
354 }
355 
NewObject()356 shared_ptr<JsValue> ArkJSRuntime::NewObject()
357 {
358     LocalScope scope(vm_);
359     return std::make_shared<ArkJSValue>(shared_from_this(), ObjectRef::New(vm_));
360 }
361 
NewArray()362 shared_ptr<JsValue> ArkJSRuntime::NewArray()
363 {
364     LocalScope scope(vm_);
365     return std::make_shared<ArkJSValue>(shared_from_this(), ArrayRef::New(vm_));
366 }
367 
NewFunction(RegisterFunctionType func)368 shared_ptr<JsValue> ArkJSRuntime::NewFunction(RegisterFunctionType func)
369 {
370     LocalScope scope(vm_);
371     auto data = new PandaFunctionData(shared_from_this(), func);
372     return std::make_shared<ArkJSValue>(shared_from_this(),
373         FunctionRef::NewConcurrent(vm_, FunctionCallback, FunctionDeleter, data));
374 }
375 
NewNativePointer(void * ptr)376 shared_ptr<JsValue> ArkJSRuntime::NewNativePointer(void* ptr)
377 {
378     LocalScope scope(vm_);
379     return std::make_shared<ArkJSValue>(shared_from_this(), NativePointerRef::New(vm_, ptr));
380 }
381 
ThrowError(const std::string & msg,int32_t code)382 void ArkJSRuntime::ThrowError(const std::string& msg, int32_t code)
383 {
384     auto errorVal = panda::Exception::Error(vm_, panda::StringRef::NewFromUtf8(vm_, msg.c_str()));
385     auto codeVal = panda::Exception::Error(vm_, panda::StringRef::NewFromUtf8(vm_, std::to_string(code).c_str()));
386     Local<StringRef> codeKey = StringRef::NewFromUtf8(vm_, "code");
387     Local<ObjectRef> errorObj(errorVal);
388     errorObj->Set(vm_, codeKey, codeVal);
389     panda::JSNApi::ThrowException(vm_, errorObj);
390 }
391 
RegisterUncaughtExceptionHandler(UncaughtExceptionCallback callback)392 void ArkJSRuntime::RegisterUncaughtExceptionHandler(UncaughtExceptionCallback callback)
393 {
394     JSNApi::EnableUserUncaughtErrorHandler(vm_);
395     uncaughtErrorHandler_ = callback;
396 }
397 
HasPendingException()398 bool ArkJSRuntime::HasPendingException()
399 {
400     return JSNApi::HasPendingException(vm_);
401 }
402 
HandleUncaughtException(panda::TryCatch & trycatch,const std::function<void (const std::string &,int32_t)> & errorCallback)403 void ArkJSRuntime::HandleUncaughtException(panda::TryCatch& trycatch,
404     const std::function<void(const std::string&, int32_t)>& errorCallback)
405 {
406     if (errorCallback != nullptr) {
407         Local<ObjectRef> exception = trycatch.GetAndClearException();
408         if (!exception.IsEmpty() && !exception->IsHole()) {
409             errorCallback("loading js file has crash or the uri of router is not exist.",
410                 ERROR_CODE_URI_ERROR);
411             return;
412         }
413     }
414 
415     // Handle the uncaught exception by native engine created by ability runtime in the stage model project.
416     if (nativeEngine_) {
417         nativeEngine_->HandleUncaughtException();
418         return;
419     }
420 
421     // Handle the uncaught exception without native engine, such as oom error
422     HandleUncaughtExceptionWithoutNativeEngine(trycatch, errorCallback);
423 }
424 
HandleUncaughtExceptionWithoutNativeEngine(panda::TryCatch & trycatch,const std::function<void (const std::string &,int32_t)> & errorCallback)425 void ArkJSRuntime::HandleUncaughtExceptionWithoutNativeEngine(panda::TryCatch& trycatch,
426     const std::function<void(const std::string&, int32_t)>& errorCallback)
427 {
428     if (uncaughtErrorHandler_ == nullptr) {
429         return;
430     }
431 
432     Local<ObjectRef> exception = trycatch.GetAndClearException();
433     if (!exception.IsEmpty() && !exception->IsHole()) {
434         shared_ptr<JsValue> errorPtr =
435             std::static_pointer_cast<JsValue>(std::make_shared<ArkJSValue>(shared_from_this(), exception));
436         uncaughtErrorHandler_(errorPtr, shared_from_this());
437     }
438 }
439 
ExecutePendingJob()440 void ArkJSRuntime::ExecutePendingJob()
441 {
442     LocalScope scope(vm_);
443     JSNApi::ExecutePendingJob(vm_);
444 }
445 
NotifyUIIdle()446 void ArkJSRuntime::NotifyUIIdle()
447 {
448     LocalScope scope(vm_);
449     panda::JSNApi::NotifyUIIdle(vm_, 0);
450 }
451 
452 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
DumpHeapSnapshot(bool isPrivate)453 void ArkJSRuntime::DumpHeapSnapshot(bool isPrivate)
454 {
455     panda::ecmascript::DumpSnapShotOption dumpOption;
456     dumpOption.dumpFormat = panda::ecmascript::DumpFormat::JSON;
457     dumpOption.isVmMode = true;
458     dumpOption.isPrivate = isPrivate;
459     dumpOption.isSync = false;
460     LocalScope scope(vm_);
461     panda::DFXJSNApi::DumpHeapSnapshot(vm_, dumpOption);
462 }
463 #else
DumpHeapSnapshot(bool isPrivate)464 void ArkJSRuntime::DumpHeapSnapshot(bool isPrivate)
465 {
466     LOGE("Do not support Ark DumpHeapSnapshot on Windows or MacOS");
467 }
468 #endif
469 
470 #if !defined(PREVIEW) && !defined(IOS_PLATFORM)
DestroyHeapProfiler()471 void ArkJSRuntime::DestroyHeapProfiler()
472 {
473     LocalScope scope(vm_);
474     panda::DFXJSNApi::DestroyHeapProfiler(vm_);
475 }
476 #else
DestroyHeapProfiler()477 void ArkJSRuntime::DestroyHeapProfiler()
478 {
479     LOGE("Do not support Ark DestroyHeapProfiler on Windows or MacOS");
480 }
481 #endif
482 
Callback(panda::JsiRuntimeCallInfo * info) const483 Local<JSValueRef> PandaFunctionData::Callback(panda::JsiRuntimeCallInfo* info) const
484 {
485     auto runtime = runtime_.lock();
486     if (runtime == nullptr) {
487         return Local<JSValueRef>();
488     }
489     EscapeLocalScope scope(runtime->GetEcmaVm());
490     shared_ptr<JsValue> thisPtr =
491         std::static_pointer_cast<JsValue>(std::make_shared<ArkJSValue>(runtime, info->GetThisRef()));
492 
493     std::vector<shared_ptr<JsValue>> argv;
494     uint32_t length = info->GetArgsNumber();
495     argv.reserve(length);
496     for (uint32_t i = 0; i < length; ++i) {
497         argv.emplace_back(
498             std::static_pointer_cast<JsValue>(std::make_shared<ArkJSValue>(runtime, info->GetCallArgRef(i))));
499     }
500     shared_ptr<JsValue> result = func_(runtime, thisPtr, argv, length);
501     return scope.Escape(std::static_pointer_cast<ArkJSValue>(result)->GetValue(runtime));
502 }
503 
LoadDestinationFile(const std::string & bundleName,const std::string & moduleName,const std::string & pageSourceFile,bool isSingleton)504 int32_t ArkJSRuntime::LoadDestinationFile(const std::string& bundleName, const std::string& moduleName,
505     const std::string& pageSourceFile, bool isSingleton)
506 {
507     JSExecutionScope executionScope(vm_);
508     LocalScope scope(vm_);
509     panda::TryCatch trycatch(vm_);
510     std::string module = moduleName;
511     int ret = JSNApi::ExecuteWithSingletonPatternFlag(vm_, bundleName, module, pageSourceFile, isSingleton);
512     HandleUncaughtException(trycatch);
513     if (ret != 0) {
514         TAG_LOGE(AceLogTag::ACE_NAVIGATION, "load pageSourceFile failed code is: %{public}d", ret);
515     }
516     return ret;
517 }
518 } // namespace OHOS::Ace::Framework
519