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