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