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