• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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/declarative_frontend/engine/jsi/jsi_declarative_engine.h"
17 
18 #include <mutex>
19 #include <optional>
20 #include <regex>
21 #include <shared_mutex>
22 #include <string>
23 #include <unistd.h>
24 
25 #include "dfx_jsnapi.h"
26 
27 #include "base/thread/task_executor.h"
28 #include "base/utils/utils.h"
29 #ifdef WINDOWS_PLATFORM
30 #include <algorithm>
31 #endif
32 
33 #include "ace_forward_compatibility.h"
34 #include "scope_manager/native_scope_manager.h"
35 
36 #include "base/base64/base64_util.h"
37 #include "base/i18n/localization.h"
38 #include "base/log/ace_trace.h"
39 #include "base/log/event_report.h"
40 #include "bridge/declarative_frontend/engine/jsi/nativeModule/ui_context_helper.h"
41 #include "core/common/ace_application_info.h"
42 #include "core/common/ace_view.h"
43 #include "core/common/card_scope.h"
44 #include "core/common/connect_server_manager.h"
45 #include "core/common/container.h"
46 #include "core/common/container_scope.h"
47 #include "core/common/layout_inspector.h"
48 #include "core/components_v2/inspector/inspector_constants.h"
49 #include "frameworks/bridge/card_frontend/card_frontend_declarative.h"
50 #include "frameworks/bridge/card_frontend/form_frontend_declarative.h"
51 #include "frameworks/bridge/common/utils/engine_helper.h"
52 #include "frameworks/bridge/declarative_frontend/engine/js_converter.h"
53 #include "frameworks/bridge/declarative_frontend/engine/js_ref_ptr.h"
54 #include "frameworks/bridge/declarative_frontend/engine/js_types.h"
55 #include "frameworks/bridge/declarative_frontend/engine/jsi/js_ui_index.h"
56 #include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_group_js_bridge.h"
57 #include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_types.h"
58 #include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register.h"
59 #include "frameworks/bridge/declarative_frontend/engine/jsi/modules/jsi_context_module.h"
60 #include "frameworks/bridge/declarative_frontend/engine/jsi/modules/jsi_module_manager.h"
61 #include "frameworks/bridge/declarative_frontend/engine/jsi/modules/jsi_syscap_module.h"
62 #include "frameworks/bridge/declarative_frontend/engine/jsi/modules/jsi_timer_module.h"
63 #include "frameworks/bridge/declarative_frontend/jsview/js_local_storage.h"
64 #include "frameworks/bridge/declarative_frontend/jsview/js_mock.h"
65 #include "frameworks/bridge/declarative_frontend/jsview/js_view_register.h"
66 #include "frameworks/bridge/declarative_frontend/jsview/js_view_stack_processor.h"
67 #include "frameworks/bridge/declarative_frontend/jsview/js_xcomponent.h"
68 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
69 #include "frameworks/bridge/js_frontend/engine/common/js_api_perf.h"
70 #include "frameworks/bridge/js_frontend/engine/common/runtime_constants.h"
71 #include "frameworks/bridge/js_frontend/engine/jsi/ark_js_runtime.h"
72 #include "frameworks/bridge/js_frontend/engine/jsi/ark_js_value.h"
73 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_base_utils.h"
74 #include "frameworks/core/components/xcomponent/xcomponent_component_client.h"
75 #include "frameworks/core/components_ng/base/view_stack_processor.h"
76 #include "frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.h"
77 
78 #if defined(PREVIEW)
79 extern const char _binary_jsMockSystemPlugin_abc_start[];
80 extern const char _binary_jsMockSystemPlugin_abc_end[];
81 #endif
82 extern const char _binary_stateMgmt_abc_start[];
83 extern const char _binary_jsEnumStyle_abc_start[];
84 extern const char _binary_jsUIContext_abc_start[];
85 extern const char _binary_arkComponent_abc_start[];
86 extern const char _binary_arkTheme_abc_start[];
87 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
88 extern const char _binary_jsPreload_abc_start[];
89 extern const char _binary_jsPreload_abc_end[];
90 #endif
91 #if !defined(IOS_PLATFORM)
92 extern const char _binary_stateMgmt_abc_end[];
93 extern const char _binary_jsEnumStyle_abc_end[];
94 extern const char _binary_jsUIContext_abc_end[];
95 extern const char _binary_arkComponent_abc_end[];
96 extern const char _binary_arkTheme_abc_end[];
97 #else
98 extern const char* _binary_stateMgmt_abc_end;
99 extern const char* _binary_jsEnumStyle_abc_end;
100 extern const char* _binary_jsUIContext_abc_end;
101 extern const char* _binary_arkComponent_abc_end;
102 extern const char* _binary_arkTheme_abc_end;
103 #endif
104 
105 namespace OHOS::Ace::Framework {
106 namespace {
107 
108 const std::string OHMURL_START_TAG = "@bundle:";
109 
110 #if defined(ANDROID_PLATFORM)
111 const std::string ARK_DEBUGGER_LIB_PATH = "libark_inspector.so";
112 #elif defined(APP_USE_ARM)
113 const std::string ARK_DEBUGGER_LIB_PATH = "/system/lib/platformsdk/libark_inspector.z.so";
114 #else
115 const std::string ARK_DEBUGGER_LIB_PATH = "/system/lib64/platformsdk/libark_inspector.z.so";
116 #endif
117 const std::string FORM_ES_MODULE_CARD_PATH = "ets/widgets.abc";
118 const std::string FORM_ES_MODULE_PATH = "ets/modules.abc";
119 
120 const std::string ASSET_PATH_PREFIX = "/data/storage/el1/bundle/";
121 
122 #ifdef PREVIEW
123 constexpr uint32_t PREFIX_LETTER_NUMBER = 4;
124 #endif
125 constexpr uint32_t MAX_STRING_CACHE_SIZE = 100;
126 
127 // native implementation for js function: perfutil.print()
JsPerfPrint(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)128 shared_ptr<JsValue> JsPerfPrint(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
129     const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
130 {
131     std::string ret = JsApiPerf::GetInstance().PrintToLogs();
132     return runtime->NewString(ret);
133 }
134 
135 // native implementation for js function: perfutil.sleep()
JsPerfSleep(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)136 shared_ptr<JsValue> JsPerfSleep(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
137     const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
138 {
139     int32_t valInt = argv[0]->ToInt32(runtime);
140     usleep(valInt);
141     return runtime->NewNull();
142 }
143 
144 // native implementation for js function: perfutil.begin()
JsPerfBegin(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)145 shared_ptr<JsValue> JsPerfBegin(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
146     const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
147 {
148     int64_t currentTime = GetMicroTickCount();
149     JsApiPerf::GetInstance().InsertJsBeginLog(argv[0]->ToString(runtime), currentTime);
150     return runtime->NewNull();
151 }
152 
153 // native implementation for js function: perfutil.end()
JsPerfEnd(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)154 shared_ptr<JsValue> JsPerfEnd(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
155     const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
156 {
157     int64_t currentTime = GetMicroTickCount();
158     JsApiPerf::GetInstance().InsertJsEndLog(argv[0]->ToString(runtime), currentTime);
159     return runtime->NewNull();
160 }
161 
RequireNativeModule(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)162 shared_ptr<JsValue> RequireNativeModule(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
163     const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
164 {
165     std::string moduleName = argv[0]->ToString(runtime);
166 
167     // has already init module object
168     shared_ptr<JsValue> global = runtime->GetGlobal();
169     shared_ptr<JsValue> moduleObject = global->GetProperty(runtime, moduleName);
170     if (moduleObject != nullptr && moduleObject->IsObject(runtime)) {
171         return moduleObject;
172     }
173 
174     // init module object first time
175     shared_ptr<JsValue> newObject = runtime->NewObject();
176     if (ModuleManager::GetInstance()->InitModule(runtime, newObject, moduleName)) {
177         global->SetProperty(runtime, moduleName, newObject);
178         return newObject;
179     }
180 
181     return runtime->NewNull();
182 }
183 
PreloadJsEnums(const shared_ptr<JsRuntime> & runtime)184 inline bool PreloadJsEnums(const shared_ptr<JsRuntime>& runtime)
185 {
186     std::string str("arkui_binary_jsEnumStyle_abc_loadFile");
187     return runtime->EvaluateJsCode(
188         (uint8_t*)_binary_jsEnumStyle_abc_start, _binary_jsEnumStyle_abc_end - _binary_jsEnumStyle_abc_start, str);
189 }
190 
PreloadStateManagement(const shared_ptr<JsRuntime> & runtime)191 inline bool PreloadStateManagement(const shared_ptr<JsRuntime>& runtime)
192 {
193     // set __hasUIFramework__
194     runtime->GetGlobal()->SetProperty(runtime, "__hasUIFramework__", runtime->NewBoolean(true));
195 #ifdef STATE_MGMT_USE_AOT
196     return runtime->ExecuteJsBinForAOT("/etc/abc/framework/stateMgmt.abc");
197 #else
198     std::string str("arkui_binary_stateMgmt_abc_loadFile");
199     return runtime->EvaluateJsCode(
200         (uint8_t*)_binary_stateMgmt_abc_start, _binary_stateMgmt_abc_end - _binary_stateMgmt_abc_start, str);
201 #endif
202 }
203 
PreloadUIContent(const shared_ptr<JsRuntime> & runtime)204 inline bool PreloadUIContent(const shared_ptr<JsRuntime>& runtime)
205 {
206 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
207     uint8_t* codeStart = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(_binary_jsUIContext_abc_start));
208     int32_t codeLength = _binary_jsUIContext_abc_end - _binary_jsUIContext_abc_start;
209 #else
210     uint8_t* codeStart = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(_binary_jsPreload_abc_start));
211     int32_t codeLength = _binary_jsPreload_abc_end - _binary_jsPreload_abc_start;
212 #endif
213     return runtime->EvaluateJsCode(codeStart, codeLength);
214 }
215 
PreloadArkComponent(const shared_ptr<JsRuntime> & runtime)216 inline bool PreloadArkComponent(const shared_ptr<JsRuntime>& runtime)
217 {
218     std::string str("arkui_binary_arkComponent_abc_loadFile");
219     return runtime->EvaluateJsCode(
220         (uint8_t*)_binary_arkComponent_abc_start, _binary_arkComponent_abc_end - _binary_arkComponent_abc_start, str);
221 }
222 
PreloadArkTheme(const shared_ptr<JsRuntime> & runtime)223 inline bool PreloadArkTheme(const shared_ptr<JsRuntime>& runtime)
224 {
225     std::string str("arkui_binary_arkTheme_abc_loadFile");
226     return runtime->EvaluateJsCode(
227         (uint8_t*)_binary_arkTheme_abc_start, _binary_arkTheme_abc_end - _binary_arkTheme_abc_start, str);
228 }
229 
PreloadConsole(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & global)230 bool PreloadConsole(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& global)
231 {
232     shared_ptr<JsValue> consoleObj = runtime->NewObject();
233     consoleObj->SetProperty(runtime, "log", runtime->NewFunction(JsiBaseUtils::AppInfoLogPrint));
234     consoleObj->SetProperty(runtime, "debug", runtime->NewFunction(JsiBaseUtils::AppDebugLogPrint));
235     consoleObj->SetProperty(runtime, "info", runtime->NewFunction(JsiBaseUtils::AppInfoLogPrint));
236     consoleObj->SetProperty(runtime, "warn", runtime->NewFunction(JsiBaseUtils::AppWarnLogPrint));
237     consoleObj->SetProperty(runtime, "error", runtime->NewFunction(JsiBaseUtils::AppErrorLogPrint));
238     return global->SetProperty(runtime, "console", consoleObj);
239 }
240 
PreloadAceConsole(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & global)241 bool PreloadAceConsole(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& global)
242 {
243     shared_ptr<JsValue> aceConsoleObj = runtime->NewObject();
244     aceConsoleObj->SetProperty(runtime, "log", runtime->NewFunction(JsiBaseUtils::JsInfoLogPrint));
245     aceConsoleObj->SetProperty(runtime, "debug", runtime->NewFunction(JsiBaseUtils::JsDebugLogPrint));
246     aceConsoleObj->SetProperty(runtime, "info", runtime->NewFunction(JsiBaseUtils::JsInfoLogPrint));
247     aceConsoleObj->SetProperty(runtime, "warn", runtime->NewFunction(JsiBaseUtils::JsWarnLogPrint));
248     aceConsoleObj->SetProperty(runtime, "error", runtime->NewFunction(JsiBaseUtils::JsErrorLogPrint));
249     return global->SetProperty(runtime, "aceConsole", aceConsoleObj);
250 }
251 
PreloadAceTrace(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & global)252 bool PreloadAceTrace(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& global)
253 {
254     shared_ptr<JsValue> aceTraceObj = runtime->NewObject();
255     aceTraceObj->SetProperty(runtime, "begin", runtime->NewFunction(JsiBaseUtils::JsTraceBegin));
256     aceTraceObj->SetProperty(runtime, "end", runtime->NewFunction(JsiBaseUtils::JsTraceEnd));
257     return global->SetProperty(runtime, "aceTrace", aceTraceObj);
258 }
259 
PreloadPerfutil(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & global)260 bool PreloadPerfutil(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& global)
261 {
262     shared_ptr<JsValue> perfObj = runtime->NewObject();
263     perfObj->SetProperty(runtime, "printlog", runtime->NewFunction(JsPerfPrint));
264     perfObj->SetProperty(runtime, "sleep", runtime->NewFunction(JsPerfSleep));
265     perfObj->SetProperty(runtime, "begin", runtime->NewFunction(JsPerfBegin));
266     perfObj->SetProperty(runtime, "end", runtime->NewFunction(JsPerfEnd));
267     return global->SetProperty(runtime, "perfutil", perfObj);
268 }
269 
PreloadExports(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & global)270 inline bool PreloadExports(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& global)
271 {
272     shared_ptr<JsValue> exportsUtilObj = runtime->NewObject();
273     return global->SetProperty(runtime, "exports", exportsUtilObj);
274 }
275 
PreloadRequireNative(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & global)276 inline bool PreloadRequireNative(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& global)
277 {
278     return global->SetProperty(runtime, "requireNativeModule", runtime->NewFunction(RequireNativeModule));
279 }
280 
281 /**
282  * The old version of the SDK will not generate the ohmUrl field, so we need to build it ourselves
283  * for forward compatibility. The basic ohmUrl formats are as follows:
284  *
285  * 1. @bundle:{bundleName}/{moduleName}/ets/{pagePath}
286  * examples as follow:
287  *   @bundle:com.example.app/entry/ets/pages/Index
288  *   @bundle:com.example.app/hsp/ets/pages/Second
289  *
290  * 2. @bundle:{bundleName}/{moduleName}@{harModuleName}/ets/{pagePath}
291  * examples as follow:
292  *   @bundle:com.example.app/entry@har/ets/pages/Index
293  *   @bundle:com.example.app/hsp@har/ets/pages/Second
294  * In this case, since the compiler did not generate the harModuleName field and pagePath is a relative path during
295  * compilation, wee need to split the harModuleName and normal pathPath fields from the original pagePath.
296  * for example:
297  *    original pagePath: "../../../../har/src/main/ets/pages/harPageTwo"
298  *     -> harModuleName: "har"
299  *     -> result pagePath: "pages/harPageTwo"
300  *
301  * For any other situation, currently only format 1 ohmUrl can be returned.
302  */
BuildOhmUrl(const std::string & bundleName,const std::string & moduleName,const std::string & pagePath)303 std::string BuildOhmUrl(const std::string& bundleName, const std::string& moduleName, const std::string& pagePath)
304 {
305     std::string tempUrl = OHMURL_START_TAG + bundleName + "/" + moduleName;
306     std::string ohmUrl = tempUrl + "/ets/" + pagePath;
307     auto pos = pagePath.rfind("../");
308     if (pos == std::string::npos) {
309         return ohmUrl;
310     }
311     std::string newPagePath = pagePath.substr(pos + 3);
312     pos = newPagePath.find("/");
313     if (pos == std::string::npos) {
314         return ohmUrl;
315     }
316     std::string harModuleName = newPagePath.substr(0, pos);
317     pos = newPagePath.find("ets");
318     if (pos == std::string::npos) {
319         return ohmUrl;
320     }
321     newPagePath = newPagePath.substr(pos);
322     return tempUrl + "@" + harModuleName + "/" + newPagePath;
323 }
324 
ParseNamedRouterParams(const EcmaVM * vm,const panda::Local<panda::ObjectRef> & params,std::string & bundleName,std::string & moduleName,std::string & pagePath,std::string & pageFullPath,std::string & ohmUrl)325 bool ParseNamedRouterParams(const EcmaVM* vm, const panda::Local<panda::ObjectRef>& params, std::string& bundleName,
326     std::string& moduleName, std::string& pagePath, std::string& pageFullPath, std::string& ohmUrl)
327 {
328     auto jsBundleName = params->Get(vm, panda::StringRef::NewFromUtf8(vm, "bundleName"));
329     auto jsModuleName = params->Get(vm, panda::StringRef::NewFromUtf8(vm, "moduleName"));
330     auto jsPagePath = params->Get(vm, panda::StringRef::NewFromUtf8(vm, "pagePath"));
331     if (!jsBundleName->IsString(vm) || !jsModuleName->IsString(vm) || !jsPagePath->IsString(vm)) {
332         return false;
333     }
334     bundleName = jsBundleName->ToString(vm)->ToString(vm);
335     moduleName = jsModuleName->ToString(vm)->ToString(vm);
336     pagePath = jsPagePath->ToString(vm)->ToString(vm);
337     bool ohmUrlValid = false;
338     if (params->Has(vm, panda::StringRef::NewFromUtf8(vm, "ohmUrl"))) {
339         auto jsOhmUrl = params->Get(vm, panda::StringRef::NewFromUtf8(vm, "ohmUrl"));
340         if (jsOhmUrl->IsString(vm)) {
341             ohmUrl = jsOhmUrl->ToString(vm)->ToString(vm);
342             ohmUrlValid = true;
343         } else {
344             LOGE("add named router record with invalid ohmUrl!");
345         }
346     }
347     if (!ohmUrlValid) {
348         LOGI("build ohmUrl for forward compatibility");
349         ohmUrl = BuildOhmUrl(bundleName, moduleName, pagePath);
350     }
351 
352     std::string integratedHspName = "false";
353     // Integrated hsp adaptation
354     if (params->Has(vm, panda::StringRef::NewFromUtf8(vm, "integratedHsp"))) {
355         auto integratedHsp = params->Get(vm, panda::StringRef::NewFromUtf8(vm, "integratedHsp"));
356         if (integratedHsp->IsString(vm)) {
357             integratedHspName = integratedHsp->ToString(vm)->ToString(vm);
358         }
359     }
360     if (integratedHspName == "true") {
361         LocalScope scope(vm);
362         bundleName = JSNApi::GetBundleName(const_cast<EcmaVM *>(vm));
363     }
364 
365     if (params->Has(vm, panda::StringRef::NewFromUtf8(vm, "pageFullPath"))) {
366         auto pageFullPathInfo = params->Get(vm, panda::StringRef::NewFromUtf8(vm, "pageFullPath"));
367         if (pageFullPathInfo->IsString(vm)) {
368             pageFullPath = pageFullPathInfo->ToString(vm)->ToString(vm);
369         }
370     }
371 
372     return true;
373 }
374 } // namespace
375 
376 // -----------------------
377 // Start JsiDeclarativeEngineInstance
378 // -----------------------
379 std::map<std::string, std::string> JsiDeclarativeEngineInstance::mediaResourceFileMap_;
380 
381 std::unique_ptr<JsonValue> JsiDeclarativeEngineInstance::currentConfigResourceData_;
382 std::shared_mutex JsiDeclarativeEngineInstance::sharedMutex_;
383 
384 bool JsiDeclarativeEngineInstance::isModulePreloaded_ = false;
385 bool JsiDeclarativeEngineInstance::isModuleInitialized_ = false;
386 shared_ptr<JsRuntime> JsiDeclarativeEngineInstance::globalRuntime_;
387 std::shared_mutex JsiDeclarativeEngineInstance::globalRuntimeMutex_;
388 
389 // for async task callback executed after this instance has been destroyed.
390 thread_local void* cardRuntime_;
391 thread_local shared_ptr<JsRuntime> localRuntime_;
392 
393 // ArkTsCard start
394 thread_local bool isUnique_ = false;
395 // ArkTsCard end
396 
397 thread_local bool isWorker_ = false;
398 
399 thread_local bool isDynamicModulePreloaded_ = false;
400 
~JsiDeclarativeEngineInstance()401 JsiDeclarativeEngineInstance::~JsiDeclarativeEngineInstance()
402 {
403     CHECK_RUN_ON(JS);
404     LOG_DESTROY();
405 
406     if (runningPage_) {
407         runningPage_->OnJsEngineDestroy();
408     }
409 
410     if (stagingPage_) {
411         stagingPage_->OnJsEngineDestroy();
412     }
413 
414     if (runtime_) {
415         runtime_->RegisterUncaughtExceptionHandler(nullptr);
416         runtime_->Reset();
417     }
418     runtime_.reset();
419     runtime_ = nullptr;
420 }
421 
InitJsEnv(bool debuggerMode,const std::unordered_map<std::string,void * > & extraNativeObject,const shared_ptr<JsRuntime> & runtime)422 bool JsiDeclarativeEngineInstance::InitJsEnv(bool debuggerMode,
423     const std::unordered_map<std::string, void*>& extraNativeObject, const shared_ptr<JsRuntime>& runtime)
424 {
425     CHECK_RUN_ON(JS);
426     ACE_SCOPED_TRACE("JsiDeclarativeEngineInstance::InitJsEnv");
427     if (runtime != nullptr) {
428         runtime_ = runtime;
429         usingSharedRuntime_ = true;
430     } else {
431         runtime_.reset(new ArkJSRuntime());
432     }
433 
434     if (runtime_ == nullptr) {
435         EventReport::SendJsException(JsExcepType::JS_ENGINE_INIT_ERR);
436         return false;
437     }
438 
439 #if defined(PREVIEW)
440     auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime_);
441     arkRuntime->SetPkgNameList(pkgNameMap_);
442     arkRuntime->SetPkgAliasList(pkgAliasMap_);
443     arkRuntime->SetpkgContextInfoList(pkgContextInfoMap_);
444 #endif
445     auto container = Container::Current();
446     if (container) {
447         auto uid = container->GetAppRunningUniqueId();
448         runtime_->SetUniqueId(uid);
449     }
450     runtime_->SetLogPrint(PrintLog);
451     std::string libraryPath = "";
452     if (debuggerMode) {
453         libraryPath = ARK_DEBUGGER_LIB_PATH;
454         SetDebuggerPostTask();
455     }
456     if (!usingSharedRuntime_ && !runtime_->Initialize(libraryPath, isDebugMode_, instanceId_)) {
457         return false;
458     }
459 
460     runtime_->SetEmbedderData(this);
461     runtime_->RegisterUncaughtExceptionHandler(JsiBaseUtils::ReportJsErrorEvent);
462 
463 #if !defined(PREVIEW)
464     for (const auto& [key, value] : extraNativeObject) {
465         shared_ptr<JsValue> nativeValue = runtime_->NewNativePointer(value);
466         runtime_->GetGlobal()->SetProperty(runtime_, key, nativeValue);
467     }
468 
469     auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime_);
470     arkRuntime->SetLanguage("ets");
471     runtime_->StartDebugger();
472 #else
473     if (usingSharedRuntime_) {
474         auto global = runtime_->GetGlobal();
475         JsiTimerModule::GetInstance()->InitTimerModule(runtime_, global);
476     }
477 #endif
478     return true;
479 }
480 
InitJsObject()481 void JsiDeclarativeEngineInstance::InitJsObject()
482 {
483     CHECK_RUN_ON(JS);
484     LocalScope scope(std::static_pointer_cast<ArkJSRuntime>(runtime_)->GetEcmaVm());
485     if (!isModulePreloaded_ || !usingSharedRuntime_) {
486         InitGlobalObjectTemplate();
487     }
488 
489     // no need to initialize functions on global when use shared runtime
490     if (!usingSharedRuntime_ || !isModuleInitialized_ || isUnique_) { // ArtTsCard
491         InitGroupJsBridge();
492         if (!isModulePreloaded_ || !usingSharedRuntime_ || isUnique_) { // ArtTsCard
493             InitConsoleModule();
494             InitAceModule();
495             InitJsExportsUtilObject();
496             InitJsNativeModuleObject();
497             InitPerfUtilModule();
498             InitJsContextModuleObject();
499         }
500     } else {
501         auto container = Container::Current();
502         if (container && container->IsDynamicRender() && !isDynamicModulePreloaded_) {
503             isDynamicModulePreloaded_ = true;
504             LOGD("init ace module for dynamic component");
505             auto vm = std::static_pointer_cast<ArkJSRuntime>(runtime_)->GetEcmaVm();
506             LocalScope scope(vm);
507             RegisterStringCacheTable(vm, MAX_STRING_CACHE_SIZE);
508             // preload js views
509             JsRegisterViews(JSNApi::GetGlobalObject(vm));
510 
511             shared_ptr<JsValue> global = runtime_->GetGlobal();
512 
513             PreloadConsole(runtime_, global);
514             PreloadAceConsole(runtime_, global);
515             PreloadAceTrace(runtime_, global);
516 
517             // preload getContext
518             JsiContextModule::GetInstance()->InitContextModule(runtime_, global);
519 
520             PreloadPerfutil(runtime_, global);
521             PreloadExports(runtime_, global);
522             PreloadRequireNative(runtime_, global);
523             PreloadStateManagement(runtime_);
524             PreloadUIContent(runtime_);
525             PreloadArkComponent(runtime_);
526             PreloadArkTheme(runtime_);
527         }
528     }
529 
530     if (usingSharedRuntime_) {
531         isModuleInitialized_ = true;
532     }
533 
534     // load resourceConfig
535     std::unique_lock<std::shared_mutex> lock(sharedMutex_);
536     currentConfigResourceData_ = JsonUtil::CreateArray(true);
537     frontendDelegate_->LoadResourceConfiguration(mediaResourceFileMap_, currentConfigResourceData_);
538     isEngineInstanceInitialized_ = true;
539 }
540 
FireJsEvent(const std::string & eventStr)541 bool JsiDeclarativeEngineInstance::FireJsEvent(const std::string& eventStr)
542 {
543     return true;
544 }
545 
InitAceModule()546 void JsiDeclarativeEngineInstance::InitAceModule()
547 {
548     if (isUnique_ == false) {
549         PreloadStateManagement(runtime_);
550         PreloadJsEnums(runtime_);
551         PreloadArkComponent(runtime_);
552         PreloadArkTheme(runtime_);
553         PreloadUIContent(runtime_);
554     }
555 #if defined(PREVIEW)
556     std::string jsMockSystemPluginString(_binary_jsMockSystemPlugin_abc_start,
557         _binary_jsMockSystemPlugin_abc_end - _binary_jsMockSystemPlugin_abc_start);
558     runtime_->EvaluateJsCode((uint8_t*)(jsMockSystemPluginString.c_str()), jsMockSystemPluginString.length());
559     const std::string filename = "apiMock/jsMockHmos.abc";
560     std::string content;
561     if (!frontendDelegate_->GetAssetContent(filename, content)) {
562         LOGW("Failed to get the content from the file %{public}s", filename.c_str());
563         return;
564     }
565     if (!runtime_->EvaluateJsCode((uint8_t*)(content.c_str()), content.length())) {
566         LOGW("EvaluateJsCode jsMockHmos failed");
567     }
568 #endif
569 }
570 
OHOS_ACE_PreloadAceModuleWorker(void * runtime)571 extern "C" ACE_FORCE_EXPORT void OHOS_ACE_PreloadAceModuleWorker(void* runtime)
572 {
573     JsiDeclarativeEngineInstance::PreloadAceModuleWorker(runtime);
574 }
575 
PreloadAceModuleWorker(void * runtime)576 void JsiDeclarativeEngineInstance::PreloadAceModuleWorker(void* runtime)
577 {
578     isWorker_ = true;
579     auto sharedRuntime = reinterpret_cast<NativeEngine*>(runtime);
580 
581     if (!sharedRuntime) {
582         return;
583     }
584     std::shared_ptr<ArkJSRuntime> arkRuntime = std::make_shared<ArkJSRuntime>();
585     auto nativeArkEngine = static_cast<ArkNativeEngine*>(sharedRuntime);
586     EcmaVM* vm = const_cast<EcmaVM*>(nativeArkEngine->GetEcmaVm());
587     if (vm == nullptr) {
588         return;
589     }
590     if (!arkRuntime->InitializeFromExistVM(vm)) {
591         return;
592     }
593     arkRuntime->SetNativeEngine(nativeArkEngine);
594     localRuntime_ = arkRuntime;
595     LocalScope scope(vm);
596 
597     RegisterStringCacheTable(vm, MAX_STRING_CACHE_SIZE);
598     // preload js views
599     JsRegisterWorkerViews(JSNApi::GetGlobalObject(vm), runtime);
600 
601     // preload js enums
602     PreloadJsEnums(arkRuntime);
603 
604     // preload requireNative
605     shared_ptr<JsValue> global = arkRuntime->GetGlobal();
606     JSMock::PreloadWorkerRequireNative(arkRuntime, global);
607 }
608 
OHOS_ACE_PreloadAceModule(void * runtime)609 extern "C" ACE_FORCE_EXPORT void OHOS_ACE_PreloadAceModule(void* runtime)
610 {
611     JsiDeclarativeEngineInstance::PreloadAceModule(runtime);
612 }
613 
PreloadAceModule(void * runtime)614 void JsiDeclarativeEngineInstance::PreloadAceModule(void* runtime)
615 {
616 #ifndef NG_BUILD
617     if (AceForwardCompatibility::PipelineChanged()) {
618         isModulePreloaded_ = false;
619     }
620 #endif
621     if (isModulePreloaded_ && !IsPlugin()) {
622         return;
623     }
624     auto sharedRuntime = reinterpret_cast<NativeEngine*>(runtime);
625 
626     if (!sharedRuntime) {
627         return;
628     }
629     std::shared_ptr<ArkJSRuntime> arkRuntime = std::make_shared<ArkJSRuntime>();
630     auto nativeArkEngine = static_cast<ArkNativeEngine*>(sharedRuntime);
631     EcmaVM* vm = const_cast<EcmaVM*>(nativeArkEngine->GetEcmaVm());
632     if (vm == nullptr) {
633         return;
634     }
635     if (!arkRuntime->InitializeFromExistVM(vm)) {
636         return;
637     }
638     LocalScope scope(vm);
639     {
640         std::unique_lock<std::shared_mutex> lock(globalRuntimeMutex_);
641         globalRuntime_ = arkRuntime;
642     }
643 
644     RegisterStringCacheTable(vm, MAX_STRING_CACHE_SIZE);
645     // preload js views
646     JsRegisterViews(JSNApi::GetGlobalObject(vm), runtime);
647 
648     // preload aceConsole
649     shared_ptr<JsValue> global = arkRuntime->GetGlobal();
650     PreloadAceConsole(arkRuntime, global);
651 
652     // preload aceTrace
653     PreloadAceTrace(arkRuntime, global);
654 
655     // preload getContext
656     JsiContextModule::GetInstance()->InitContextModule(arkRuntime, global);
657 
658     // preload perfutil
659     PreloadPerfutil(arkRuntime, global);
660 
661     // preload exports and requireNative
662     PreloadExports(arkRuntime, global);
663     PreloadRequireNative(arkRuntime, global);
664 
665     // preload js enums
666     bool jsEnumStyleResult = PreloadJsEnums(arkRuntime);
667     if (!jsEnumStyleResult) {
668         std::unique_lock<std::shared_mutex> lock(globalRuntimeMutex_);
669         globalRuntime_ = nullptr;
670         return;
671     }
672 
673     bool evalResult = PreloadStateManagement(arkRuntime);
674 
675     PreloadUIContent(arkRuntime);
676 
677     // preload ark component
678     bool arkComponentResult = PreloadArkComponent(arkRuntime);
679     if (!arkComponentResult) {
680         std::unique_lock<std::shared_mutex> lock(globalRuntimeMutex_);
681         globalRuntime_ = nullptr;
682         return;
683     }
684 
685     // preload ark styles
686     bool arkThemeResult = PreloadArkTheme(arkRuntime);
687     if (!arkThemeResult) {
688         std::unique_lock<std::shared_mutex> lock(globalRuntimeMutex_);
689         globalRuntime_ = nullptr;
690         return;
691     }
692 
693     isModulePreloaded_ = evalResult;
694     {
695         std::unique_lock<std::shared_mutex> lock(globalRuntimeMutex_);
696         globalRuntime_ = nullptr;
697     }
698     localRuntime_ = arkRuntime;
699     cardRuntime_ = runtime;
700 }
701 
InitConsoleModule()702 void JsiDeclarativeEngineInstance::InitConsoleModule()
703 {
704     ACE_SCOPED_TRACE("JsiDeclarativeEngineInstance::InitConsoleModule");
705     shared_ptr<JsValue> global = runtime_->GetGlobal();
706 
707     // app log method
708     if (!usingSharedRuntime_) {
709         PreloadConsole(runtime_, global);
710     }
711 
712     if (isModulePreloaded_ && usingSharedRuntime_ && !IsPlugin() && !isUnique_) { // ArkTsCard
713         return;
714     }
715 
716     // js framework log method
717     PreloadAceConsole(runtime_, global);
718 
719     // js framework trace method
720     PreloadAceTrace(runtime_, global);
721 }
722 
InitConsoleModule(ArkNativeEngine * engine)723 void JsiDeclarativeEngineInstance::InitConsoleModule(ArkNativeEngine* engine)
724 {
725     ACE_SCOPED_TRACE("JsiDeclarativeEngineInstance::RegisterConsoleModule");
726     napi_env env = reinterpret_cast<napi_env>(engine);
727     napi_value globalObj;
728     napi_get_global(env, &globalObj);
729     napi_valuetype valueType = napi_undefined;
730     napi_typeof(env, globalObj, &valueType);
731     if (valueType != napi_object) {
732         return;
733     }
734 
735     napi_value logValue;
736     napi_create_function(env, "log", strlen("log"), AppInfoLogPrint, nullptr, &logValue);
737     napi_value debugValue;
738     napi_create_function(env, "debug", strlen("debug"), AppDebugLogPrint, nullptr, &debugValue);
739     napi_value infoValue;
740     napi_create_function(env, "info", strlen("info"), AppInfoLogPrint, nullptr, &infoValue);
741     napi_value warnValue;
742     napi_create_function(env, "warn", strlen("warn"), AppWarnLogPrint, nullptr, &warnValue);
743     napi_value errorValue;
744     napi_create_function(env, "error", strlen("error"), AppErrorLogPrint, nullptr, &errorValue);
745     napi_value consoleObj = nullptr;
746     napi_create_object(env, &consoleObj);
747     napi_set_named_property(env, consoleObj, "log", logValue);
748     napi_set_named_property(env, consoleObj, "debug", debugValue);
749     napi_set_named_property(env, consoleObj, "info", infoValue);
750     napi_set_named_property(env, consoleObj, "warn", warnValue);
751     napi_set_named_property(env, consoleObj, "error", errorValue);
752     napi_set_named_property(env, globalObj, "console", consoleObj);
753 }
754 
InitPerfUtilModule()755 void JsiDeclarativeEngineInstance::InitPerfUtilModule()
756 {
757     ACE_SCOPED_TRACE("JsiDeclarativeEngineInstance::InitPerfUtilModule");
758     shared_ptr<JsValue> global = runtime_->GetGlobal();
759     PreloadPerfutil(runtime_, global);
760 }
761 
InitJsExportsUtilObject()762 void JsiDeclarativeEngineInstance::InitJsExportsUtilObject()
763 {
764     shared_ptr<JsValue> global = runtime_->GetGlobal();
765     PreloadExports(runtime_, global);
766 }
767 
InitJsNativeModuleObject()768 void JsiDeclarativeEngineInstance::InitJsNativeModuleObject()
769 {
770     shared_ptr<JsValue> global = runtime_->GetGlobal();
771     PreloadRequireNative(runtime_, global);
772     auto context = PipelineBase::GetCurrentContext();
773     CHECK_NULL_VOID(context);
774     if (!usingSharedRuntime_) {
775         if (!context->IsFormRender()) {
776             JsiTimerModule::GetInstance()->InitTimerModule(runtime_, global);
777         }
778 
779         JsiSyscapModule::GetInstance()->InitSyscapModule(runtime_, global);
780     }
781 }
782 
InitJsContextModuleObject()783 void JsiDeclarativeEngineInstance::InitJsContextModuleObject()
784 {
785     JsiContextModule::GetInstance()->InitContextModule(runtime_, runtime_->GetGlobal());
786 }
787 
InitGlobalObjectTemplate()788 void JsiDeclarativeEngineInstance::InitGlobalObjectTemplate()
789 {
790     auto runtime = std::static_pointer_cast<ArkJSRuntime>(runtime_);
791     RegisterStringCacheTable(runtime->GetEcmaVm(), MAX_STRING_CACHE_SIZE);
792     JsRegisterViews(JSNApi::GetGlobalObject(runtime->GetEcmaVm()), reinterpret_cast<void*>(nativeEngine_));
793 }
794 
InitGroupJsBridge()795 void JsiDeclarativeEngineInstance::InitGroupJsBridge()
796 {
797     auto groupJsBridge = DynamicCast<JsiDeclarativeGroupJsBridge>(frontendDelegate_->GetGroupJsBridge());
798     if (groupJsBridge == nullptr || groupJsBridge->InitializeGroupJsBridge(runtime_) == JS_CALL_FAIL) {
799         EventReport::SendJsException(JsExcepType::JS_ENGINE_INIT_ERR);
800     }
801     auto runtime = std::static_pointer_cast<ArkJSRuntime>(runtime_);
802     JsUINodeRegisterCleanUp(JSNApi::GetGlobalObject(runtime->GetEcmaVm()));
803 }
804 
RootViewHandle(panda::Local<panda::ObjectRef> value)805 void JsiDeclarativeEngineInstance::RootViewHandle(panda::Local<panda::ObjectRef> value)
806 {
807     RefPtr<JsAcePage> page = JsiDeclarativeEngineInstance::GetStagingPage(Container::CurrentId());
808     if (page != nullptr) {
809         auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(GetCurrentRuntime());
810         if (!arkRuntime) {
811             return;
812         }
813         auto engine = EngineHelper::GetCurrentEngine();
814         auto jsiEngine = AceType::DynamicCast<JsiDeclarativeEngine>(engine);
815         if (!jsiEngine) {
816             return;
817         }
818         auto engineInstance = jsiEngine->GetEngineInstance();
819         if (engineInstance == nullptr) {
820             return;
821         }
822         engineInstance->SetRootView(page->GetPageId(), panda::Global<panda::ObjectRef>(arkRuntime->GetEcmaVm(), value));
823     }
824 }
825 
DestroyRootViewHandle(int32_t pageId)826 void JsiDeclarativeEngineInstance::DestroyRootViewHandle(int32_t pageId)
827 {
828     CHECK_RUN_ON(JS);
829     JAVASCRIPT_EXECUTION_SCOPE_STATIC;
830     auto iter = rootViewMap_.find(pageId);
831     if (iter != rootViewMap_.end()) {
832         auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime_);
833         if (!arkRuntime) {
834             return;
835         }
836         panda::Local<panda::ObjectRef> rootView = iter->second.ToLocal(arkRuntime->GetEcmaVm());
837         auto* jsView = static_cast<JSView*>(rootView->GetNativePointerField(arkRuntime->GetEcmaVm(), 0));
838         if (jsView != nullptr) {
839             jsView->Destroy(nullptr);
840         }
841         iter->second.FreeGlobalHandleAddr();
842         rootViewMap_.erase(pageId);
843     }
844 }
845 
DestroyAllRootViewHandle()846 void JsiDeclarativeEngineInstance::DestroyAllRootViewHandle()
847 {
848     CHECK_RUN_ON(JS);
849     JAVASCRIPT_EXECUTION_SCOPE_STATIC;
850     auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime_);
851     if (!arkRuntime) {
852         return;
853     }
854     for (const auto& pair : rootViewMap_) {
855         auto globalRootView = pair.second;
856         panda::Local<panda::ObjectRef> rootView = globalRootView.ToLocal(arkRuntime->GetEcmaVm());
857         auto* jsView = static_cast<JSView*>(rootView->GetNativePointerField(arkRuntime->GetEcmaVm(), 0));
858         if (jsView != nullptr) {
859             jsView->Destroy(nullptr);
860         }
861         globalRootView.FreeGlobalHandleAddr();
862     }
863     rootViewMap_.clear();
864 }
865 
FlushReload()866 void JsiDeclarativeEngineInstance::FlushReload()
867 {
868     CHECK_RUN_ON(JS);
869     JAVASCRIPT_EXECUTION_SCOPE_STATIC;
870     if (rootViewMap_.empty()) {
871         return;
872     }
873     auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime_);
874     if (!arkRuntime) {
875         return;
876     }
877     for (const auto& pair : rootViewMap_) {
878         auto globalRootView = pair.second;
879         panda::Local<panda::ObjectRef> rootView = globalRootView.ToLocal(arkRuntime->GetEcmaVm());
880         auto* jsView = static_cast<JSView*>(rootView->GetNativePointerField(arkRuntime->GetEcmaVm(), 0));
881         if (jsView != nullptr) {
882             jsView->MarkNeedUpdate();
883         }
884     }
885 }
886 
GetI18nStringResource(const std::string & targetStringKey,const std::string & targetStringValue)887 std::unique_ptr<JsonValue> JsiDeclarativeEngineInstance::GetI18nStringResource(
888     const std::string& targetStringKey, const std::string& targetStringValue)
889 {
890     std::shared_lock<std::shared_mutex> lock(sharedMutex_);
891     auto resourceI18nFileNum = currentConfigResourceData_->GetArraySize();
892     for (int i = 0; i < resourceI18nFileNum; i++) {
893         auto priorResource = currentConfigResourceData_->GetArrayItem(i);
894         if ((priorResource->Contains(targetStringKey))) {
895             auto valuePair = priorResource->GetValue(targetStringKey);
896             if (valuePair->Contains(targetStringValue)) {
897                 return valuePair->GetValue(targetStringValue);
898             }
899         }
900     }
901 
902     return JsonUtil::Create(true);
903 }
904 
GetMediaResource(const std::string & targetFileName)905 std::string JsiDeclarativeEngineInstance::GetMediaResource(const std::string& targetFileName)
906 {
907     auto iter = mediaResourceFileMap_.find(targetFileName);
908 
909     if (iter != mediaResourceFileMap_.end()) {
910         return iter->second;
911     }
912 
913     return std::string();
914 }
915 
GetRunningPage(int32_t instanceId)916 RefPtr<JsAcePage> JsiDeclarativeEngineInstance::GetRunningPage(int32_t instanceId)
917 {
918     auto engine = EngineHelper::GetEngine(instanceId);
919     auto jsiEngine = AceType::DynamicCast<JsiDeclarativeEngine>(engine);
920     if (!jsiEngine) {
921         return nullptr;
922     }
923     auto engineInstance = jsiEngine->GetEngineInstance();
924     if (engineInstance == nullptr) {
925         return nullptr;
926     }
927     return engineInstance->GetRunningPage();
928 }
929 
GetStagingPage(int32_t instanceId)930 RefPtr<JsAcePage> JsiDeclarativeEngineInstance::GetStagingPage(int32_t instanceId)
931 {
932     auto engine = EngineHelper::GetEngine(instanceId);
933     auto jsiEngine = AceType::DynamicCast<JsiDeclarativeEngine>(engine);
934     if (!jsiEngine) {
935         return nullptr;
936     }
937     auto engineInstance = jsiEngine->GetEngineInstance();
938     if (engineInstance == nullptr) {
939         return nullptr;
940     }
941     return engineInstance->GetStagingPage();
942 }
943 
GetCurrentRuntime()944 shared_ptr<JsRuntime> JsiDeclarativeEngineInstance::GetCurrentRuntime()
945 {
946     auto jsRuntime = InnerGetCurrentRuntime();
947     if (isUnique_ && jsRuntime) {
948         return jsRuntime;
949     }
950 
951     // ArkTsCard
952     if (isUnique_ && localRuntime_) {
953         return localRuntime_;
954     }
955 
956     if (isWorker_ && localRuntime_) {
957         return localRuntime_;
958     }
959 
960     // Preload
961     std::shared_lock<std::shared_mutex> lock(globalRuntimeMutex_);
962     if (globalRuntime_) {
963         return globalRuntime_;
964     }
965 
966     return jsRuntime == nullptr ? localRuntime_ : jsRuntime;
967 }
968 
InnerGetCurrentRuntime()969 shared_ptr<JsRuntime> JsiDeclarativeEngineInstance::InnerGetCurrentRuntime()
970 {
971     auto engine = EngineHelper::GetCurrentEngine();
972     auto jsiEngine = AceType::DynamicCast<JsiDeclarativeEngine>(engine);
973     if (!jsiEngine) {
974         return nullptr;
975     }
976 
977     auto engineInstance = jsiEngine->GetEngineInstance();
978     if (engineInstance == nullptr) {
979         return nullptr;
980     }
981 
982     if (isUnique_ && !engineInstance->IsEngineInstanceInitialized()) {
983         return nullptr;
984     }
985 
986     return engineInstance->GetJsRuntime();
987 }
988 
CallGetUIContextFunc(const shared_ptr<JsRuntime> & runtime,const std::vector<shared_ptr<JsValue>> & argv)989 shared_ptr<JsValue> JsiDeclarativeEngineInstance::CallGetUIContextFunc(
990     const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv)
991 {
992     shared_ptr<JsValue> global = runtime->GetGlobal();
993     shared_ptr<JsValue> func = global->GetProperty(runtime, "__getUIContext__");
994     if (!func->IsFunction(runtime)) {
995         return nullptr;
996     }
997 
998     shared_ptr<JsValue> retVal = func->Call(runtime, global, argv, argv.size());
999     if (!retVal) {
1000         return nullptr;
1001     }
1002 
1003     return retVal;
1004 }
1005 
CallGetFrameNodeByNodeIdFunc(const shared_ptr<JsRuntime> & runtime,const std::vector<shared_ptr<JsValue>> & argv)1006 shared_ptr<JsValue> JsiDeclarativeEngineInstance::CallGetFrameNodeByNodeIdFunc(
1007     const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv)
1008 {
1009     shared_ptr<JsValue> global = runtime->GetGlobal();
1010     shared_ptr<JsValue> func = global->GetProperty(runtime, "__getFrameNodeByNodeId__");
1011     if (!func->IsFunction(runtime)) {
1012         return nullptr;
1013     }
1014 
1015     shared_ptr<JsValue> retVal = func->Call(runtime, global, argv, argv.size());
1016     if (!retVal) {
1017         return nullptr;
1018     }
1019 
1020     return retVal;
1021 }
1022 
PostJsTask(const shared_ptr<JsRuntime> & runtime,std::function<void ()> && task,const std::string & name)1023 void JsiDeclarativeEngineInstance::PostJsTask(
1024     const shared_ptr<JsRuntime>& runtime, std::function<void()>&& task, const std::string& name)
1025 {
1026     if (runtime == nullptr) {
1027         return;
1028     }
1029     auto engineInstance = static_cast<JsiDeclarativeEngineInstance*>(runtime->GetEmbedderData());
1030     if (engineInstance == nullptr) {
1031         return;
1032     }
1033     engineInstance->GetDelegate()->PostJsTask(std::move(task), name);
1034 }
1035 
TriggerPageUpdate(const shared_ptr<JsRuntime> & runtime)1036 void JsiDeclarativeEngineInstance::TriggerPageUpdate(const shared_ptr<JsRuntime>& runtime)
1037 {
1038     CHECK_NULL_VOID(runtime);
1039     auto engineInstance = static_cast<JsiDeclarativeEngineInstance*>(runtime->GetEmbedderData());
1040     CHECK_NULL_VOID(engineInstance);
1041     auto page = engineInstance->GetRunningPage();
1042     CHECK_NULL_VOID(page);
1043     engineInstance->GetDelegate()->TriggerPageUpdate(page->GetPageId());
1044 }
1045 
GetPipelineContext(const shared_ptr<JsRuntime> & runtime)1046 RefPtr<PipelineBase> JsiDeclarativeEngineInstance::GetPipelineContext(const shared_ptr<JsRuntime>& runtime)
1047 {
1048     if (runtime == nullptr) {
1049         return nullptr;
1050     }
1051     auto engineInstance = static_cast<JsiDeclarativeEngineInstance*>(runtime->GetEmbedderData());
1052     if (engineInstance == nullptr) {
1053         return nullptr;
1054     }
1055     return engineInstance->GetDelegate()->GetPipelineContext();
1056 }
1057 
FlushCommandBuffer(void * context,const std::string & command)1058 void JsiDeclarativeEngineInstance::FlushCommandBuffer(void* context, const std::string& command)
1059 {
1060     return;
1061 }
1062 
IsPlugin()1063 bool JsiDeclarativeEngineInstance::IsPlugin()
1064 {
1065     return (ContainerScope::CurrentId() >= MIN_PLUGIN_SUBCONTAINER_ID);
1066 }
1067 
SetDebuggerPostTask()1068 void JsiDeclarativeEngineInstance::SetDebuggerPostTask()
1069 {
1070     auto weakDelegate = AceType::WeakClaim(AceType::RawPtr(frontendDelegate_));
1071     auto&& postTask = [weakDelegate](std::function<void()>&& task) {
1072         auto delegate = weakDelegate.Upgrade();
1073         if (delegate == nullptr) {
1074             return;
1075         }
1076         delegate->PostJsTask(std::move(task), "ArkUIDebuggerTask");
1077     };
1078     std::static_pointer_cast<ArkJSRuntime>(runtime_)->SetDebuggerPostTask(postTask);
1079 }
1080 
RegisterFaPlugin()1081 void JsiDeclarativeEngineInstance::RegisterFaPlugin()
1082 {
1083     shared_ptr<JsValue> global = runtime_->GetGlobal();
1084     shared_ptr<JsValue> requireNapiFunc = global->GetProperty(runtime_, "requireNapi");
1085     if (!requireNapiFunc || !requireNapiFunc->IsFunction(runtime_)) {
1086         return;
1087     }
1088     std::vector<shared_ptr<JsValue>> argv = { runtime_->NewString("FeatureAbility") };
1089     requireNapiFunc->Call(runtime_, global, argv, argv.size());
1090 }
1091 
GetContextValue()1092 napi_value JsiDeclarativeEngineInstance::GetContextValue()
1093 {
1094     auto runtime = GetJsRuntime();
1095 
1096     // obtain uiContext instance
1097     std::vector<shared_ptr<JsValue>> argv = { runtime->NewNumber(instanceId_) };
1098     shared_ptr<JsValue> uiContext = CallGetUIContextFunc(runtime, argv);
1099     if (uiContext) {
1100         SetContextValue(uiContext);
1101     }
1102 
1103     auto arkJSRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
1104     if (!arkJSRuntime) {
1105         return nullptr;
1106     }
1107     auto arkJSValue = std::static_pointer_cast<ArkJSValue>(uiContext_);
1108     if (!arkJSValue) {
1109         return nullptr;
1110     }
1111     auto arkNativeEngine = static_cast<ArkNativeEngine*>(GetNativeEngine());
1112     if (!arkNativeEngine) {
1113         return nullptr;
1114     }
1115     napi_value napiValue = ArkNativeEngine::ArkValueToNapiValue(
1116         reinterpret_cast<napi_env>(GetNativeEngine()), arkJSValue->GetValue(arkJSRuntime));
1117 
1118     return napiValue;
1119 }
1120 
GetFrameNodeValueByNodeId(int32_t nodeId)1121 napi_value JsiDeclarativeEngineInstance::GetFrameNodeValueByNodeId(int32_t nodeId)
1122 {
1123     auto runtime = GetJsRuntime();
1124 
1125     // obtain frameNode instance
1126     std::vector<shared_ptr<JsValue>> argv = { runtime->NewNumber(instanceId_), runtime->NewNumber(nodeId) };
1127     shared_ptr<JsValue> frameNode = CallGetFrameNodeByNodeIdFunc(runtime, argv);
1128 
1129     auto arkJSRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
1130     if (!arkJSRuntime) {
1131         return nullptr;
1132     }
1133     auto arkJSValue = std::static_pointer_cast<ArkJSValue>(frameNode);
1134     if (!arkJSValue) {
1135         return nullptr;
1136     }
1137     auto arkNativeEngine = static_cast<ArkNativeEngine*>(GetNativeEngine());
1138     if (!arkNativeEngine) {
1139         return nullptr;
1140     }
1141     napi_value napiValue = ArkNativeEngine::ArkValueToNapiValue(
1142         reinterpret_cast<napi_env>(GetNativeEngine()), arkJSValue->GetValue(arkJSRuntime));
1143 
1144     return napiValue;
1145 }
1146 
1147 thread_local std::unordered_map<std::string, NamedRouterProperty> JsiDeclarativeEngine::namedRouterRegisterMap_;
1148 thread_local std::unordered_map<std::string, std::string> JsiDeclarativeEngine::routerPathInfoMap_;
1149 thread_local std::unordered_map<std::string, panda::Global<panda::ObjectRef>> JsiDeclarativeEngine::builderMap_;
1150 thread_local panda::Global<panda::ObjectRef> JsiDeclarativeEngine::obj_;
1151 
1152 // -----------------------
1153 // Start JsiDeclarativeEngine
1154 // -----------------------
~JsiDeclarativeEngine()1155 JsiDeclarativeEngine::~JsiDeclarativeEngine()
1156 {
1157     CHECK_RUN_ON(JS);
1158     LOG_DESTROY();
1159 }
1160 
Destroy()1161 void JsiDeclarativeEngine::Destroy()
1162 {
1163     CHECK_RUN_ON(JS);
1164 
1165 #ifdef USE_ARK_ENGINE
1166     JSLocalStorage::RemoveStorage(instanceId_);
1167     JsiContextModule::RemoveContext(instanceId_);
1168 #endif
1169 
1170     engineInstance_->GetDelegate()->RemoveTaskObserver();
1171     engineInstance_->DestroyAllRootViewHandle();
1172     if (isUnique_) {
1173         RunFullGarbageCollection();
1174     }
1175 
1176     if (!runtime_ && nativeEngine_ != nullptr) {
1177 #if !defined(PREVIEW)
1178         nativeEngine_->CancelCheckUVLoop();
1179 #endif
1180         delete nativeEngine_;
1181         nativeEngine_ = nullptr;
1182     }
1183 }
1184 
Initialize(const RefPtr<FrontendDelegate> & delegate)1185 bool JsiDeclarativeEngine::Initialize(const RefPtr<FrontendDelegate>& delegate)
1186 {
1187     CHECK_RUN_ON(JS);
1188     ACE_SCOPED_TRACE("JsiDeclarativeEngine::Initialize");
1189     ACE_DCHECK(delegate);
1190     NG::UIContextHelper::RegisterRemoveUIContextFunc();
1191     engineInstance_ = AceType::MakeRefPtr<JsiDeclarativeEngineInstance>(delegate);
1192     auto sharedRuntime = reinterpret_cast<NativeEngine*>(runtime_);
1193     std::shared_ptr<ArkJSRuntime> arkRuntime;
1194     EcmaVM* vm = nullptr;
1195     if (sharedRuntime) {
1196         arkRuntime = std::make_shared<ArkJSRuntime>();
1197         if (isUnique_ && reinterpret_cast<NativeEngine*>(cardRuntime_) != nullptr) {
1198             sharedRuntime = reinterpret_cast<NativeEngine*>(cardRuntime_);
1199         }
1200         auto nativeArkEngine = static_cast<ArkNativeEngine*>(sharedRuntime);
1201         vm = const_cast<EcmaVM*>(nativeArkEngine->GetEcmaVm());
1202         if (vm == nullptr) {
1203             return false;
1204         }
1205         if (!arkRuntime->InitializeFromExistVM(vm)) {
1206             return false;
1207         }
1208         nativeEngine_ = nativeArkEngine;
1209         arkRuntime->SetNativeEngine(nativeArkEngine);
1210     }
1211     engineInstance_->SetInstanceId(instanceId_);
1212     engineInstance_->SetDebugMode(NeedDebugBreakPoint());
1213 #if defined(PREVIEW)
1214     engineInstance_->SetPkgNameList(pkgNameMap_);
1215     engineInstance_->SetPkgAliasList(pkgAliasMap_);
1216     engineInstance_->SetpkgContextInfoList(pkgContextInfoMap_);
1217 #endif
1218     bool result = engineInstance_->InitJsEnv(IsDebugVersion(), GetExtraNativeObject(), arkRuntime);
1219     if (!result) {
1220         return false;
1221     }
1222 
1223     auto runtime = engineInstance_->GetJsRuntime();
1224     vm = vm ? vm : const_cast<EcmaVM*>(std::static_pointer_cast<ArkJSRuntime>(runtime)->GetEcmaVm());
1225     if (vm == nullptr) {
1226         return false;
1227     }
1228 
1229     if (nativeEngine_ == nullptr) {
1230         nativeEngine_ = new ArkNativeEngine(vm, static_cast<void*>(this));
1231     }
1232     EngineTask(sharedRuntime);
1233     return result;
1234 }
1235 
EngineTask(bool sharedRuntime)1236 void JsiDeclarativeEngine::EngineTask(bool sharedRuntime)
1237 {
1238     engineInstance_->SetNativeEngine(nativeEngine_);
1239     engineInstance_->InitJsObject();
1240     if (!sharedRuntime) {
1241         SetPostTask(nativeEngine_);
1242 #if !defined(PREVIEW)
1243         nativeEngine_->CheckUVLoop();
1244 #endif
1245         RegisterWorker();
1246         engineInstance_->RegisterFaPlugin();
1247     }
1248 }
1249 
SetPostTask(NativeEngine * nativeEngine)1250 void JsiDeclarativeEngine::SetPostTask(NativeEngine* nativeEngine)
1251 {
1252     auto weakDelegate = WeakPtr(engineInstance_->GetDelegate());
1253     auto&& postTask = [weakDelegate, weakEngine = AceType::WeakClaim(this), id = instanceId_](bool needSync) {
1254         auto delegate = weakDelegate.Upgrade();
1255         if (delegate == nullptr) {
1256             return;
1257         }
1258         delegate->PostJsTask(
1259             [weakEngine, needSync, id]() {
1260                 auto jsEngine = weakEngine.Upgrade();
1261                 if (jsEngine == nullptr) {
1262                     return;
1263                 }
1264                 auto nativeEngine = jsEngine->GetNativeEngine();
1265                 if (nativeEngine == nullptr) {
1266                     return;
1267                 }
1268                 ContainerScope scope(id);
1269                 nativeEngine->Loop(LOOP_NOWAIT, needSync);
1270             },
1271             "ArkUISetNativeEngineLoop");
1272     };
1273     nativeEngine_->SetPostTask(postTask);
1274 }
1275 
RegisterInitWorkerFunc()1276 void JsiDeclarativeEngine::RegisterInitWorkerFunc()
1277 {
1278     auto weakInstance = AceType::WeakClaim(AceType::RawPtr(engineInstance_));
1279     bool debugVersion = IsDebugVersion();
1280     std::string libraryPath = "";
1281     if (debugVersion) {
1282         libraryPath = ARK_DEBUGGER_LIB_PATH;
1283     }
1284     auto&& initWorkerFunc = [weakInstance, libraryPath, debugVersion, instanceId = instanceId_](
1285                                 NativeEngine* nativeEngine) {
1286         if (nativeEngine == nullptr) {
1287             return;
1288         }
1289         auto arkNativeEngine = static_cast<ArkNativeEngine*>(nativeEngine);
1290         if (arkNativeEngine == nullptr) {
1291             return;
1292         }
1293         auto instance = weakInstance.Upgrade();
1294         if (instance == nullptr) {
1295             return;
1296         }
1297 #ifdef OHOS_PLATFORM
1298         auto tid = gettid();
1299         ConnectServerManager::Get().AddInstance(tid, "ets");
1300         auto vm = const_cast<EcmaVM*>(arkNativeEngine->GetEcmaVm());
1301         auto workerPostTask = [nativeEngine](std::function<void()>&& callback) {
1302             nativeEngine->CallDebuggerPostTaskFunc(std::move(callback));
1303         };
1304         bool debugMode = AceApplicationInfo::GetInstance().IsNeedDebugBreakPoint();
1305         panda::JSNApi::DebugOption debugOption = { libraryPath.c_str(), debugMode, -1, true }; //FA:true port:-1
1306         JSNApi::NotifyDebugMode(tid, vm, debugOption, tid, workerPostTask, debugVersion);
1307 #endif
1308         instance->InitConsoleModule(arkNativeEngine);
1309 
1310         std::vector<uint8_t> buffer((uint8_t*)_binary_jsEnumStyle_abc_start, (uint8_t*)_binary_jsEnumStyle_abc_end);
1311         arkNativeEngine->RunBufferScript(buffer);
1312     };
1313     nativeEngine_->SetInitWorkerFunc(initWorkerFunc);
1314 }
1315 
1316 #ifdef OHOS_PLATFORM
RegisterOffWorkerFunc()1317 void JsiDeclarativeEngine::RegisterOffWorkerFunc()
1318 {
1319     auto weakInstance = AceType::WeakClaim(AceType::RawPtr(engineInstance_));
1320     bool debugVersion = IsDebugVersion();
1321     auto&& offWorkerFunc = [debugVersion](NativeEngine* nativeEngine) {
1322         if (!debugVersion) {
1323             return;
1324         }
1325         if (nativeEngine == nullptr) {
1326             return;
1327         }
1328         auto arkNativeEngine = static_cast<ArkNativeEngine*>(nativeEngine);
1329         if (arkNativeEngine == nullptr) {
1330             return;
1331         }
1332         ConnectServerManager::Get().RemoveInstance(gettid());
1333         auto vm = const_cast<EcmaVM*>(arkNativeEngine->GetEcmaVm());
1334         panda::JSNApi::StopDebugger(vm);
1335     };
1336     nativeEngine_->SetOffWorkerFunc(offWorkerFunc);
1337 }
1338 #endif
1339 
RegisterAssetFunc()1340 void JsiDeclarativeEngine::RegisterAssetFunc()
1341 {
1342     auto weakDelegate = WeakPtr(engineInstance_->GetDelegate());
1343     auto&& assetFunc = [weakDelegate](const std::string& uri, uint8_t** buff, size_t* buffSize,
1344         std::vector<uint8_t>& content, std::string& ami, bool& useSecureMem, bool isRestricted) {
1345         auto delegate = weakDelegate.Upgrade();
1346         if (delegate == nullptr) {
1347             return;
1348         }
1349         size_t index = uri.find_last_of(".");
1350         if (index != std::string::npos) {
1351             delegate->GetResourceData(uri.substr(0, index) + ".abc", content, ami);
1352             useSecureMem = false;
1353         }
1354     };
1355     nativeEngine_->SetGetAssetFunc(assetFunc);
1356 }
1357 
RegisterWorker()1358 void JsiDeclarativeEngine::RegisterWorker()
1359 {
1360     RegisterInitWorkerFunc();
1361 #ifdef OHOS_PLATFORM
1362     RegisterOffWorkerFunc();
1363 #endif
1364     RegisterAssetFunc();
1365 }
1366 
ExecuteAbc(const std::string & fileName)1367 bool JsiDeclarativeEngine::ExecuteAbc(const std::string& fileName)
1368 {
1369     ACE_SCOPED_TRACE("JsiDeclarativeEngine::ExecuteAbc Execute Page code : %s", fileName.c_str());
1370     auto runtime = engineInstance_->GetJsRuntime();
1371     auto delegate = engineInstance_->GetDelegate();
1372     std::vector<uint8_t> content;
1373     if (!delegate->GetAssetContent(fileName, content)) {
1374         return true;
1375     }
1376 #if !defined(PREVIEW)
1377     const std::string abcPath = delegate->GetAssetPath(fileName).append(fileName);
1378 #else
1379     const std::string& abcPath = fileName;
1380 #endif
1381     if (!runtime->EvaluateJsCode(content.data(), content.size(), abcPath, needUpdate_)) {
1382         return false;
1383     }
1384     return true;
1385 }
1386 
ExecuteJs(const uint8_t * content,int32_t size)1387 bool JsiDeclarativeEngine::ExecuteJs(const uint8_t* content, int32_t size)
1388 {
1389     auto runtime = engineInstance_->GetJsRuntime();
1390     CHECK_NULL_RETURN(runtime, false);
1391     if (!runtime->EvaluateJsCode(content, size)) {
1392         return false;
1393     }
1394     return true;
1395 }
1396 
ExecuteCardAbc(const std::string & fileName,int64_t cardId)1397 bool JsiDeclarativeEngine::ExecuteCardAbc(const std::string& fileName, int64_t cardId)
1398 {
1399     auto runtime = engineInstance_->GetJsRuntime();
1400     CHECK_NULL_RETURN(runtime, false);
1401     auto container = Container::Current();
1402     CHECK_NULL_RETURN(container, false);
1403     CardScope cardScope(cardId);
1404     std::string abcPath;
1405     std::vector<uint8_t> content;
1406     if (container->IsFRSCardContainer()) {
1407         auto frontEnd = AceType::DynamicCast<FormFrontendDeclarative>(container->GetCardFrontend(cardId).Upgrade());
1408         CHECK_NULL_RETURN(frontEnd, false);
1409         auto delegate = frontEnd->GetDelegate();
1410         CHECK_NULL_RETURN(delegate, false);
1411         if (frontEnd->IsBundle()) {
1412             if (!delegate->GetAssetContent(fileName, content)) {
1413                 return false;
1414             }
1415             abcPath = delegate->GetAssetPath(fileName).append(fileName);
1416             if (!runtime->EvaluateJsCode(content.data(), content.size(), abcPath)) {
1417                 return false;
1418             }
1419             return true;
1420         }
1421         if (!delegate->GetAssetContent(FORM_ES_MODULE_CARD_PATH, content)) {
1422             return false;
1423         }
1424         const std::string bundleName = frontEnd->GetBundleName();
1425         std::string moduleName = frontEnd->GetModuleName();
1426 #ifdef PREVIEW
1427         const std::string assetPath = delegate->GetAssetPath(FORM_ES_MODULE_CARD_PATH).append(FORM_ES_MODULE_CARD_PATH);
1428 #else
1429         const std::string assetPath =
1430             ASSET_PATH_PREFIX + bundleName + "/" + moduleName + "/" + FORM_ES_MODULE_CARD_PATH;
1431 #endif
1432         auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
1433         CHECK_NULL_RETURN(arkRuntime, false);
1434         arkRuntime->SetBundleName(bundleName);
1435         arkRuntime->SetAssetPath(assetPath);
1436         arkRuntime->SetBundle(false);
1437         arkRuntime->SetModuleName(moduleName);
1438 #ifdef PREVIEW
1439         // remove the prefix of "ets/"
1440         abcPath = fileName.substr(PREFIX_LETTER_NUMBER);
1441 #else
1442         abcPath = moduleName.append("/").append(fileName);
1443 #endif
1444         {
1445             if (!arkRuntime->ExecuteModuleBuffer(content.data(), content.size(), abcPath, true)) {
1446                 return false;
1447             }
1448         }
1449         return true;
1450     } else {
1451         auto frontEnd = AceType::DynamicCast<CardFrontendDeclarative>(container->GetCardFrontend(cardId).Upgrade());
1452         CHECK_NULL_RETURN(frontEnd, false);
1453         auto delegate = frontEnd->GetDelegate();
1454         CHECK_NULL_RETURN(delegate, false);
1455         if (!delegate->GetAssetContent(fileName, content)) {
1456             return false;
1457         }
1458         abcPath = delegate->GetAssetPath(fileName).append(fileName);
1459     }
1460     if (!runtime->EvaluateJsCode(content.data(), content.size(), abcPath)) {
1461         return false;
1462     }
1463     return true;
1464 }
1465 
ExecuteDynamicAbc(const std::string & fileName,const std::string & entryPoint)1466 bool JsiDeclarativeEngine::ExecuteDynamicAbc(const std::string& fileName, const std::string& entryPoint)
1467 {
1468     CHECK_NULL_RETURN(runtime_, false);
1469     auto engine = reinterpret_cast<NativeEngine*>(runtime_);
1470     CHECK_NULL_RETURN(engine, false);
1471     auto vm = engine->GetEcmaVm();
1472     CHECK_NULL_RETURN(vm, false);
1473     panda::TryCatch trycatch(vm);
1474 
1475     panda::JSNApi::SetModuleInfo(const_cast<EcmaVM*>(vm), ASSET_PATH_PREFIX + fileName, entryPoint);
1476     if (trycatch.HasCaught()) {
1477         engine->lastException_ = trycatch.GetException();
1478         return false;
1479     }
1480 
1481     engine->RunScriptForAbc(fileName.c_str(), const_cast<char*>(entryPoint.c_str()));
1482     if (trycatch.HasCaught()) {
1483         engine->lastException_ = trycatch.GetException();
1484         return false;
1485     }
1486     return true;
1487 }
1488 
UpdateRootComponent()1489 bool JsiDeclarativeEngine::UpdateRootComponent()
1490 {
1491     if (!JsiDeclarativeEngine::obj_.IsEmpty()) {
1492         LOGI("update rootComponent start");
1493         LocalScope scope(obj_.GetEcmaVM());
1494         Framework::UpdateRootComponent(obj_.GetEcmaVM(), JsiDeclarativeEngine::obj_.ToLocal());
1495         // Clear the global object to avoid load this obj next time
1496         JsiDeclarativeEngine::obj_.FreeGlobalHandleAddr();
1497         JsiDeclarativeEngine::obj_.Empty();
1498         return true;
1499     }
1500     return false;
1501 }
1502 
LoadPluginComponent(const std::string & url,const RefPtr<JsAcePage> & page,bool isMainPage)1503 bool JsiDeclarativeEngine::LoadPluginComponent(const std::string &url, const RefPtr<JsAcePage>& page, bool isMainPage)
1504 {
1505     LoadJs(url, page, isMainPage);
1506     if (!UpdateRootComponent()) {
1507         auto pagePath = url;
1508         if (pagePath.rfind(".js") != std::string::npos) {
1509             pagePath = pagePath.substr(0, pagePath.length() - strlen(".js"));
1510         }
1511         std::string pluginUrlName = OHMURL_START_TAG + pluginBundleName_ + "/" + pluginModuleName_ + "/ets/" + pagePath;
1512         return LoadNamedRouterSource(pluginUrlName, false);
1513     }
1514     return true;
1515 }
1516 
LoadJs(const std::string & url,const RefPtr<JsAcePage> & page,bool isMainPage)1517 void JsiDeclarativeEngine::LoadJs(const std::string& url, const RefPtr<JsAcePage>& page, bool isMainPage)
1518 {
1519     ACE_SCOPED_TRACE("JsiDeclarativeEngine::LoadJs url : %s", url.c_str());
1520     LOGI("LoadJs page:%{public}d", page->GetPageId());
1521     ACE_DCHECK(engineInstance_);
1522     engineInstance_->SetStagingPage(page);
1523     if (isMainPage) {
1524         ACE_DCHECK(!engineInstance_->GetRunningPage());
1525         engineInstance_->SetRunningPage(page);
1526     }
1527     auto runtime = engineInstance_->GetJsRuntime();
1528     auto delegate = engineInstance_->GetDelegate();
1529     auto vm = const_cast<EcmaVM*>(std::static_pointer_cast<ArkJSRuntime>(runtime)->GetEcmaVm());
1530     // get source map
1531     std::string jsSourceMap;
1532     if (JSNApi::IsBundle(vm)) {
1533         if (delegate->GetAssetContent(url + ".map", jsSourceMap)) {
1534             page->SetPageMap(jsSourceMap);
1535         }
1536     }
1537     // get js bundle content
1538     shared_ptr<JsValue> jsCode = runtime->NewUndefined();
1539     shared_ptr<JsValue> jsAppCode = runtime->NewUndefined();
1540     const char js_ext[] = ".js";
1541     const char bin_ext[] = ".abc";
1542     auto pos = url.rfind(js_ext);
1543     if (pos != std::string::npos && pos == url.length() - (sizeof(js_ext) - 1)) {
1544         std::string urlName = url.substr(0, pos) + bin_ext;
1545 #if !defined(PREVIEW)
1546         if (IsModule()) {
1547             if (!engineInstance_->IsPlugin()) {
1548                 LoadJsWithModule(urlName);
1549                 return;
1550             }
1551             if (!pluginModuleName_.empty()) {
1552                 LoadPluginJsWithModule(urlName);
1553                 return;
1554             }
1555         }
1556 #endif
1557         if (isMainPage) {
1558             if (!ExecuteAbc("commons.abc")) {
1559                 return;
1560             }
1561             if (!ExecuteAbc("vendors.abc")) {
1562                 return;
1563             }
1564             std::string appMap;
1565             if (delegate->GetAssetContent("app.js.map", appMap)) {
1566                 page->SetAppMap(appMap);
1567             }
1568             if (ExecuteAbc("app.abc")) {
1569                 CallAppFunc("onCreate");
1570             }
1571         }
1572 #if !defined(PREVIEW)
1573         if (!ExecuteAbc(urlName)) {
1574             return;
1575         }
1576 #else
1577         if (!assetPath_.empty() && !isBundle_) {
1578             auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
1579             arkRuntime->SetBundleName(bundleName_);
1580             arkRuntime->SetAssetPath(assetPath_);
1581             arkRuntime->SetBundle(isBundle_);
1582             arkRuntime->SetModuleName(moduleName_);
1583             std::vector<uint8_t> content;
1584             if (!delegate->GetAssetContent("modules.abc", content)) {
1585                 LOGW("GetAssetContent \"%{public}s\" failed.", urlName.c_str());
1586                 return;
1587             }
1588             if (!arkRuntime->ExecuteModuleBuffer(content.data(), content.size(), urlName)) {
1589                 LOGW("EvaluateJsCode \"%{public}s\" failed.", urlName.c_str());
1590                 return;
1591             }
1592         } else {
1593             ExecuteAbc(urlName);
1594         }
1595 #endif
1596     }
1597 }
1598 #if !defined(PREVIEW)
IsModule()1599 bool JsiDeclarativeEngine::IsModule()
1600 {
1601     auto container = Container::Current();
1602     CHECK_NULL_RETURN(container, false);
1603     return container->IsModule();
1604 }
1605 
LoadPluginJsWithModule(std::string & urlName)1606 void JsiDeclarativeEngine::LoadPluginJsWithModule(std::string& urlName)
1607 {
1608     auto runtime = std::static_pointer_cast<ArkJSRuntime>(engineInstance_->GetJsRuntime());
1609     auto delegate = engineInstance_->GetDelegate();
1610     auto pluginUrlName = OHMURL_START_TAG + pluginBundleName_ + "/" + pluginModuleName_ + "/ets/" + urlName;
1611     std::vector<uint8_t> content;
1612     if (!delegate->GetAssetContent("ets/modules.abc", content)) {
1613         return;
1614     }
1615     if (!runtime->ExecuteModuleBuffer(content.data(), content.size(), pluginUrlName, true)) {
1616         return;
1617     }
1618 }
1619 
LoadJsWithModule(std::string & urlName,const std::function<void (const std::string &,int32_t)> & errorCallback)1620 void JsiDeclarativeEngine::LoadJsWithModule(
1621     std::string& urlName, const std::function<void(const std::string&, int32_t)>& errorCallback)
1622 {
1623     ACE_SCOPED_TRACE("JsiDeclarativeEngine::LoadJsWithModule Execute Page code : %s", urlName.c_str());
1624     auto container = Container::Current();
1625     CHECK_NULL_VOID(container);
1626     auto runtime = std::static_pointer_cast<ArkJSRuntime>(engineInstance_->GetJsRuntime());
1627     const std::string moduleName = container->GetModuleName();
1628     const std::string assetPath = ASSET_PATH_PREFIX + moduleName + "/" + FORM_ES_MODULE_PATH;
1629     runtime->SetAssetPath(assetPath);
1630     runtime->SetModuleName(moduleName);
1631     if (urlName.substr(0, strlen(BUNDLE_TAG)) != BUNDLE_TAG) {
1632         urlName = container->GetModuleName() + "/ets/" + urlName;
1633     }
1634     runtime->ExecuteJsBin(urlName, errorCallback);
1635 }
1636 #endif
1637 // Load the app.js file of the FA model in NG structure.
LoadFaAppSource()1638 bool JsiDeclarativeEngine::LoadFaAppSource()
1639 {
1640     ACE_SCOPED_TRACE("JsiDeclarativeEngine::LoadFaAppSource");
1641     if (!ExecuteAbc("commons.abc") || !ExecuteAbc("vendors.abc") || !ExecuteAbc("app.abc")) {
1642         return false;
1643     }
1644     CallAppFunc("onCreate");
1645     return true;
1646 }
1647 
1648 // Load the js file of the page in NG structure..
LoadPageSource(const std::string & url,const std::function<void (const std::string &,int32_t)> & errorCallback)1649 bool JsiDeclarativeEngine::LoadPageSource(
1650     const std::string& url, const std::function<void(const std::string&, int32_t)>& errorCallback)
1651 {
1652     ACE_SCOPED_TRACE("JsiDeclarativeEngine::LoadPageSource");
1653     ACE_DCHECK(engineInstance_);
1654     // get js bundle content
1655     const char jsExt[] = ".js";
1656     const char binExt[] = ".abc";
1657     std::optional<std::string> urlName;
1658     auto pos = url.rfind(jsExt);
1659     if (pos != std::string::npos && pos == url.length() - (sizeof(jsExt) - 1)) {
1660         urlName = url.substr(0, pos) + binExt;
1661     }
1662     if (!urlName.has_value()) {
1663         return false;
1664     }
1665 
1666 #if !defined(PREVIEW)
1667     if (IsModule()) {
1668         LoadJsWithModule(urlName.value(), errorCallback);
1669         return true;
1670     }
1671 #else
1672     auto runtime = engineInstance_->GetJsRuntime();
1673     auto delegate = engineInstance_->GetDelegate();
1674     if (!assetPath_.empty() && !isBundle_) {
1675         auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
1676         arkRuntime->SetBundleName(bundleName_);
1677         arkRuntime->SetAssetPath(assetPath_);
1678         arkRuntime->SetBundle(isBundle_);
1679         arkRuntime->SetModuleName(moduleName_);
1680         std::vector<uint8_t> content;
1681         if (!delegate->GetAssetContent("modules.abc", content)) {
1682             return false;
1683         }
1684         if (!arkRuntime->ExecuteModuleBuffer(content.data(), content.size(), urlName.value())) {
1685             return false;
1686         }
1687         return true;
1688     }
1689 #endif
1690     return ExecuteAbc(urlName.value());
1691 }
1692 
LoadPageSource(const std::shared_ptr<std::vector<uint8_t>> & content,const std::function<void (const std::string &,int32_t)> & errorCallback,const std::string & contentName)1693 bool JsiDeclarativeEngine::LoadPageSource(
1694     const std::shared_ptr<std::vector<uint8_t>>& content,
1695     const std::function<void(const std::string&, int32_t)>& errorCallback,
1696     const std::string& contentName)
1697 {
1698     ACE_SCOPED_TRACE("JsiDeclarativeEngine::LoadPageSource");
1699     LOGI("LoadJs by buffer");
1700     ACE_DCHECK(engineInstance_);
1701     auto container = Container::Current();
1702     CHECK_NULL_RETURN(container, false);
1703     auto runtime = engineInstance_->GetJsRuntime();
1704     auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
1705     if (!arkRuntime->EvaluateJsCode(content->data(), content->size(), contentName)) {
1706         return false;
1707     }
1708     return true;
1709 }
1710 
LoadNavDestinationSource(const std::string & bundleName,const std::string & moduleName,const std::string & pageSourceFile,bool isSingleton)1711 int32_t JsiDeclarativeEngine::LoadNavDestinationSource(const std::string& bundleName,
1712     const std::string& moduleName, const std::string& pageSourceFile, bool isSingleton)
1713 {
1714     auto runtime = engineInstance_->GetJsRuntime();
1715     CHECK_NULL_RETURN(runtime, false);
1716     auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
1717     return arkRuntime->LoadDestinationFile(bundleName, moduleName, pageSourceFile, isSingleton);
1718 }
1719 
AddToNamedRouterMap(const EcmaVM * vm,panda::Global<panda::FunctionRef> pageGenerator,const std::string & namedRoute,panda::Local<panda::ObjectRef> params)1720 void JsiDeclarativeEngine::AddToNamedRouterMap(const EcmaVM* vm, panda::Global<panda::FunctionRef> pageGenerator,
1721     const std::string& namedRoute, panda::Local<panda::ObjectRef> params)
1722 {
1723     std::string bundleName;
1724     std::string moduleName;
1725     std::string pagePath;
1726     std::string pageFullPath;
1727     std::string ohmUrl;
1728     if (!ParseNamedRouterParams(vm, params, bundleName, moduleName, pagePath, pageFullPath, ohmUrl)) {
1729         return;
1730     }
1731 
1732     TAG_LOGI(AceLogTag::ACE_ROUTER,
1733         "add named router record, name: %{public}s, bundleName: %{public}s, moduleName: %{public}s, "
1734         "pagePath: %{public}s, pageFullPath: %{public}s, ohmUrl: %{public}s",
1735         namedRoute.c_str(), bundleName.c_str(), moduleName.c_str(), pagePath.c_str(), pageFullPath.c_str(),
1736         ohmUrl.c_str());
1737     NamedRouterProperty namedRouterProperty({ pageGenerator, bundleName, moduleName, pagePath, ohmUrl });
1738     auto ret = namedRouterRegisterMap_.insert(std::make_pair(namedRoute, namedRouterProperty));
1739     if (!ret.second) {
1740         ret.first->second.pageGenerator.FreeGlobalHandleAddr();
1741         namedRouterRegisterMap_[namedRoute] = namedRouterProperty;
1742     }
1743     auto pagePathKey = moduleName + pagePath;
1744     auto pageRet = routerPathInfoMap_.insert(std::make_pair(pagePathKey, pageFullPath));
1745     if (!pageRet.second) {
1746         routerPathInfoMap_[pagePathKey] = pageFullPath;
1747     }
1748     if (!namedRoute.empty()) {
1749         auto ret = routerPathInfoMap_.insert(std::make_pair(namedRoute, pageFullPath));
1750         if (!ret.second) {
1751             routerPathInfoMap_[namedRoute] = pageFullPath;
1752         }
1753     }
1754 }
1755 
SearchRouterRegisterMap(const std::string & pageName)1756 std::string JsiDeclarativeEngine::SearchRouterRegisterMap(const std::string& pageName)
1757 {
1758     auto it = namedRouterRegisterMap_.find(pageName);
1759     if (it != namedRouterRegisterMap_.end()) {
1760         return it->second.moduleName;
1761     }
1762     return "";
1763 }
1764 
LoadNamedRouterSource(const std::string & namedRoute,bool isTriggeredByJs)1765 bool JsiDeclarativeEngine::LoadNamedRouterSource(const std::string& namedRoute, bool isTriggeredByJs)
1766 {
1767     CHECK_NULL_RETURN(!namedRouterRegisterMap_.empty(), false);
1768     auto iter = namedRouterRegisterMap_.find(namedRoute);
1769     if (isTriggeredByJs && iter == namedRouterRegisterMap_.end()) {
1770         LOGW("named route %{public}s not found!", namedRoute.c_str());
1771         return false;
1772     }
1773     // if this triggering is not from js named router api,
1774     // 'namedRoute' will be used as url to find the page in 'main_pages.json'
1775     if (!isTriggeredByJs) {
1776         std::string bundleName;
1777         std::string moduleName;
1778         std::string url = namedRoute;
1779 #if !defined(PREVIEW)
1780         if (namedRoute.substr(0, strlen(BUNDLE_TAG)) == BUNDLE_TAG) {
1781             size_t bundleEndPos = namedRoute.find('/');
1782             bundleName = namedRoute.substr(strlen(BUNDLE_TAG), bundleEndPos - strlen(BUNDLE_TAG));
1783             size_t moduleStartPos = bundleEndPos + 1;
1784             size_t moduleEndPos = namedRoute.find('/', moduleStartPos);
1785             moduleName = namedRoute.substr(moduleStartPos, moduleEndPos - moduleStartPos);
1786             url = namedRoute.substr(moduleEndPos + strlen("/ets/"));
1787         } else {
1788             bundleName = AceApplicationInfo::GetInstance().GetPackageName();
1789             auto container = Container::Current();
1790             CHECK_NULL_RETURN(container, false);
1791             moduleName = container->GetModuleName();
1792         }
1793 #else
1794         bundleName = bundleName_;
1795         moduleName = moduleName_;
1796 #endif
1797         // when need to locate page in main_pages.json, url shouldn't be empty
1798         if (url == "") {
1799             LOGW("page not found! bundleName: %{public}s, moduleName: %{public}s, url: %{public}s",
1800                 bundleName.c_str(), moduleName.c_str(), url.c_str());
1801             return false;
1802         }
1803         iter = std::find_if(namedRouterRegisterMap_.begin(), namedRouterRegisterMap_.end(),
1804             [&bundleName, &moduleName, &url](const auto& item) {
1805                 return item.second.bundleName == bundleName && item.second.moduleName == moduleName &&
1806                        item.second.pagePath == url;
1807             });
1808         if (iter == namedRouterRegisterMap_.end()) {
1809             LOGW("page not found! bundleName: %{public}s, moduleName: %{public}s, url: %{public}s",
1810                 bundleName.c_str(), moduleName.c_str(), url.c_str());
1811             return false;
1812         }
1813     }
1814 
1815     /**
1816      * The pageGenerator may be filled in two situations: one is when the developer explicitly imports it(
1817      * dynamic import in ets, eg: import("hsp"); ), and the other is when the PageRouterManager preload namedRoute
1818      * in Backup&Restore scenario.
1819      */
1820     if (iter->second.pageGenerator.IsEmpty()) {
1821         LOGE("Named router %{public}s has no PageGenerator", iter->first.c_str());
1822         return false;
1823     }
1824 
1825     CHECK_NULL_RETURN(engineInstance_, false);
1826     auto runtime = engineInstance_->GetJsRuntime();
1827     auto vm = const_cast<EcmaVM*>(std::static_pointer_cast<ArkJSRuntime>(runtime)->GetEcmaVm());
1828     std::vector<Local<JSValueRef>> argv;
1829     LocalScope scope(vm);
1830     JSViewStackProcessor::JsStartGetAccessRecordingFor(JSViewStackProcessor::JsAllocateNewElmetIdForNextComponent());
1831     auto ret = iter->second.pageGenerator->Call(vm, JSNApi::GetGlobalObject(vm), argv.data(), 0);
1832     if (!ret->IsObject(vm)) {
1833         return false;
1834     }
1835 #if defined(PREVIEW)
1836     panda::Global<panda::ObjectRef> rootView(vm, ret->ToObject(vm));
1837     shared_ptr<ArkJSRuntime> arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
1838     arkRuntime->AddRootView(rootView);
1839 #endif
1840     Framework::UpdateRootComponent(vm, ret->ToObject(vm));
1841     JSViewStackProcessor::JsStopGetAccessRecording();
1842     return true;
1843 }
1844 
GetFullPathInfo()1845 std::unique_ptr<JsonValue> JsiDeclarativeEngine::GetFullPathInfo()
1846 {
1847     auto jsonFullPathInfo = JsonUtil::CreateArray(true);
1848     auto recordIter = routerPathInfoMap_.begin();
1849     while (recordIter != routerPathInfoMap_.end()) {
1850         auto jsonItem = JsonUtil::Create(true);
1851         jsonItem->Put("url", recordIter->first.c_str());
1852         jsonItem->Put("fullPathInfo", recordIter->second.c_str());
1853         jsonFullPathInfo->Put(jsonItem);
1854         ++recordIter;
1855     }
1856     return jsonFullPathInfo;
1857 }
1858 
RestoreFullPathInfo(std::unique_ptr<JsonValue> fullPathInfo)1859 void JsiDeclarativeEngine::RestoreFullPathInfo(std::unique_ptr<JsonValue> fullPathInfo)
1860 {
1861     std::unordered_map<std::string, std::string> routerPathInfoMap;
1862     if (!fullPathInfo || !fullPathInfo->IsValid() || !fullPathInfo->IsArray()) {
1863         LOGW("Invalid fullPathInfo");
1864         return;
1865     }
1866 
1867     NamedRouterProperty property;
1868     int32_t size = fullPathInfo->GetArraySize();
1869     for (int32_t i = 0; i < size; ++i) {
1870         auto item = fullPathInfo->GetArrayItem(i);
1871         if (!item) {
1872             LOGW("failed to get fullPathInfo item");
1873             continue;
1874         }
1875         auto urlJsonValue = item->GetValue("url");
1876         auto fullPathInfoJsonValue = item->GetValue("fullPathInfo");
1877         if (!urlJsonValue || !urlJsonValue->IsString() ||
1878             !fullPathInfoJsonValue || !fullPathInfoJsonValue->IsString()) {
1879             LOGW("Invalid fullPathInfo item");
1880             continue;
1881         }
1882 
1883         std::string url = urlJsonValue->GetString();
1884         std::string pathInfo = fullPathInfoJsonValue->GetString();
1885         routerPathInfoMap.emplace(url, pathInfo);
1886     }
1887 
1888     std::swap(routerPathInfoMap_, routerPathInfoMap);
1889 }
1890 
GetNamedRouterInfo()1891 std::unique_ptr<JsonValue> JsiDeclarativeEngine::GetNamedRouterInfo()
1892 {
1893     auto jsonNamedRouterInfo = JsonUtil::CreateArray(true);
1894     auto recordIter = namedRouterRegisterMap_.begin();
1895     while (recordIter != namedRouterRegisterMap_.end()) {
1896         auto jsonItem = JsonUtil::Create(true);
1897         jsonItem->Put("name", recordIter->first.c_str());
1898         const auto& property = recordIter->second;
1899         jsonItem->Put("bundleName", property.bundleName.c_str());
1900         jsonItem->Put("moduleName", property.moduleName.c_str());
1901         jsonItem->Put("pagePath", property.pagePath.c_str());
1902         jsonItem->Put("ohmUrl", property.ohmUrl.c_str());
1903         jsonNamedRouterInfo->Put(jsonItem);
1904         ++recordIter;
1905     }
1906     return jsonNamedRouterInfo;
1907 }
1908 
RestoreNamedRouterInfo(std::unique_ptr<JsonValue> namedRouterInfo)1909 void JsiDeclarativeEngine::RestoreNamedRouterInfo(std::unique_ptr<JsonValue> namedRouterInfo)
1910 {
1911     std::unordered_map<std::string, NamedRouterProperty> namedRouterMap;
1912     if (!namedRouterInfo || !namedRouterInfo->IsValid() || !namedRouterInfo->IsArray()) {
1913         LOGW("Invalid namedRouterInfo");
1914         return;
1915     }
1916 
1917     NamedRouterProperty property;
1918     int32_t size = namedRouterInfo->GetArraySize();
1919     for (int32_t i = 0; i < size; ++i) {
1920         auto item = namedRouterInfo->GetArrayItem(i);
1921         if (!item) {
1922             LOGW("failed to get namedRouterInfo item");
1923             continue;
1924         }
1925         auto nameJsonValue = item->GetValue("name");
1926         auto bundleNameJsonValue = item->GetValue("bundleName");
1927         auto moduleNameJsonValue = item->GetValue("moduleName");
1928         auto pagePathJsonValue = item->GetValue("pagePath");
1929         auto ohmUrlJsonValue = item->GetValue("ohmUrl");
1930         if (!nameJsonValue || !nameJsonValue->IsString() ||
1931             !bundleNameJsonValue || !bundleNameJsonValue->IsString() ||
1932             !moduleNameJsonValue || !moduleNameJsonValue->IsString() ||
1933             !pagePathJsonValue || !pagePathJsonValue->IsString() ||
1934             !ohmUrlJsonValue || !ohmUrlJsonValue->IsString()) {
1935             LOGW("Invalid NamedRouterInfo item");
1936             continue;
1937         }
1938 
1939         std::string name = nameJsonValue->GetString();
1940         property.bundleName = bundleNameJsonValue->GetString();
1941         property.moduleName = moduleNameJsonValue->GetString();
1942         property.pagePath = pagePathJsonValue->GetString();
1943         property.ohmUrl = ohmUrlJsonValue->GetString();
1944         namedRouterMap.emplace(name, property);
1945     }
1946 
1947     std::swap(namedRouterRegisterMap_, namedRouterMap);
1948 }
1949 
IsNamedRouterNeedPreload(const std::string & name)1950 bool JsiDeclarativeEngine::IsNamedRouterNeedPreload(const std::string& name)
1951 {
1952     auto it = namedRouterRegisterMap_.find(name);
1953     if (it == namedRouterRegisterMap_.end()) {
1954         return false;
1955     }
1956     return it->second.pageGenerator.IsEmpty();
1957 }
1958 
PreloadNamedRouter(const std::string & name,std::function<void (bool)> && loadFinishCallback)1959 void JsiDeclarativeEngine::PreloadNamedRouter(const std::string& name, std::function<void(bool)>&& loadFinishCallback)
1960 {
1961     if (!pageUrlCheckFunc_) {
1962         LOGW("JSEngine didn't set PageUrlCheckFunc");
1963         if (loadFinishCallback) {
1964             loadFinishCallback(false);
1965         }
1966         return;
1967     }
1968     auto it = namedRouterRegisterMap_.find(name);
1969     if (it == namedRouterRegisterMap_.end() || !it->second.pageGenerator.IsEmpty()) {
1970         if (loadFinishCallback) {
1971             loadFinishCallback(true);
1972         }
1973         return;
1974     }
1975     const auto& bundleName = it->second.bundleName;
1976     const auto& moduleName = it->second.moduleName;
1977     const auto& pagePath = it->second.pagePath;
1978     std::string ohmUrl = it->second.ohmUrl + ".js";
1979     TAG_LOGI(AceLogTag::ACE_ROUTER, "preload named rotuer, bundleName:"
1980         "%{public}s, moduleName: %{public}s, pagePath: %{public}s, ohmUrl: %{public}s",
1981         bundleName.c_str(), moduleName.c_str(), pagePath.c_str(), ohmUrl.c_str());
1982 
1983     auto callback = [weak = AceType::WeakClaim(this), ohmUrl, finishCallback = loadFinishCallback]() {
1984         auto jsEngine = weak.Upgrade();
1985         CHECK_NULL_VOID(jsEngine);
1986         bool loadSuccess = true;
1987         jsEngine->LoadPageSource(ohmUrl, [ohmUrl, &loadSuccess](const std::string& errorMsg, int32_t errorCode) {
1988             TAG_LOGW(AceLogTag::ACE_ROUTER,
1989                 "Failed to load page source: %{public}s, errorCode: %{public}d, errorMsg: %{public}s", ohmUrl.c_str(),
1990                 errorCode, errorMsg.c_str());
1991             loadSuccess = false;
1992         });
1993         if (finishCallback) {
1994             finishCallback(loadSuccess);
1995         }
1996     };
1997     auto silentInstallErrorCallBack = [finishCallback = loadFinishCallback](
1998                                           int32_t errorCode, const std::string& errorMsg) {
1999         TAG_LOGW(AceLogTag::ACE_ROUTER, "Failed to preload named router, error = %{public}d, errorMsg = %{public}s",
2000             errorCode, errorMsg.c_str());
2001         if (finishCallback) {
2002             finishCallback(false);
2003         }
2004     };
2005     pageUrlCheckFunc_(ohmUrl, callback, silentInstallErrorCallBack);
2006 }
2007 
LoadCard(const std::string & url,int64_t cardId,const std::string & entryPoint)2008 bool JsiDeclarativeEngine::LoadCard(const std::string& url, int64_t cardId, const std::string& entryPoint)
2009 {
2010     ACE_SCOPED_TRACE("JsiDeclarativeEngine::LoadCard");
2011     auto container = Container::Current();
2012     CHECK_NULL_RETURN(container, false);
2013     return container->IsDynamicRender() ? ExecuteDynamicAbc(url, entryPoint) : ExecuteCardAbc(url, cardId);
2014 }
2015 
2016 #if defined(PREVIEW)
ReplaceJSContent(const std::string & url,const std::string componentName)2017 void JsiDeclarativeEngine::ReplaceJSContent(const std::string& url, const std::string componentName)
2018 {
2019     ACE_DCHECK(engineInstance_);
2020     if (engineInstance_ == nullptr) {
2021         return;
2022     }
2023     auto runtime = engineInstance_->GetJsRuntime();
2024     std::static_pointer_cast<ArkJSRuntime>(runtime)->SetPreviewFlag(true);
2025     std::static_pointer_cast<ArkJSRuntime>(runtime)->SetRequiredComponent(componentName);
2026     engineInstance_->GetDelegate()->Replace(url, "");
2027 }
2028 
GetNewComponentWithJsCode(const std::string & jsCode,const std::string & viewID)2029 RefPtr<Component> JsiDeclarativeEngine::GetNewComponentWithJsCode(const std::string& jsCode, const std::string& viewID)
2030 {
2031     std::string dest;
2032     if (!Base64Util::Decode(jsCode, dest)) {
2033         return nullptr;
2034     }
2035 
2036     ViewStackProcessor::GetInstance()->ClearStack();
2037     ViewStackProcessor::GetInstance()->PushKey(viewID);
2038     bool result = engineInstance_->InitAceModule((uint8_t*)dest.data(), dest.size());
2039     ViewStackProcessor::GetInstance()->PopKey();
2040     if (!result) {
2041         return nullptr;
2042     }
2043     auto component = ViewStackProcessor::GetInstance()->GetNewComponent();
2044     return component;
2045 }
2046 
ExecuteJsForFastPreview(const std::string & jsCode,const std::string & viewID)2047 bool JsiDeclarativeEngine::ExecuteJsForFastPreview(const std::string& jsCode, const std::string& viewID)
2048 {
2049     std::string dest;
2050     if (!Base64Util::Decode(jsCode, dest)) {
2051         return false;
2052     }
2053     NG::ViewStackProcessor::GetInstance()->ClearStack();
2054     NG::ViewStackProcessor::GetInstance()->PushKey(viewID);
2055     bool result = engineInstance_->InitAceModule((uint8_t*)dest.data(), dest.size());
2056     NG::ViewStackProcessor::GetInstance()->PopKey();
2057     return result;
2058 }
2059 
SetHspBufferTrackerCallback(std::function<bool (const std::string &,uint8_t **,size_t *,std::string &)> && callback)2060 void JsiDeclarativeEngine::SetHspBufferTrackerCallback(
2061     std::function<bool(const std::string&, uint8_t**, size_t*, std::string&)>&& callback)
2062 {
2063     CHECK_NULL_VOID(engineInstance_);
2064     auto runtime = std::static_pointer_cast<ArkJSRuntime>(engineInstance_->GetJsRuntime());
2065     CHECK_NULL_VOID(runtime);
2066     auto vm = const_cast<EcmaVM*>(runtime->GetEcmaVm());
2067     panda::JSNApi::SetHostResolveBufferTracker(vm, std::move(callback));
2068 }
2069 
SetMockModuleList(const std::map<std::string,std::string> & mockJsonInfo)2070 void JsiDeclarativeEngine::SetMockModuleList(const std::map<std::string, std::string>& mockJsonInfo)
2071 {
2072     CHECK_NULL_VOID(engineInstance_);
2073     auto runtime = std::static_pointer_cast<ArkJSRuntime>(engineInstance_->GetJsRuntime());
2074     CHECK_NULL_VOID(runtime);
2075     auto vm = const_cast<EcmaVM*>(runtime->GetEcmaVm());
2076     panda::JSNApi::SetMockModuleList(vm, mockJsonInfo);
2077 }
2078 
IsComponentPreview()2079 bool JsiDeclarativeEngine::IsComponentPreview()
2080 {
2081     auto runtime = engineInstance_->GetJsRuntime();
2082     CHECK_NULL_RETURN(runtime, false);
2083     shared_ptr<ArkJSRuntime> arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
2084     CHECK_NULL_RETURN(arkRuntime, false);
2085     return arkRuntime->GetPreviewFlag();
2086 }
2087 #endif
2088 
UpdateRunningPage(const RefPtr<JsAcePage> & page)2089 void JsiDeclarativeEngine::UpdateRunningPage(const RefPtr<JsAcePage>& page)
2090 {
2091     ACE_DCHECK(engineInstance_);
2092     engineInstance_->SetRunningPage(page);
2093 }
2094 
UpdateStagingPage(const RefPtr<JsAcePage> & page)2095 void JsiDeclarativeEngine::UpdateStagingPage(const RefPtr<JsAcePage>& page)
2096 {
2097     ACE_DCHECK(engineInstance_);
2098     engineInstance_->SetStagingPage(page);
2099 }
2100 
ResetStagingPage()2101 void JsiDeclarativeEngine::ResetStagingPage()
2102 {
2103     ACE_DCHECK(engineInstance_);
2104     auto runningPage = engineInstance_->GetRunningPage();
2105     engineInstance_->ResetStagingPage(runningPage);
2106 }
2107 
SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher> & dispatcher)2108 void JsiDeclarativeEngine::SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher>& dispatcher)
2109 {
2110     ACE_DCHECK(engineInstance_);
2111     engineInstance_->SetJsMessageDispatcher(dispatcher);
2112 }
2113 
FireAsyncEvent(const std::string & eventId,const std::string & param)2114 void JsiDeclarativeEngine::FireAsyncEvent(const std::string& eventId, const std::string& param)
2115 {
2116     std::string callBuf = std::string("[{\"args\": [\"")
2117                               .append(eventId)
2118                               .append("\",")
2119                               .append(param)
2120                               .append("], \"method\":\"fireEvent\"}]");
2121 
2122     ACE_DCHECK(engineInstance_);
2123     engineInstance_->FireJsEvent(callBuf.c_str());
2124 }
2125 
FireSyncEvent(const std::string & eventId,const std::string & param)2126 void JsiDeclarativeEngine::FireSyncEvent(const std::string& eventId, const std::string& param)
2127 {
2128     std::string callBuf = std::string("[{\"args\": [\"")
2129                               .append(eventId)
2130                               .append("\",")
2131                               .append(param)
2132                               .append("], \"method\":\"fireEventSync\"}]");
2133 
2134     ACE_DCHECK(engineInstance_);
2135     engineInstance_->FireJsEvent(callBuf.c_str());
2136 }
2137 
InitXComponent(const std::string & componentId)2138 void JsiDeclarativeEngine::InitXComponent(const std::string& componentId)
2139 {
2140     ACE_DCHECK(engineInstance_);
2141     std::tie(nativeXComponentImpl_, nativeXComponent_) =
2142         XComponentClient::GetInstance().GetNativeXComponentFromXcomponentsMap(componentId);
2143 }
2144 
FireExternalEvent(const std::string & componentId,const uint32_t nodeId,const bool isDestroy)2145 void JsiDeclarativeEngine::FireExternalEvent(
2146     const std::string& componentId, const uint32_t nodeId, const bool isDestroy)
2147 {
2148     CHECK_RUN_ON(JS);
2149 
2150     if (Container::IsCurrentUseNewPipeline()) {
2151         ACE_DCHECK(engineInstance_);
2152         auto xcFrameNode = NG::FrameNode::GetFrameNode(V2::XCOMPONENT_ETS_TAG, static_cast<int32_t>(nodeId));
2153         if (!xcFrameNode) {
2154             return;
2155         }
2156         auto xcPattern = DynamicCast<NG::XComponentPattern>(xcFrameNode->GetPattern());
2157         CHECK_NULL_VOID(xcPattern);
2158         CHECK_EQUAL_VOID(xcPattern->GetLibraryName().has_value(), false);
2159         std::weak_ptr<OH_NativeXComponent> weakNativeXComponent;
2160         RefPtr<OHOS::Ace::NativeXComponentImpl> nativeXComponentImpl = nullptr;
2161         std::tie(nativeXComponentImpl, weakNativeXComponent) = xcPattern->GetNativeXComponent();
2162         auto nativeXComponent = weakNativeXComponent.lock();
2163         CHECK_NULL_VOID(nativeXComponent);
2164         CHECK_NULL_VOID(nativeXComponentImpl);
2165 
2166         nativeXComponentImpl->SetXComponentId(componentId);
2167 
2168 #ifdef XCOMPONENT_SUPPORTED
2169         xcPattern->SetExpectedRateRangeInit();
2170         xcPattern->OnFrameEventInit();
2171         xcPattern->UnregisterOnFrameEventInit();
2172 #endif
2173         auto* arkNativeEngine = static_cast<ArkNativeEngine*>(nativeEngine_);
2174         if (arkNativeEngine == nullptr) {
2175             return;
2176         }
2177 
2178         napi_handle_scope handleScope;
2179         napi_status status = napi_open_handle_scope(reinterpret_cast<napi_env>(nativeEngine_), &handleScope);
2180         if (status != napi_ok) {
2181             return;
2182         }
2183         std::string arguments;
2184         auto soPath = xcPattern->GetSoPath().value_or("");
2185         auto runtime = engineInstance_->GetJsRuntime();
2186         shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
2187         LocalScope scope(pandaRuntime->GetEcmaVm());
2188         auto objXComp = arkNativeEngine->LoadModuleByName(xcPattern->GetLibraryName().value(), true, arguments,
2189             OH_NATIVE_XCOMPONENT_OBJ, reinterpret_cast<void*>(nativeXComponent.get()), soPath);
2190         if (objXComp.IsEmpty() || pandaRuntime->HasPendingException()) {
2191             return;
2192         }
2193 
2194         auto objContext = JsiObject(objXComp);
2195         JSRef<JSObject> obj = JSRef<JSObject>::Make(objContext);
2196         OHOS::Ace::Framework::XComponentClient::GetInstance().AddJsValToJsValMap(componentId, obj);
2197         napi_close_handle_scope(reinterpret_cast<napi_env>(nativeEngine_), handleScope);
2198 
2199         auto type = xcPattern->GetType();
2200         if (type == XComponentType::SURFACE || type == XComponentType::TEXTURE) {
2201             auto task = [weak = WeakClaim(this), weakPattern = AceType::WeakClaim(AceType::RawPtr(xcPattern))]() {
2202                 auto pattern = weakPattern.Upgrade();
2203                 if (!pattern) {
2204                     return;
2205                 }
2206                 auto bridge = weak.Upgrade();
2207                 if (bridge) {
2208 #ifdef XCOMPONENT_SUPPORTED
2209                     pattern->NativeXComponentInit();
2210 #endif
2211                 }
2212             };
2213 
2214             auto delegate = engineInstance_->GetDelegate();
2215             if (!delegate) {
2216                 return;
2217             }
2218             delegate->PostSyncTaskToPage(task, "ArkUINativeXComponentInit");
2219         }
2220         return;
2221     }
2222 #ifndef NG_BUILD
2223     if (isDestroy) {
2224         XComponentComponentClient::GetInstance().DeleteFromXcomponentsMapById(componentId);
2225         XComponentClient::GetInstance().DeleteControllerFromJSXComponentControllersMap(componentId);
2226         XComponentClient::GetInstance().DeleteFromNativeXcomponentsMapById(componentId);
2227         XComponentClient::GetInstance().DeleteFromJsValMapById(componentId);
2228         return;
2229     }
2230     InitXComponent(componentId);
2231     RefPtr<XComponentComponent> xcomponent =
2232         XComponentComponentClient::GetInstance().GetXComponentFromXcomponentsMap(componentId);
2233     if (!xcomponent) {
2234         return;
2235     }
2236 
2237     void* nativeWindow = nullptr;
2238 #ifdef OHOS_STANDARD_SYSTEM
2239     nativeWindow = const_cast<void*>(xcomponent->GetNativeWindow());
2240 #else
2241     auto container = Container::Current();
2242     if (!container) {
2243         return;
2244     }
2245     auto nativeView = container->GetAceView();
2246     if (!nativeView) {
2247         return;
2248     }
2249     auto textureId = static_cast<int64_t>(xcomponent->GetTextureId());
2250     nativeWindow = const_cast<void*>(nativeView->GetNativeWindowById(textureId));
2251 #endif
2252 
2253     if (!nativeWindow) {
2254         return;
2255     }
2256     nativeXComponentImpl_->SetSurface(nativeWindow);
2257     nativeXComponentImpl_->SetXComponentId(xcomponent->GetId());
2258 
2259     auto arkNativeEngine = static_cast<ArkNativeEngine*>(nativeEngine_);
2260     if (arkNativeEngine == nullptr) {
2261         return;
2262     }
2263 
2264     napi_handle_scope handleScope;
2265     napi_status status = napi_open_handle_scope(reinterpret_cast<napi_env>(nativeEngine_), &handleScope);
2266     if (status != napi_ok) {
2267         return;
2268     }
2269     std::string arguments;
2270     auto soPath = xcomponent->GetSoPath().value_or("");
2271     auto runtime = engineInstance_->GetJsRuntime();
2272     shared_ptr<ArkJSRuntime> pandaRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
2273     LocalScope scope(pandaRuntime->GetEcmaVm());
2274     auto objXComp = arkNativeEngine->LoadModuleByName(xcomponent->GetLibraryName(), true, arguments,
2275         OH_NATIVE_XCOMPONENT_OBJ, reinterpret_cast<void*>(nativeXComponent_), soPath);
2276     if (objXComp.IsEmpty() || pandaRuntime->HasPendingException()) {
2277         return;
2278     }
2279 
2280     auto objContext = JsiObject(objXComp);
2281     JSRef<JSObject> obj = JSRef<JSObject>::Make(objContext);
2282     XComponentClient::GetInstance().AddJsValToJsValMap(componentId, obj);
2283     napi_close_handle_scope(reinterpret_cast<napi_env>(nativeEngine_), handleScope);
2284 
2285     auto task = [weak = WeakClaim(this), xcomponent]() {
2286         auto pool = xcomponent->GetTaskPool();
2287         if (!pool) {
2288             return;
2289         }
2290         auto bridge = weak.Upgrade();
2291         if (bridge) {
2292 #ifdef XCOMPONENT_SUPPORTED
2293             pool->NativeXComponentInit(
2294                 bridge->nativeXComponent_, AceType::WeakClaim(AceType::RawPtr(bridge->nativeXComponentImpl_)));
2295 #endif
2296         }
2297     };
2298 
2299     auto delegate = engineInstance_->GetDelegate();
2300     if (!delegate) {
2301         return;
2302     }
2303     delegate->PostSyncTaskToPage(task, "ArkUINativeXComponentInit");
2304 #endif
2305 }
2306 
TimerCallback(const std::string & callbackId,const std::string & delay,bool isInterval)2307 void JsiDeclarativeEngine::TimerCallback(const std::string& callbackId, const std::string& delay, bool isInterval)
2308 {
2309     TimerCallJs(callbackId);
2310     auto runtime = JsiDeclarativeEngineInstance::GetCurrentRuntime();
2311     if (!runtime) {
2312         return;
2313     }
2314     auto instance = static_cast<JsiDeclarativeEngineInstance*>(runtime->GetEmbedderData());
2315     if (instance == nullptr) {
2316         return;
2317     }
2318     auto delegate = instance->GetDelegate();
2319     if (!delegate) {
2320         return;
2321     }
2322 
2323     if (isInterval) {
2324         delegate->WaitTimer(callbackId, delay, isInterval, false);
2325     } else {
2326         JsiTimerModule::GetInstance()->RemoveCallBack(std::stoi(callbackId));
2327         delegate->ClearTimer(callbackId);
2328     }
2329 }
2330 
TimerCallJs(const std::string & callbackId) const2331 void JsiDeclarativeEngine::TimerCallJs(const std::string& callbackId) const
2332 {
2333     shared_ptr<JsValue> func;
2334     std::vector<shared_ptr<JsValue>> params;
2335     if (!JsiTimerModule::GetInstance()->GetCallBack(std::stoi(callbackId), func, params)) {
2336         return;
2337     }
2338     auto runtime = JsiDeclarativeEngineInstance::GetCurrentRuntime();
2339     if (func) {
2340         func->Call(runtime, runtime->GetGlobal(), params, params.size());
2341     }
2342 }
2343 
DestroyPageInstance(int32_t pageId)2344 void JsiDeclarativeEngine::DestroyPageInstance(int32_t pageId)
2345 {
2346     ACE_DCHECK(engineInstance_);
2347 
2348     engineInstance_->DestroyRootViewHandle(pageId);
2349 }
2350 
DestroyApplication(const std::string & packageName)2351 void JsiDeclarativeEngine::DestroyApplication(const std::string& packageName)
2352 {
2353     if (engineInstance_) {
2354         shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
2355         CallAppFunc("onDestroy");
2356     }
2357 }
2358 
UpdateApplicationState(const std::string & packageName,Frontend::State state)2359 void JsiDeclarativeEngine::UpdateApplicationState(const std::string& packageName, Frontend::State state)
2360 {
2361     LOGI("Update application state %{public}s, state: %{public}s", packageName.c_str(),
2362         Frontend::stateToString(state).c_str());
2363     shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
2364     if (!runtime) {
2365         return;
2366     }
2367     switch (state) {
2368         case Frontend::State::ON_SHOW:
2369             if (isFirstCallShow_) {
2370                 isFirstCallShow_ = false;
2371                 break;
2372             }
2373             CallAppFunc("onShow");
2374             break;
2375         case Frontend::State::ON_HIDE:
2376             CallAppFunc("onHide");
2377             break;
2378         case Frontend::State::ON_ACTIVE:
2379             CallAppFunc("onActive");
2380             break;
2381         case Frontend::State::ON_INACTIVE:
2382             CallAppFunc("onInactive");
2383             break;
2384         case Frontend::State::ON_DESTROY:
2385             CallAppFunc("onDestroy");
2386             break;
2387         default:
2388             return;
2389     }
2390 }
2391 
OnWindowDisplayModeChanged(bool isShownInMultiWindow,const std::string & data)2392 void JsiDeclarativeEngine::OnWindowDisplayModeChanged(bool isShownInMultiWindow, const std::string& data)
2393 {
2394     shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
2395     std::vector<shared_ptr<JsValue>> argv = { runtime->NewBoolean(isShownInMultiWindow), runtime->NewString(data) };
2396     CallAppFunc("onWindowDisplayModeChanged", argv);
2397 }
2398 
CallAppFunc(const std::string & appFuncName)2399 bool JsiDeclarativeEngine::CallAppFunc(const std::string& appFuncName)
2400 {
2401     std::vector<shared_ptr<JsValue>> argv = {};
2402     return CallAppFunc(appFuncName, argv);
2403 }
2404 
CallAppFunc(const std::string & appFuncName,std::vector<shared_ptr<JsValue>> & argv)2405 bool JsiDeclarativeEngine::CallAppFunc(const std::string& appFuncName, std::vector<shared_ptr<JsValue>>& argv)
2406 {
2407     shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
2408     ACE_DCHECK(runtime);
2409     shared_ptr<JsValue> global = runtime->GetGlobal();
2410     shared_ptr<JsValue> exportsObject = global->GetProperty(runtime, "exports");
2411     if (!exportsObject->IsObject(runtime)) {
2412         return false;
2413     }
2414     shared_ptr<JsValue> defaultObject = exportsObject->GetProperty(runtime, "default");
2415     if (!defaultObject->IsObject(runtime)) {
2416         return false;
2417     }
2418     shared_ptr<JsValue> func = defaultObject->GetProperty(runtime, appFuncName);
2419     if (!func || !func->IsFunction(runtime)) {
2420         return false;
2421     }
2422     shared_ptr<JsValue> result;
2423     result = func->Call(runtime, defaultObject, argv, argv.size());
2424     return (result->ToString(runtime) == "true");
2425 }
2426 
MediaQueryCallback(const std::string & callbackId,const std::string & args)2427 void JsiDeclarativeEngine::MediaQueryCallback(const std::string& callbackId, const std::string& args)
2428 {
2429     JsEngine::MediaQueryCallback(callbackId, args);
2430 }
2431 
RequestAnimationCallback(const std::string & callbackId,uint64_t timeStamp)2432 void JsiDeclarativeEngine::RequestAnimationCallback(const std::string& callbackId, uint64_t timeStamp) {}
2433 
JsCallback(const std::string & callbackId,const std::string & args)2434 void JsiDeclarativeEngine::JsCallback(const std::string& callbackId, const std::string& args) {}
2435 
RunGarbageCollection()2436 void JsiDeclarativeEngine::RunGarbageCollection()
2437 {
2438     if (engineInstance_ && engineInstance_->GetJsRuntime()) {
2439         engineInstance_->GetJsRuntime()->RunGC();
2440     }
2441 }
2442 
RunFullGarbageCollection()2443 void JsiDeclarativeEngine::RunFullGarbageCollection()
2444 {
2445     if (engineInstance_ && engineInstance_->GetJsRuntime()) {
2446         engineInstance_->GetJsRuntime()->RunFullGC();
2447     }
2448 }
2449 
DumpHeapSnapshot(bool isPrivate)2450 void JsiDeclarativeEngine::DumpHeapSnapshot(bool isPrivate)
2451 {
2452     if (engineInstance_ && engineInstance_->GetJsRuntime()) {
2453         engineInstance_->GetJsRuntime()->DumpHeapSnapshot(isPrivate);
2454     }
2455 }
2456 
NotifyUIIdle()2457 void JsiDeclarativeEngine::NotifyUIIdle()
2458 {
2459     if (engineInstance_ && engineInstance_->GetJsRuntime()) {
2460         engineInstance_->GetJsRuntime()->NotifyUIIdle();
2461     }
2462 }
2463 
GetStacktraceMessage()2464 std::string JsiDeclarativeEngine::GetStacktraceMessage()
2465 {
2466     auto arkNativeEngine = static_cast<ArkNativeEngine*>(nativeEngine_);
2467     if (!arkNativeEngine) {
2468         return "";
2469     }
2470     std::string stack;
2471     arkNativeEngine->SuspendVM();
2472     bool getStackSuccess = arkNativeEngine->BuildJsStackTrace(stack);
2473     arkNativeEngine->ResumeVM();
2474     if (!getStackSuccess) {
2475         return "JS stacktrace is empty";
2476     }
2477 
2478     auto runningPage = engineInstance_ ? engineInstance_->GetRunningPage() : nullptr;
2479     return JsiBaseUtils::TransSourceStack(runningPage, stack);
2480 }
2481 
GetStackTrace(std::string & trace)2482 void JsiDeclarativeEngine::GetStackTrace(std::string& trace)
2483 {
2484     auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
2485     if (!arkRuntime) {
2486         return;
2487     }
2488     auto vm = arkRuntime->GetEcmaVm();
2489     if (!vm) {
2490         return;
2491     }
2492     panda::DFXJSNApi::BuildJsStackTrace(vm, trace);
2493 }
2494 
GetPagePath(const std::string & url)2495 std::string JsiDeclarativeEngine::GetPagePath(const std::string& url)
2496 {
2497     auto iter = namedRouterRegisterMap_.find(url);
2498     if (iter != namedRouterRegisterMap_.end()) {
2499         return iter->second.pagePath;
2500     }
2501     return "";
2502 }
2503 
GetFullPathInfo(const std::string & url)2504 std::string JsiDeclarativeEngine::GetFullPathInfo(const std::string& url)
2505 {
2506     auto iter = routerPathInfoMap_.find(url);
2507     if (iter != routerPathInfoMap_.end()) {
2508         return iter->second;
2509     }
2510     return "";
2511 }
2512 
GetRouteNameByUrl(const std::string & url,const std::string & bundleName,const std::string & moduleName)2513 std::optional<std::string> JsiDeclarativeEngine::GetRouteNameByUrl(
2514     const std::string& url, const std::string& bundleName, const std::string& moduleName)
2515 {
2516     auto iter = std::find_if(namedRouterRegisterMap_.begin(), namedRouterRegisterMap_.end(),
2517         [&bundleName, &moduleName, &url](const auto& item) {
2518             return item.second.bundleName == bundleName && item.second.moduleName == moduleName &&
2519                     item.second.pagePath == url;
2520         });
2521     if (iter != namedRouterRegisterMap_.end()) {
2522         return iter->first;
2523     }
2524     return std::nullopt;
2525 }
2526 
SetLocalStorage(int32_t instanceId,NativeReference * nativeValue)2527 void JsiDeclarativeEngine::SetLocalStorage(int32_t instanceId, NativeReference* nativeValue)
2528 {
2529 #ifdef USE_ARK_ENGINE
2530     auto jsValue = JsConverter::ConvertNapiValueToJsVal(nativeValue->GetNapiValue());
2531     if (jsValue->IsObject()) {
2532         auto storage = JSRef<JSObject>::Cast(jsValue);
2533         JSLocalStorage::AddStorage(instanceId, storage);
2534     }
2535     delete nativeValue;
2536     nativeValue = nullptr;
2537 #endif
2538 }
2539 
SetContext(int32_t instanceId,NativeReference * nativeValue)2540 void JsiDeclarativeEngine::SetContext(int32_t instanceId, NativeReference* nativeValue)
2541 {
2542 #ifdef USE_ARK_ENGINE
2543     napi_handle_scope scope;
2544     napi_status status = napi_open_handle_scope(reinterpret_cast<napi_env>(GetNativeEngine()), &scope);
2545     if (status != napi_ok) {
2546         return;
2547     }
2548     auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(JsiDeclarativeEngineInstance::GetCurrentRuntime());
2549     if (!arkRuntime || !arkRuntime->GetEcmaVm()) {
2550         napi_close_handle_scope(reinterpret_cast<napi_env>(GetNativeEngine()), scope);
2551         return;
2552     }
2553     JAVASCRIPT_EXECUTION_SCOPE_STATIC;
2554     auto localRef = NapiValueToLocalValue(nativeValue->GetNapiValue());
2555     std::shared_ptr<JsValue> jsValue = std::make_shared<ArkJSValue>(arkRuntime, localRef);
2556     if (jsValue->IsObject(arkRuntime)) {
2557         JsiContextModule::AddContext(instanceId_, jsValue);
2558     }
2559     napi_close_handle_scope(reinterpret_cast<napi_env>(GetNativeEngine()), scope);
2560 #endif
2561 }
2562 
GetGroupJsBridge()2563 RefPtr<GroupJsBridge> JsiDeclarativeEngine::GetGroupJsBridge()
2564 {
2565     return AceType::MakeRefPtr<JsiDeclarativeGroupJsBridge>();
2566 }
2567 
OnActive()2568 void JsiDeclarativeEngine::OnActive()
2569 {
2570     shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
2571     if (!runtime) {
2572         return;
2573     }
2574     CallAppFunc("onActive");
2575 }
2576 
OnInactive()2577 void JsiDeclarativeEngine::OnInactive()
2578 {
2579     shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
2580     if (!runtime) {
2581         return;
2582     }
2583     CallAppFunc("onInactive");
2584 }
2585 
OnNewWant(const std::string & data)2586 void JsiDeclarativeEngine::OnNewWant(const std::string& data)
2587 {
2588     shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
2589     if (!runtime) {
2590         return;
2591     }
2592 
2593     shared_ptr<JsValue> object = runtime->ParseJson(data);
2594     std::vector<shared_ptr<JsValue>> argv = { object };
2595     CallAppFunc("onNewWant", argv);
2596 }
2597 
OnStartContinuation()2598 bool JsiDeclarativeEngine::OnStartContinuation()
2599 {
2600     shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
2601     if (!runtime) {
2602         return false;
2603     }
2604 
2605     return CallAppFunc("onStartContinuation");
2606 }
2607 
OnCompleteContinuation(int32_t code)2608 void JsiDeclarativeEngine::OnCompleteContinuation(int32_t code)
2609 {
2610     shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
2611     if (!runtime) {
2612         return;
2613     }
2614 
2615     std::vector<shared_ptr<JsValue>> argv = { runtime->NewNumber(code) };
2616     CallAppFunc("onCompleteContinuation", argv);
2617 }
2618 
OnRemoteTerminated()2619 void JsiDeclarativeEngine::OnRemoteTerminated()
2620 {
2621     shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
2622     if (!runtime) {
2623         return;
2624     }
2625 
2626     CallAppFunc("onRemoteTerminated");
2627 }
2628 
OnSaveData(std::string & data)2629 void JsiDeclarativeEngine::OnSaveData(std::string& data)
2630 {
2631     shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
2632     if (!runtime) {
2633         return;
2634     }
2635 
2636     shared_ptr<JsValue> object = runtime->NewObject();
2637     std::vector<shared_ptr<JsValue>> argv = { object };
2638     if (CallAppFunc("onSaveData", argv)) {
2639         data = object->GetJsonString(runtime);
2640     }
2641 }
2642 
SetErrorEventHandler(std::function<void (const std::string &,const std::string &)> && errorCallback)2643 void JsiDeclarativeEngine::SetErrorEventHandler(
2644     std::function<void(const std::string&, const std::string&)>&& errorCallback)
2645 {
2646     shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
2647     if (!runtime) {
2648         return;
2649     }
2650 
2651     runtime->SetErrorEventHandler(std::move(errorCallback));
2652 }
2653 
OnRestoreData(const std::string & data)2654 bool JsiDeclarativeEngine::OnRestoreData(const std::string& data)
2655 {
2656     shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
2657     if (!runtime) {
2658         return false;
2659     }
2660     shared_ptr<JsValue> result;
2661     shared_ptr<JsValue> jsonObj = runtime->ParseJson(data);
2662     if (jsonObj->IsUndefined(runtime) || jsonObj->IsException(runtime)) {
2663         return false;
2664     }
2665     std::vector<shared_ptr<JsValue>> argv = { jsonObj };
2666     return CallAppFunc("onRestoreData", argv);
2667 }
2668 
AddToNavigationBuilderMap(std::string name,panda::Global<panda::ObjectRef> builderFunc)2669 void JsiDeclarativeEngine::AddToNavigationBuilderMap(std::string name,
2670     panda::Global<panda::ObjectRef> builderFunc)
2671 {
2672     auto ret = builderMap_.insert(std::pair<std::string, panda::Global<panda::ObjectRef>>(name, builderFunc));
2673     if (!ret.second) {
2674         TAG_LOGW(AceLogTag::ACE_NAVIGATION, "insert builder failed, update builder: %{public}s", name.c_str());
2675         builderMap_[name] = builderFunc;
2676     }
2677 }
2678 
GetNavigationBuilder(std::string name)2679 panda::Global<panda::ObjectRef> JsiDeclarativeEngine::GetNavigationBuilder(std::string name)
2680 {
2681     auto targetBuilder = builderMap_.find(name);
2682     if (targetBuilder == builderMap_.end()) {
2683         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "get navDestination builder failed: %{public}s", name.c_str());
2684         return panda::Global<panda::ObjectRef>();
2685     }
2686     return targetBuilder->second;
2687 }
2688 
JsStateProfilerResgiter()2689 void JsiDeclarativeEngine::JsStateProfilerResgiter()
2690 {
2691 #if defined(PREVIEW)
2692     return;
2693 #else
2694     CHECK_NULL_VOID(runtime_);
2695     auto engine = reinterpret_cast<NativeEngine*>(runtime_);
2696     CHECK_NULL_VOID(engine);
2697     auto vm = engine->GetEcmaVm();
2698     CHECK_NULL_VOID(vm);
2699     auto globalObj = JSNApi::GetGlobalObject(vm);
2700     const auto globalObject = JSRef<JSObject>::Make(globalObj);
2701 
2702     const JSRef<JSVal> setProfilerStatus = globalObject->GetProperty("setProfilerStatus");
2703     if (!setProfilerStatus->IsFunction()) {
2704         return;
2705     }
2706 
2707     const auto globalFunc = JSRef<JSFunc>::Cast(setProfilerStatus);
2708     std::function<void(bool)> callback = [globalFunc, globalObject, instanceId = instanceId_](
2709                                              bool enableStateProfiler) {
2710         ContainerScope scope(instanceId);
2711 
2712         const std::function<void()> task = [globalFunc, globalObject, enableStateProfiler]() {
2713             auto isInStateProfiler = JSRef<JSVal>::Make(ToJSValue(enableStateProfiler));
2714             globalFunc->Call(globalObject, 1, &isInStateProfiler);
2715         };
2716 
2717         auto executor = Container::CurrentTaskExecutor();
2718         CHECK_NULL_VOID(executor);
2719         executor->PostSyncTask(task, TaskExecutor::TaskType::UI, "setProfilerStatus");
2720     };
2721 
2722     LayoutInspector::SetJsStateProfilerStatusCallback(std::move(callback));
2723 #endif
2724 }
2725 
2726 // ArkTsCard start
2727 #ifdef FORM_SUPPORTED
PreloadAceModuleCard(void * runtime,const std::unordered_set<std::string> & formModuleList)2728 void JsiDeclarativeEngineInstance::PreloadAceModuleCard(
2729     void* runtime, const std::unordered_set<std::string>& formModuleList)
2730 {
2731     isUnique_ = true;
2732     if (isModulePreloaded_ && !IsPlugin() && !isUnique_) {
2733         return;
2734     }
2735     auto sharedRuntime = reinterpret_cast<NativeEngine*>(runtime);
2736 
2737     if (!sharedRuntime) {
2738         return;
2739     }
2740     std::shared_ptr<ArkJSRuntime> arkRuntime = std::make_shared<ArkJSRuntime>();
2741     localRuntime_ = arkRuntime;
2742     auto nativeArkEngine = static_cast<ArkNativeEngine*>(sharedRuntime);
2743     EcmaVM* vm = const_cast<EcmaVM*>(nativeArkEngine->GetEcmaVm());
2744     if (vm == nullptr) {
2745         return;
2746     }
2747     if (arkRuntime->InitializeFromExistVM(vm)) {
2748         arkRuntime->SetThreadVm(vm);
2749     } else {
2750         return;
2751     }
2752     LocalScope scope(vm);
2753     {
2754         std::unique_lock<std::shared_mutex> lock(globalRuntimeMutex_);
2755         globalRuntime_ = arkRuntime;
2756     }
2757 
2758     RegisterStringCacheTable(vm, MAX_STRING_CACHE_SIZE);
2759     // preload js views
2760     JsRegisterFormViews(JSNApi::GetGlobalObject(vm), formModuleList, false, runtime);
2761     // preload aceConsole
2762     shared_ptr<JsValue> global = arkRuntime->GetGlobal();
2763     PreloadAceConsole(arkRuntime, global);
2764     // preload aceTrace
2765     PreloadAceTrace(arkRuntime, global);
2766     // preload getContext
2767     JsiContextModule::GetInstance()->InitContextModule(arkRuntime, global);
2768     // preload exports
2769     PreloadExports(arkRuntime, global);
2770 
2771     // preload js enums
2772     bool jsEnumStyleResult = PreloadJsEnums(arkRuntime);
2773     if (!jsEnumStyleResult) {
2774         std::unique_lock<std::shared_mutex> lock(globalRuntimeMutex_);
2775         globalRuntime_ = nullptr;
2776         return;
2777     }
2778 
2779     // preload ark component
2780     bool arkComponentResult = PreloadArkComponent(arkRuntime);
2781     if (!arkComponentResult) {
2782         std::unique_lock<std::shared_mutex> lock(globalRuntimeMutex_);
2783         globalRuntime_ = nullptr;
2784         return;
2785     }
2786 
2787     // preload state management
2788     isModulePreloaded_ = PreloadStateManagement(arkRuntime);
2789 
2790     // preload ark styles
2791     bool arkThemeResult = PreloadArkTheme(arkRuntime);
2792     if (!arkThemeResult) {
2793         std::unique_lock<std::shared_mutex> lock(globalRuntimeMutex_);
2794         globalRuntime_ = nullptr;
2795         return;
2796     }
2797 
2798     {
2799         std::unique_lock<std::shared_mutex> lock(globalRuntimeMutex_);
2800         globalRuntime_ = nullptr;
2801     }
2802     cardRuntime_ = runtime;
2803     TAG_LOGI(AceLogTag::ACE_FORM, "Card model is preloaded successfully.");
2804 }
2805 
ReloadAceModuleCard(void * runtime,const std::unordered_set<std::string> & formModuleList)2806 void JsiDeclarativeEngineInstance::ReloadAceModuleCard(
2807     void* runtime, const std::unordered_set<std::string>& formModuleList)
2808 {
2809     auto sharedRuntime = reinterpret_cast<NativeEngine*>(runtime);
2810 
2811     if (!sharedRuntime) {
2812         return;
2813     }
2814     auto nativeArkEngine = static_cast<ArkNativeEngine*>(sharedRuntime);
2815     EcmaVM* vm = const_cast<EcmaVM*>(nativeArkEngine->GetEcmaVm());
2816     if (vm == nullptr) {
2817         return;
2818     }
2819     LocalScope scope(vm);
2820     RegisterStringCacheTable(vm, MAX_STRING_CACHE_SIZE);
2821     // reload js views
2822     JsRegisterFormViews(JSNApi::GetGlobalObject(vm), formModuleList, true);
2823     JSNApi::TriggerGC(vm, panda::ecmascript::GCReason::TRIGGER_BY_ARKUI, JSNApi::TRIGGER_GC_TYPE::FULL_GC);
2824     TAG_LOGI(AceLogTag::ACE_FORM, "Card model was reloaded successfully.");
2825 }
2826 #endif
2827 
GetCachedString(const EcmaVM * vm,int32_t propertyIndex)2828 panda::Local<panda::StringRef> JsiDeclarativeEngineInstance::GetCachedString(const EcmaVM *vm, int32_t propertyIndex)
2829 {
2830     return panda::ExternalStringCache::GetCachedString(vm, propertyIndex);
2831 }
2832 
SetCachedString(const EcmaVM * vm)2833 void JsiDeclarativeEngineInstance::SetCachedString(const EcmaVM* vm)
2834 {
2835     #define REGISTER_ALL_CACHE_STRING(name, index)              \
2836         panda::ExternalStringCache::SetCachedString(vm, name, static_cast<int32_t>(ArkUIIndex::index));
2837     ARK_UI_KEY(REGISTER_ALL_CACHE_STRING)
2838     #undef REGISTER_ALL_CACHE_STRING
2839 }
2840 
RegisterStringCacheTable(const EcmaVM * vm,int32_t size)2841 bool JsiDeclarativeEngineInstance::RegisterStringCacheTable(const EcmaVM* vm, int32_t size)
2842 {
2843     if (vm == nullptr) {
2844         return false;
2845     }
2846     if (static_cast<uint32_t>(size) > MAX_STRING_CACHE_SIZE) {
2847         return false;
2848     }
2849 
2850     bool res = panda::ExternalStringCache::RegisterStringCacheTable(vm, size);
2851     if (!res) {
2852         return false;
2853     }
2854     SetCachedString(vm);
2855     return true;
2856 }
2857 
2858 // ArkTsCard end
2859 } // namespace OHOS::Ace::Framework
2860