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