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