1 /*
2 * Copyright (c) 2021-2022 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/js_frontend/engine/jsi/jsi_engine.h"
17
18 #ifndef WINDOWS_PLATFORM
19 #include <dlfcn.h>
20 #endif
21 #include <regex>
22 #include <unistd.h>
23
24 #include "base/i18n/localization.h"
25 #include "base/log/ace_trace.h"
26 #include "base/log/event_report.h"
27 #include "base/thread/task_executor.h"
28 #include "base/utils/time_util.h"
29 #include "bridge/js_frontend/engine/jsi/ark_js_runtime.h"
30 #include "bridge/js_frontend/engine/jsi/ark_js_value.h"
31 #include "bridge/js_frontend/engine/jsi/jsi_base_utils.h"
32 #include "core/common/ace_application_info.h"
33 #include "core/common/connect_server_manager.h"
34 #include "core/common/container.h"
35 #include "core/common/container_scope.h"
36 #include "core/components/common/layout/grid_system_manager.h"
37 #include "frameworks/bridge/common/utils/utils.h"
38 #include "frameworks/bridge/js_frontend/engine/common/js_api_perf.h"
39 #include "frameworks/bridge/js_frontend/engine/common/js_constants.h"
40 #include "frameworks/bridge/js_frontend/engine/common/runtime_constants.h"
41 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_animation_bridge.h"
42 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_animator_bridge.h"
43 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_badge_bridge.h"
44 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_canvas_bridge.h"
45 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_chart_bridge.h"
46 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_clock_bridge.h"
47 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_component_api_bridge.h"
48 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_image_animator_bridge.h"
49 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_input_bridge.h"
50 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_list_bridge.h"
51 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_offscreen_canvas_bridge.h"
52 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_stepper_bridge.h"
53 #include "frameworks/bridge/js_frontend/engine/jsi/jsi_xcomponent_bridge.h"
54
55 #ifdef PIXEL_MAP_SUPPORTED
56 #include "pixel_map.h"
57 #include "pixel_map_napi.h"
58 #endif
59
60 #ifndef OHOS_PLATFORM
61 extern const uint8_t _binary_strip_native_min_abc_start[];
62 extern const uint8_t* _binary_strip_native_min_abc_end;
63 #if defined(PREVIEW)
64 extern const uint8_t _binary_jsMockSystemPlugin_abc_start[];
65 extern const uint8_t* _binary_jsMockSystemPlugin_abc_end;
66 #endif
67 #endif
68
69 namespace OHOS::Ace::Framework {
70
71 const int SYSTEM_BASE = 10;
72
73 #if defined(ANDROID_PLATFORM)
74 const std::string ARK_DEBUGGER_LIB_PATH = "libark_debugger.so";
75 #elif defined(APP_USE_ARM)
76 const std::string ARK_DEBUGGER_LIB_PATH = "/system/lib/libark_debugger.z.so";
77 #else
78 const std::string ARK_DEBUGGER_LIB_PATH = "/system/lib64/libark_debugger.z.so";
79 #endif
80 const int32_t MAX_READ_TEXT_LENGTH = 4096;
81 const std::regex URI_PATTERN("^\\/([a-z0-9A-Z_]+\\/)*[a-z0-9A-Z_]+\\.?[a-z0-9A-Z_]*$");
82 using std::shared_ptr;
83 static int32_t globalNodeId = 100000;
84 std::map<const std::string, std::string> JsiEngineInstance::dataMap_;
85 RefPtr<Clipboard> clipboard;
86
87 #if !defined(PREVIEW)
CreatePixelMapFromNapiValue(const shared_ptr<JsRuntime> & runtime,shared_ptr<JsValue> jsValue)88 RefPtr<PixelMap> CreatePixelMapFromNapiValue(const shared_ptr<JsRuntime>& runtime, shared_ptr<JsValue> jsValue)
89 {
90 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
91 if (!engine) {
92 LOGE("engine is null.");
93 return nullptr;
94 }
95
96 auto nativeEngine = static_cast<ArkNativeEngine*>(engine->GetNativeEngine());
97 if (!nativeEngine) {
98 LOGE("NativeEngine is null");
99 return nullptr;
100 }
101
102 shared_ptr<ArkJSValue> arkJsValue = std::static_pointer_cast<ArkJSValue>(jsValue);
103 if (!arkJsValue) {
104 LOGE("arkJsValue is null.");
105 return nullptr;
106 }
107 shared_ptr<ArkJSRuntime> arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime);
108 if (!arkRuntime) {
109 LOGE("arkRuntime is null");
110 return nullptr;
111 }
112
113 JSValueWrapper valueWrapper = arkJsValue->GetValue(arkRuntime);
114 napi_value napiValue = nativeEngine->ValueToNapiValue(valueWrapper);
115
116 PixelMapNapiEntry pixelMapNapiEntry = JsEngine::GetPixelMapNapiEntry();
117 if (!pixelMapNapiEntry) {
118 LOGE("pixelMapNapiEntry is null");
119 return nullptr;
120 }
121 void* pixmapPtrAddr =
122 pixelMapNapiEntry(reinterpret_cast<napi_env>(nativeEngine), napiValue);
123 if (pixmapPtrAddr == nullptr) {
124 LOGE(" Failed to get pixmap pointer");
125 return nullptr;
126 }
127 return PixelMap::CreatePixelMap(pixmapPtrAddr);
128 }
129 #endif
130
GetStagingPage(const shared_ptr<JsRuntime> & runtime)131 RefPtr<JsAcePage> GetStagingPage(const shared_ptr<JsRuntime>& runtime)
132 {
133 if (!runtime) {
134 LOGE("JsRuntime is null, cannot get staging page!");
135 return nullptr;
136 }
137 auto engineInstance = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
138 return engineInstance->GetStagingPage();
139 }
140
GetRunningPage(const shared_ptr<JsRuntime> & runtime)141 RefPtr<JsAcePage> GetRunningPage(const shared_ptr<JsRuntime>& runtime)
142 {
143 if (!runtime) {
144 LOGE("JsRuntime is null, cannot get running page!");
145 return nullptr;
146 }
147 auto engineInstance = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
148 return engineInstance->GetRunningPage();
149 }
150
GetFrontendDelegate(const shared_ptr<JsRuntime> & runtime)151 RefPtr<FrontendDelegate> GetFrontendDelegate(const shared_ptr<JsRuntime>& runtime)
152 {
153 if (!runtime) {
154 LOGE("JsRuntime is null, cannot get frontend delegate!");
155 return nullptr;
156 }
157 auto engineInstance = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
158 return engineInstance->GetFrontendDelegate();
159 }
160
GetValueAsString(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,std::string & str)161 void GetValueAsString(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value, std::string& str)
162 {
163 if (!value->IsObject(runtime)) {
164 LOGE("JsValue is not an object!");
165 return;
166 }
167 int32_t len = 0;
168 shared_ptr<JsValue> propertyNames;
169 value->GetEnumerablePropertyNames(runtime, propertyNames, len);
170 for (int32_t i = 0; i < len; ++i) {
171 if (i != 0) {
172 str.append(1, DOM_PICKER_SPLIT_ARRAY);
173 }
174
175 shared_ptr<JsValue> key = propertyNames->GetElement(runtime, i);
176 shared_ptr<JsValue> item = value->GetProperty(runtime, key);
177
178 if (item->IsString(runtime) || item->IsNumber(runtime) || item->IsBoolean(runtime)) {
179 std::string valStr = item->ToString(runtime);
180 str.append(valStr);
181 continue;
182 }
183 if (item->IsArray(runtime)) {
184 int32_t subLen = item->GetArrayLength(runtime);
185 for (int32_t j = 0; j < subLen; ++j) {
186 if (j != 0) {
187 str.append(1, DOM_PICKER_SPLIT_ITEM);
188 }
189
190 shared_ptr<JsValue> subItem = item->GetElement(runtime, j);
191 std::string subItemStr = subItem->ToString(runtime);
192 str.append(subItemStr);
193 }
194 continue;
195 }
196 }
197 }
198
GetStyleFamilyValue(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,std::string & familyStyle)199 void GetStyleFamilyValue(
200 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value, std::string& familyStyle)
201 {
202 std::string family;
203 std::string src;
204 int32_t len = value->GetArrayLength(runtime);
205 for (int32_t i = 0; i < len; ++i) {
206 // ValArray is one row of family array
207 shared_ptr<JsValue> element = value->GetElement(runtime, i);
208 if (element->IsObject(runtime)) {
209 shared_ptr<JsValue> properties;
210 int32_t objLen = 0;
211 element->GetPropertyNames(runtime, properties, objLen);
212 for (int32_t j = 0; j < objLen; ++j) {
213 shared_ptr<JsValue> propKey = properties->GetElement(runtime, j);
214 shared_ptr<JsValue> propValue = element->GetProperty(runtime, propKey);
215 if (propValue->IsString(runtime)) {
216 std::string propValueStr = propValue->ToString(runtime);
217 std::string propKeyStr = propKey->ToString(runtime);
218 if (propKeyStr == "fontFamily") {
219 family = propValueStr;
220 if (!src.empty()) {
221 GetFrontendDelegate(runtime)->RegisterFont(family, src);
222 family.erase();
223 src.erase();
224 }
225 if (familyStyle.length() > 0) {
226 familyStyle += ",";
227 }
228 familyStyle += propValueStr;
229 } else if (propKeyStr == "src") {
230 // The format of font src is: url("src"), here get the src.
231 src = propValueStr.substr(URL_SOURCE_START_IDX, propValueStr.length() - URL_SOURCE_SUFFIX_LEN);
232 if (!family.empty()) {
233 GetFrontendDelegate(runtime)->RegisterFont(family, src);
234 family.erase();
235 src.erase();
236 }
237 }
238 }
239 }
240 }
241 }
242 }
243
GetStyleAnimationName(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & value,std::vector<std::unordered_map<std::string,std::string>> & styleVec)244 void GetStyleAnimationName(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& value,
245 std::vector<std::unordered_map<std::string, std::string>>& styleVec)
246 {
247 int32_t len = value->GetArrayLength(runtime);
248 for (int32_t i = 0; i < len; ++i) {
249 std::unordered_map<std::string, std::string> animationNameKeyFrame;
250 shared_ptr<JsValue> element = value->GetElement(runtime, i);
251 if (element->IsObject(runtime)) {
252 int32_t objLen = 0;
253 shared_ptr<JsValue> properties;
254 element->GetPropertyNames(runtime, properties, objLen);
255 for (int32_t j = 0; j < objLen; ++j) {
256 shared_ptr<JsValue> propKey = properties->GetElement(runtime, j);
257 shared_ptr<JsValue> propValue = element->GetProperty(runtime, propKey);
258 if (propValue->IsString(runtime) || propValue->IsNumber(runtime)) {
259 std::string propKeyStr = propKey->ToString(runtime);
260 std::string propValueStr = propValue->ToString(runtime);
261 animationNameKeyFrame.emplace(propKeyStr, propValueStr);
262 }
263 }
264 }
265 if (!animationNameKeyFrame.empty()) {
266 styleVec.emplace_back(animationNameKeyFrame);
267 }
268 }
269 }
270
GetAttrImage(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & valObject,ImageProperties & imageProperties)271 void GetAttrImage(
272 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& valObject, ImageProperties& imageProperties)
273 {
274 if (!runtime || !valObject) {
275 return;
276 }
277 shared_ptr<JsValue> propertyNames;
278 int32_t len = 0;
279 valObject->GetPropertyNames(runtime, propertyNames, len);
280 for (auto i = 0; i < len; ++i) {
281 shared_ptr<JsValue> key = propertyNames->GetElement(runtime, i);
282 if (!key) {
283 LOGW("key is null. Ignoring!");
284 continue;
285 }
286 std::string keyStr = key->ToString(runtime);
287 shared_ptr<JsValue> value = valObject->GetProperty(runtime, key);
288 if (!value) {
289 LOGW("value is null. Ignoring!");
290 continue;
291 }
292 std::string valStr = value->ToString(runtime);
293 if (value->IsString(runtime) || value->IsNumber(runtime) || value->IsBoolean(runtime)) {
294 if (keyStr == DOM_SRC) {
295 imageProperties.src = valStr;
296 } else if (keyStr == DOM_WIDTH) {
297 imageProperties.width = StringToDimension(valStr);
298 } else if (keyStr == DOM_HEIGHT) {
299 imageProperties.height = StringToDimension(valStr);
300 } else if (keyStr == DOM_TOP) {
301 imageProperties.top = StringToDimension(valStr);
302 } else if (keyStr == DOM_LEFT) {
303 imageProperties.left = StringToDimension(valStr);
304 } else if (keyStr == DOM_DURATION) {
305 imageProperties.duration = StringToInt(valStr);
306 }
307 }
308 }
309 }
310
GetAttrImages(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arrayVal,std::vector<ImageProperties> & images)311 void GetAttrImages(
312 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arrayVal, std::vector<ImageProperties>& images)
313 {
314 if (!arrayVal) {
315 return;
316 }
317 int32_t length = arrayVal->GetArrayLength(runtime);
318 for (int32_t i = 0; i < length; ++i) {
319 shared_ptr<JsValue> valArray = arrayVal->GetProperty(runtime, i);
320 ImageProperties imageProperties;
321 if (valArray && valArray->IsObject(runtime)) {
322 GetAttrImage(runtime, valArray, imageProperties);
323 images.push_back(imageProperties);
324 }
325 }
326 }
327
SetDomAttributesWithArray(const shared_ptr<JsRuntime> & runtime,const std::string & keyStr,const shared_ptr<JsValue> & value,std::vector<std::pair<std::string,std::string>> & attrs,JsCommandDomElementOperator & command)328 void SetDomAttributesWithArray(const shared_ptr<JsRuntime>& runtime, const std::string& keyStr,
329 const shared_ptr<JsValue>& value, std::vector<std::pair<std::string, std::string>>& attrs,
330 JsCommandDomElementOperator& command)
331 {
332 if (!value->IsArray(runtime)) {
333 LOGE("Value is not array type.");
334 return;
335 }
336 if (keyStr == "datasets") {
337 auto chartBridge = AceType::MakeRefPtr<JsiChartBridge>();
338 chartBridge->GetAttrDatasets(runtime, value);
339 command.SetDatasets(chartBridge->GetDatasets());
340 } else if (keyStr == "images") {
341 std::vector<ImageProperties> images;
342 GetAttrImages(runtime, value, images);
343 command.SetImagesAttr(std::move(images));
344 } else if (keyStr == "segments") {
345 auto chartBridge = AceType::MakeRefPtr<JsiChartBridge>();
346 chartBridge->ParseAttrSegmentArray(runtime, value);
347 command.SetSegments(chartBridge->GetSegments());
348 } else if (keyStr == "menuoptions") {
349 auto inputBridge = AceType::MakeRefPtr<JsiInputBridge>();
350 inputBridge->ParseInputOptions(runtime, value);
351 command.SetInputOptions(inputBridge->GetInputOptions());
352 } else {
353 std::string valStr;
354 GetValueAsString(runtime, value, valStr);
355 attrs.emplace_back(keyStr, valStr);
356 }
357 }
358
SetDomAttributesWithObject(const shared_ptr<JsRuntime> & runtime,const std::string & keyStr,const shared_ptr<JsValue> & value,JsCommandDomElementOperator & command)359 void SetDomAttributesWithObject(const shared_ptr<JsRuntime>& runtime, const std::string& keyStr,
360 const shared_ptr<JsValue>& value, JsCommandDomElementOperator& command)
361 {
362 if (keyStr == "options") {
363 auto chartBridge = AceType::MakeRefPtr<JsiChartBridge>();
364 chartBridge->GetAttrOptionsObject(runtime, value);
365 command.SetOptions(chartBridge->GetChartOptions());
366 } else if (keyStr == "segments") {
367 auto chartBridge = AceType::MakeRefPtr<JsiChartBridge>();
368 chartBridge->ParseAttrSingleSegment(runtime, value);
369 command.SetSegments(chartBridge->GetSegments());
370 } else if (keyStr == DOM_CLOCK_CONFIG) {
371 auto clockBridge = AceType::MakeRefPtr<JsiClockBridge>();
372 clockBridge->ParseClockConfig(runtime, value);
373 command.SetClockConfig(clockBridge->GetClockConfig());
374 } else if (keyStr == DOM_NODE_TAG_LABEL) {
375 auto stepperBridge = AceType::MakeRefPtr<JsiStepperBridge>();
376 StepperLabels label;
377 stepperBridge->GetAttrLabel(runtime, value, label);
378 command.SetStepperLabel(label);
379 } else if (keyStr == DOM_BADGE_CONFIG) {
380 auto badgeBridge = AceType::MakeRefPtr<JsiBadgeBridge>();
381 badgeBridge->ParseBadgeConfig(runtime, value);
382 command.SetBadgeConfig(badgeBridge->GetBadgeConfig());
383 } else if (keyStr == DOM_STEPPER_LABEL) {
384 auto stepperBridge = AceType::MakeRefPtr<JsiStepperBridge>();
385 StepperLabels label;
386 stepperBridge->GetAttrLabel(runtime, value, label);
387 command.SetStepperLabel(label);
388 }
389 }
390
SetDomAttributes(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & attrObj,JsCommandDomElementOperator & command)391 bool SetDomAttributes(
392 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& attrObj, JsCommandDomElementOperator& command)
393 {
394 bool hasShowAttr = false;
395
396 if (!attrObj || !attrObj->IsObject(runtime)) {
397 return false;
398 }
399
400 int32_t len = 0;
401 shared_ptr<JsValue> properties;
402 attrObj->GetPropertyNames(runtime, properties, len);
403
404 std::vector<std::pair<std::string, std::string>> attrs;
405 for (int32_t i = 0; i < len; ++i) {
406 shared_ptr<JsValue> key = properties->GetElement(runtime, i);
407 if (!key) {
408 LOGE("key is null. Ignoring!");
409 continue;
410 }
411 shared_ptr<JsValue> value = attrObj->GetProperty(runtime, key);
412 std::string keyStr = key->ToString(runtime);
413 if (value->IsString(runtime) || value->IsNumber(runtime) || value->IsBoolean(runtime)) {
414 std::string valStr = value->ToString(runtime);
415 if (keyStr == DOM_ID) {
416 command.SetId(valStr);
417 } else if (keyStr == DOM_TARGET) {
418 command.SetTarget(valStr);
419 } else if (keyStr == DOM_SHARE_ID) {
420 command.SetShareId(valStr);
421 }
422 attrs.emplace_back(keyStr, valStr);
423 if (keyStr == DOM_SHOW) {
424 hasShowAttr = true;
425 }
426 } else if (value->IsArray(runtime)) {
427 SetDomAttributesWithArray(runtime, keyStr, value, attrs, command);
428 } else if (value->IsObject(runtime)) {
429 SetDomAttributesWithObject(runtime, keyStr, value, command);
430 } else if (value->IsUndefined(runtime)) {
431 LOGE("value of key[%{private}s] is undefined. Ignoring!", keyStr.c_str());
432 } else {
433 LOGE("value of key[%{private}s] unsupported type. Ignoring!", keyStr.c_str());
434 }
435 }
436 command.SetAttributes(std::move(attrs));
437 return hasShowAttr;
438 }
439
SetDomStyle(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & styleObj,JsCommandDomElementOperator & command)440 void SetDomStyle(
441 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& styleObj, JsCommandDomElementOperator& command)
442 {
443 if (!styleObj || !styleObj->IsObject(runtime)) {
444 return;
445 }
446
447 int32_t len = 0;
448 shared_ptr<JsValue> properties;
449 styleObj->GetPropertyNames(runtime, properties, len);
450
451 std::vector<std::pair<std::string, std::string>> styles;
452 for (int32_t i = 0; i < len; ++i) {
453 shared_ptr<JsValue> key = properties->GetElement(runtime, i);
454 if (!key) {
455 LOGE("key is null. Ignoring!");
456 continue;
457 }
458 shared_ptr<JsValue> value = styleObj->GetProperty(runtime, key);
459 std::string keyStr = key->ToString(runtime);
460 if (value->IsString(runtime) || value->IsNumber(runtime) || value->IsBoolean(runtime)) {
461 std::string valStr = value->ToString(runtime);
462 styles.emplace_back(keyStr, valStr);
463 } else if (value->IsArray(runtime)) {
464 if (strcmp(keyStr.c_str(), DOM_TEXT_FONT_FAMILY) == 0) {
465 // Deal with special case such as fontFamily, suppose all the keys in the array are the same.
466 std::string familyStyle;
467 GetStyleFamilyValue(runtime, value, familyStyle);
468 styles.emplace_back(keyStr, familyStyle);
469 } else if (strcmp(keyStr.c_str(), DOM_ANIMATION_NAME) == 0) {
470 // Deal with special case animationName, it different with fontfamily,
471 // the keys in the array are different.
472 std::vector<std::unordered_map<std::string, std::string>> animationNameStyles;
473 GetStyleAnimationName(runtime, value, animationNameStyles);
474 command.SetAnimationStyles(std::move(animationNameStyles));
475 } else if (strcmp(keyStr.c_str(), DOM_TRANSITION_ENTER) == 0) {
476 std::vector<std::unordered_map<std::string, std::string>> transitionEnter;
477 GetStyleAnimationName(runtime, value, transitionEnter);
478 command.SetTransitionEnter(std::move(transitionEnter));
479 } else if (strcmp(keyStr.c_str(), DOM_TRANSITION_EXIT) == 0) {
480 std::vector<std::unordered_map<std::string, std::string>> transitionExit;
481 GetStyleAnimationName(runtime, value, transitionExit);
482 command.SetTransitionExit(std::move(transitionExit));
483 } else if (strcmp(keyStr.c_str(), DOM_SHARED_TRANSITION_NAME) == 0) {
484 std::vector<std::unordered_map<std::string, std::string>> sharedTransitionName;
485 GetStyleAnimationName(runtime, value, sharedTransitionName);
486 command.SetSharedTransitionName(std::move(sharedTransitionName));
487 }
488 }
489 }
490
491 bool isIine = false;
492 for (int32_t i = 0; i < static_cast<int32_t>(styles.size()); i++) {
493 std::string key = styles[i].first;
494 std::string value = styles[i].second;
495 if (key == "display" && value == "inline") {
496 isIine = true;
497 break;
498 }
499 }
500
501 if (isIine) {
502 std::vector<std::pair<std::string, std::string>> stylesFinally;
503 for (int32_t i = 0; i < static_cast<int32_t>(styles.size()); i++) {
504 std::string key = styles[i].first;
505 std::string value = styles[i].second;
506 if (key == "width" || key == "height" || key.find("margin") != std::string::npos ||
507 key.find("padding") != std::string::npos) {
508 continue;
509 } else {
510 stylesFinally.emplace_back(key, value);
511 }
512 }
513 command.SetStyles(std::move(stylesFinally));
514 } else {
515 command.SetStyles(std::move(styles));
516 }
517 auto pipelineContext = AceType::DynamicCast<PipelineContext>(GetFrontendDelegate(runtime)->GetPipelineContext());
518 command.SetPipelineContext(pipelineContext);
519 }
520
AddDomEvent(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & eventObj,JsCommandDomElementOperator & command)521 void AddDomEvent(
522 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& eventObj, JsCommandDomElementOperator& command)
523 {
524 if (!eventObj || !eventObj->IsObject(runtime)) {
525 return;
526 }
527
528 int32_t len = 0;
529 shared_ptr<JsValue> properties;
530 eventObj->GetPropertyNames(runtime, properties, len);
531
532 std::vector<std::string> events;
533 for (int32_t i = 0; i < len; ++i) {
534 shared_ptr<JsValue> key = properties->GetElement(runtime, i);
535 if (!key) {
536 LOGE("key is null. Ignoring!");
537 continue;
538 }
539 shared_ptr<JsValue> value = eventObj->GetProperty(runtime, key);
540 std::string keyStr = key->ToString(runtime);
541 if (value->IsString(runtime)) {
542 std::string valStr = value->ToString(runtime);
543 events.emplace_back(valStr);
544 } else {
545 LOGW("value of unsupported type. Ignoring!");
546 }
547 }
548 command.AddEvents(std::move(events));
549 }
550
GetAppInfo(const shared_ptr<JsRuntime> & runtime)551 shared_ptr<JsValue> GetAppInfo(const shared_ptr<JsRuntime>& runtime)
552 {
553 auto delegate = GetFrontendDelegate(runtime);
554 shared_ptr<JsValue> appID = runtime->NewString(delegate->GetAppID());
555 shared_ptr<JsValue> appName = runtime->NewString(delegate->GetAppName());
556 shared_ptr<JsValue> versionName = runtime->NewString(delegate->GetVersionName());
557 shared_ptr<JsValue> versionCode = runtime->NewNumber(delegate->GetVersionCode());
558
559 // return the result as an object
560 shared_ptr<JsValue> res = runtime->NewObject();
561 res->SetProperty(runtime, "appID", appID);
562 res->SetProperty(runtime, "appName", appName);
563 res->SetProperty(runtime, "versionName", versionName);
564 res->SetProperty(runtime, "versionCode", versionCode);
565
566 return res;
567 }
568
Terminate(const shared_ptr<JsRuntime> & runtime)569 void Terminate(const shared_ptr<JsRuntime>& runtime)
570 {
571 auto delegate = GetFrontendDelegate(runtime);
572 WeakPtr<PipelineBase> pipelineContextWeak = delegate->GetPipelineContext();
573 auto uiTaskExecutor = delegate->GetUiTask();
574 uiTaskExecutor.PostTask([pipelineContextWeak]() mutable {
575 auto pipelineContext = pipelineContextWeak.Upgrade();
576 if (pipelineContext) {
577 pipelineContext->Finish();
578 }
579 });
580 }
581
GetPackageInfoCallback(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & message,const std::string & callbackId)582 void GetPackageInfoCallback(
583 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& message, const std::string& callbackId)
584 {
585 std::string arguments;
586 std::string methods;
587
588 if (!message || !message->IsObject(runtime)) {
589 LOGE("GetPackageInfoCallback: jsMessage is not Object");
590 arguments.append("{\"arguments\":[\"jsMessage is not Object\",200],");
591 methods.append("\"method\":\"fail\"}");
592 } else {
593 shared_ptr<JsValue> packageName = message->GetProperty(runtime, APP_PACKAGE_NAME);
594 if (!packageName->IsString(runtime) || packageName->ToString(runtime) == "") {
595 arguments.append("{\"arguments\":[\"packageName is not available string\",202],");
596 methods.append("\"method\":\"fail\"}");
597 } else {
598 AceBundleInfo bundleInfo;
599 if (!AceApplicationInfo::GetInstance().GetBundleInfo(packageName->ToString(runtime), bundleInfo)) {
600 LOGE("can not get info by GetBundleInfo");
601 arguments.append("{\"arguments\":[\"can not get info\",200],");
602 methods.append("\"method\":\"fail\"}");
603 } else {
604 auto infoList = JsonUtil::Create(true);
605 infoList->Put("versionName", bundleInfo.versionName.c_str());
606 infoList->Put("versionCode", std::to_string(bundleInfo.versionCode).c_str());
607 arguments.append("{\"arguments\":[").append(infoList->ToString()).append("],");
608 methods.append("\"method\":\"success\"}");
609 }
610 }
611 }
612
613 auto engineInstance = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
614 engineInstance->CallJs(callbackId, arguments + methods, false);
615 }
616
GetPackageInfo(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)617 void GetPackageInfo(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
618 {
619 if (!arg->IsObject(runtime) || !arg->IsArray(runtime)) {
620 LOGE("GetPackageInfo: arg is not Object or Array");
621 return;
622 }
623
624 int32_t len = arg->GetArrayLength(runtime);
625 if (len < static_cast<int32_t>(PAG_INFO_ARGS_LEN)) {
626 LOGE("GetPackageInfo: invalid callback value");
627 return;
628 }
629 shared_ptr<JsValue> message = arg->GetElement(runtime, PAG_INFO_ARGS_MSG_IDX);
630 shared_ptr<JsValue> callBackId = arg->GetElement(runtime, 1);
631 std::string callbackIdStr = callBackId->ToString(runtime);
632 if (!callbackIdStr.empty()) {
633 GetPackageInfoCallback(runtime, message, callbackIdStr);
634 }
635 }
636
RequestFullWindow(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)637 void RequestFullWindow(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
638 {
639 int32_t duration = -1; // default scene
640 const int32_t customFullWindowLength = 2;
641 if (arg->IsArray(runtime)) {
642 int32_t len = arg->GetArrayLength(runtime);
643 if (len == customFullWindowLength) {
644 shared_ptr<JsValue> param = arg->GetElement(runtime, 0);
645 if (param && param->IsObject(runtime)) {
646 shared_ptr<JsValue> durationValue = param->GetProperty(runtime, APP_REQUEST_FULL_WINDOW_DURATION);
647 if (durationValue) {
648 std::string durationStr = durationValue->ToString(runtime);
649 if (!durationStr.empty()) {
650 duration = StringToInt(durationStr);
651 duration = duration >= 0 ? duration : -1;
652 }
653 }
654 }
655 }
656 }
657 auto delegate = GetFrontendDelegate(runtime);
658 WeakPtr<PipelineBase> pipelineContextWeak = delegate->GetPipelineContext();
659 auto uiTaskExecutor = delegate->GetUiTask();
660 uiTaskExecutor.PostTask([pipelineContextWeak, duration]() mutable {
661 auto pipelineContext = pipelineContextWeak.Upgrade();
662 if (pipelineContext) {
663 pipelineContext->RequestFullWindow(duration);
664 }
665 });
666 }
667
SetScreenOnVisible(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)668 void SetScreenOnVisible(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
669 {
670 std::map<std::string, std::string> params;
671 std::string callbackId;
672
673 static int32_t paramsLength = 2;
674 if (!arg->IsArray(runtime) || arg->GetArrayLength(runtime) < paramsLength) {
675 LOGE("SetScreenOnVisible, wrong args length!");
676 return;
677 }
678 // get params
679 shared_ptr<JsValue> paramObj = arg->GetElement(runtime, 0);
680 if (!paramObj || !paramObj->IsObject(runtime)) {
681 LOGE("SetScreenOnVisible, first argument is not an object!");
682 return;
683 }
684 int32_t len = 0;
685 shared_ptr<JsValue> properties;
686 if (!paramObj->GetPropertyNames(runtime, properties, len)) {
687 LOGE("SetScreenOnVisible, fail to get object property list!");
688 return;
689 }
690 for (int32_t i = 0; i < len; ++i) {
691 shared_ptr<JsValue> key = properties->GetElement(runtime, i);
692 shared_ptr<JsValue> val = paramObj->GetProperty(runtime, key);
693 std::string keyStr = key->ToString(runtime);
694 std::string valStr = val->ToString(runtime);
695 params.try_emplace(keyStr, valStr);
696 }
697 // get callbackId
698 callbackId = arg->GetElement(runtime, 1)->ToString(runtime);
699
700 std::string flag = "fail";
701 auto iter = params.find(APP_SCREEN_ON_VISIBLE_FLAG);
702 if (iter != params.end()) {
703 flag = iter->second;
704 }
705
706 auto engineInstance = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
707 if (!StringToBool(flag)) {
708 engineInstance->CallJs(
709 callbackId, R"({"arguments":["fail to set false flag in rich platform", 200],"method":"fail"})");
710 } else {
711 engineInstance->CallJs(callbackId, R"({"arguments":[],"method":"success"})");
712 }
713 }
714
GetLocale(const shared_ptr<JsRuntime> & runtime)715 shared_ptr<JsValue> GetLocale(const shared_ptr<JsRuntime>& runtime)
716 {
717 shared_ptr<JsValue> language = runtime->NewString(AceApplicationInfo::GetInstance().GetLanguage());
718 shared_ptr<JsValue> countryOrRegion = runtime->NewString(AceApplicationInfo::GetInstance().GetCountryOrRegion());
719 shared_ptr<JsValue> dir = runtime->NewString(
720 AceApplicationInfo::GetInstance().IsRightToLeft() ? LOCALE_TEXT_DIR_RTL : LOCALE_TEXT_DIR_LTR);
721
722 shared_ptr<JsValue> res = runtime->NewObject();
723 res->SetProperty(runtime, LOCALE_LANGUAGE, language);
724 res->SetProperty(runtime, LOCALE_COUNTRY_OR_REGION, countryOrRegion);
725 res->SetProperty(runtime, LOCALE_TEXT_DIR, dir);
726 return res;
727 }
728
SetLocale(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)729 void SetLocale(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
730 {
731 std::unique_ptr<JsonValue> localeJson = JsonUtil::ParseJsonString(arg->ToString(runtime));
732
733 if (localeJson) {
734 std::string language;
735 if (localeJson->GetValue(LOCALE_LANGUAGE) != nullptr && localeJson->GetValue(LOCALE_LANGUAGE)->IsString()) {
736 language = localeJson->GetValue(LOCALE_LANGUAGE)->GetString();
737 }
738 std::string countryOrRegion;
739 if (localeJson->GetValue(LOCALE_COUNTRY_OR_REGION) != nullptr &&
740 localeJson->GetValue(LOCALE_COUNTRY_OR_REGION)->IsString()) {
741 countryOrRegion = localeJson->GetValue(LOCALE_COUNTRY_OR_REGION)->GetString();
742 }
743 if (!countryOrRegion.empty() && !language.empty()) {
744 GetFrontendDelegate(runtime)->ChangeLocale(language, countryOrRegion);
745 }
746 }
747 }
748
GetDeviceInfo()749 std::string GetDeviceInfo()
750 {
751 auto infoList = JsonUtil::Create(true);
752 infoList->Put("brand", SystemProperties::GetBrand().c_str());
753 infoList->Put("manufacturer", SystemProperties::GetManufacturer().c_str());
754 infoList->Put("model", SystemProperties::GetModel().c_str());
755 infoList->Put("product", SystemProperties::GetProduct().c_str());
756 std::string tmp = SystemProperties::GetApiVersion();
757 if (tmp != SystemProperties::INVALID_PARAM) {
758 char* tmpEnd = nullptr;
759 infoList->Put("apiVersion", static_cast<int32_t>(
760 std::strtol(SystemProperties::GetApiVersion().c_str(), &tmpEnd, SYSTEM_BASE)));
761 } else {
762 infoList->Put("apiVersion", "N/A");
763 }
764 tmp = SystemProperties::GetReleaseType();
765 if (tmp != SystemProperties::INVALID_PARAM) {
766 infoList->Put("releaseType", tmp.c_str());
767 } else {
768 infoList->Put("releaseType", "N/A");
769 }
770 tmp = SystemProperties::GetParamDeviceType();
771 if (tmp != SystemProperties::INVALID_PARAM) {
772 infoList->Put("deviceType", tmp.c_str());
773 } else {
774 infoList->Put("deviceType", "N/A");
775 }
776 tmp = SystemProperties::GetLanguage();
777 if (tmp != SystemProperties::INVALID_PARAM) {
778 infoList->Put("language", tmp.c_str());
779 } else {
780 infoList->Put("language", "N/A");
781 }
782 tmp = SystemProperties::GetRegion();
783 if (tmp != SystemProperties::INVALID_PARAM) {
784 infoList->Put("region", tmp.c_str());
785 } else {
786 infoList->Put("region", "N/A");
787 }
788
789 auto container = Container::Current();
790 int32_t width = container ? container->GetViewWidth() : 0;
791 if (width != 0) {
792 infoList->Put("windowWidth", width);
793 } else {
794 infoList->Put("windowWidth", "N/A");
795 }
796
797 int32_t height = container ? container->GetViewHeight() : 0;
798 if (height != 0) {
799 infoList->Put("windowHeight", height);
800 } else {
801 infoList->Put("windowHeight", "N/A");
802 }
803
804 infoList->Put("screenDensity", PipelineBase::GetCurrentDensity());
805
806 bool isRound = SystemProperties::GetIsScreenRound();
807 if (isRound) {
808 infoList->Put("screenShape", "circle");
809 } else {
810 infoList->Put("screenShape", "rect");
811 }
812
813 return infoList->ToString();
814 }
815
ParseRouteUrl(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & key)816 std::string ParseRouteUrl(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& key)
817 {
818 std::string argStr = arg->ToString(runtime);
819 if (argStr.empty()) {
820 return argStr;
821 }
822
823 std::string pageRoute;
824 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(argStr);
825 if (argsPtr != nullptr && argsPtr->GetValue(key) != nullptr && argsPtr->GetValue(key)->IsString()) {
826 pageRoute = argsPtr->GetValue(key)->GetString();
827 }
828 return pageRoute;
829 }
830
ParseRouteUrlSpecial(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)831 std::string ParseRouteUrlSpecial(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
832 {
833 std::string argStr = arg->ToString(runtime);
834 if (argStr.empty()) {
835 return argStr;
836 }
837
838 std::string pageRoute;
839 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(argStr);
840
841 if (argsPtr->Contains(ROUTE_KEY_URI)) {
842 pageRoute = argsPtr->GetValue(ROUTE_KEY_URI)->GetString();
843 } else if (argsPtr->Contains(ROUTE_KEY_PATH)) {
844 pageRoute = argsPtr->GetValue(ROUTE_KEY_PATH)->GetString();
845 }
846 return pageRoute;
847 }
848
ParseRouteParams(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & key)849 std::string ParseRouteParams(
850 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& key)
851 {
852 std::string argStr = arg->ToString(runtime);
853 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(argStr);
854 std::string params;
855 if (argsPtr != nullptr && argsPtr->Contains(key) && argsPtr->GetValue(key)->IsObject()) {
856 params = argsPtr->GetValue(key)->ToString();
857 }
858 return params;
859 }
860
ParseIntParams(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & key)861 int32_t ParseIntParams(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& key)
862 {
863 std::string argStr = arg->ToString(runtime);
864 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(argStr);
865 int32_t params = 0;
866 if (argsPtr != nullptr && argsPtr->Contains(key) && argsPtr->GetValue(key)->IsNumber()) {
867 params = argsPtr->GetValue(key)->GetInt();
868 }
869 return params;
870 }
871
ParseRouteOverwrite(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & key)872 bool ParseRouteOverwrite(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& key)
873 {
874 std::string argStr = arg->ToString(runtime);
875
876 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(argStr);
877 if (argsPtr != nullptr && argsPtr->Contains(key)) {
878 return true;
879 }
880 return false;
881 }
882
AddListener(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)883 void AddListener(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
884 {
885 if (arg->IsObject(runtime) && arg->IsArray(runtime)) {
886 int32_t len = arg->GetArrayLength(runtime);
887 if (len == 0) {
888 return;
889 }
890 std::string listenerId = arg->GetElement(runtime, 0)->ToString(runtime);
891 auto mediaQuery = GetFrontendDelegate(runtime)->GetMediaQueryInfoInstance();
892 if (mediaQuery && !listenerId.empty()) {
893 mediaQuery->SetListenerId(listenerId);
894 }
895 }
896 }
897
ShowToast(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)898 void ShowToast(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
899 {
900 std::string argStr = arg->ToString(runtime);
901
902 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(argStr);
903 std::string message;
904 int32_t duration = 0;
905 std::string bottom;
906 if (argsPtr != nullptr) {
907 if (argsPtr->GetValue(PROMPT_KEY_MESSAGE) != nullptr) {
908 if (argsPtr->GetValue(PROMPT_KEY_MESSAGE)->IsString()) {
909 message = argsPtr->GetValue(PROMPT_KEY_MESSAGE)->GetString();
910 } else {
911 message = argsPtr->GetValue(PROMPT_KEY_MESSAGE)->ToString();
912 }
913 }
914 if (argsPtr->GetValue(PROMPT_KEY_DURATION) != nullptr && argsPtr->GetValue(PROMPT_KEY_DURATION)->IsNumber()) {
915 duration = argsPtr->GetValue(PROMPT_KEY_DURATION)->GetInt();
916 }
917 if (argsPtr->GetValue(PROMPT_KEY_BOTTOM) != nullptr) {
918 if (argsPtr->GetValue(PROMPT_KEY_BOTTOM)->IsString()) {
919 bottom = argsPtr->GetValue(PROMPT_KEY_BOTTOM)->GetString();
920 } else if (argsPtr->GetValue(PROMPT_KEY_BOTTOM)->IsNumber()) {
921 bottom = std::to_string(argsPtr->GetValue(PROMPT_KEY_BOTTOM)->GetInt());
922 }
923 }
924 }
925
926 GetFrontendDelegate(runtime)->ShowToast(message, duration, bottom, NG::ToastShowMode::DEFAULT);
927 }
928
ParseDialogButtons(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & key)929 std::vector<ButtonInfo> ParseDialogButtons(
930 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& key)
931 {
932 std::vector<ButtonInfo> dialogButtons;
933 std::string argStr = arg->ToString(runtime);
934 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(argStr);
935 if (argsPtr != nullptr && argsPtr->GetValue(key) != nullptr && argsPtr->GetValue(key)->IsArray()) {
936 for (int32_t i = 0; i < argsPtr->GetValue(key)->GetArraySize(); ++i) {
937 auto button = argsPtr->GetValue(key)->GetArrayItem(i);
938 ButtonInfo buttonInfo;
939 if (button->GetValue("text")) {
940 buttonInfo.text = button->GetValue("text")->GetString();
941 }
942 if (button->GetValue("color")) {
943 buttonInfo.textColor = button->GetValue("color")->GetString();
944 }
945 dialogButtons.emplace_back(buttonInfo);
946 }
947 }
948 return dialogButtons;
949 }
950
ShowDialog(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)951 void ShowDialog(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
952 {
953 const std::string title = ParseRouteUrl(runtime, arg, PROMPT_KEY_TITLE);
954 const std::string message = ParseRouteUrl(runtime, arg, PROMPT_KEY_MESSAGE);
955 std::vector<ButtonInfo> buttons = ParseDialogButtons(runtime, arg, PROMPT_KEY_BUTTONS);
956 const std::string success = ParseRouteUrl(runtime, arg, COMMON_SUCCESS);
957 const std::string cancel = ParseRouteUrl(runtime, arg, COMMON_CANCEL);
958 const std::string complete = ParseRouteUrl(runtime, arg, COMMON_COMPLETE);
959 bool autoCancel = true;
960
961 std::string argsStr = arg->ToString(runtime);
962 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(argsStr);
963 if (argsPtr != nullptr && argsPtr->GetValue(PROMPT_DIALOG_AUTO_CANCEL) != nullptr &&
964 argsPtr->GetValue(PROMPT_DIALOG_AUTO_CANCEL)->IsBool()) {
965 autoCancel = argsPtr->GetValue(PROMPT_DIALOG_AUTO_CANCEL)->GetBool();
966 }
967
968 std::set<std::string> callbacks;
969 if (!success.empty()) {
970 callbacks.emplace(COMMON_SUCCESS);
971 }
972 if (!cancel.empty()) {
973 callbacks.emplace(COMMON_CANCEL);
974 }
975 if (!complete.empty()) {
976 callbacks.emplace(COMMON_COMPLETE);
977 }
978
979 auto engineInstance = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
980 auto callback = [engineInstance, success, cancel, complete](int32_t callbackType, int32_t successType) {
981 switch (callbackType) {
982 case 0:
983 engineInstance->CallJs(
984 success, std::string("{\"index\":").append(std::to_string(successType)).append("}"), false);
985 break;
986 case 1:
987 engineInstance->CallJs(cancel, std::string("\"cancel\",null"), false);
988 break;
989 case 2:
990 engineInstance->CallJs(complete, std::string("\"complete\",null"), false);
991 break;
992 default:
993 break;
994 }
995 };
996
997 GetFrontendDelegate(runtime)->ShowDialog(title, message, buttons, autoCancel, std::move(callback), callbacks);
998 }
999
SetTimer(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,bool isInterval)1000 void SetTimer(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, bool isInterval)
1001 {
1002 if (arg->IsArray(runtime)) {
1003 int32_t len = arg->GetArrayLength(runtime);
1004 if (len < 2) {
1005 LOGW("SetTimer: invalid callback value");
1006 return;
1007 }
1008 std::string callBackId = arg->GetElement(runtime, 0)->ToString(runtime);
1009 std::string delay = arg->GetElement(runtime, 1)->ToString(runtime);
1010 if (!callBackId.empty() && !delay.empty()) {
1011 GetFrontendDelegate(runtime)->WaitTimer(callBackId, delay, isInterval, true);
1012 }
1013 }
1014 }
1015
ClearTimeout(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)1016 void ClearTimeout(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
1017 {
1018 if (arg->IsArray(runtime)) {
1019 int32_t len = arg->GetArrayLength(runtime);
1020 if (len < 1) {
1021 LOGW("ClearTimeout: invalid callback value");
1022 return;
1023 }
1024 std::string callBackId = arg->GetElement(runtime, 0)->ToString(runtime);
1025 if (!callBackId.empty()) {
1026 GetFrontendDelegate(runtime)->ClearTimer(callBackId);
1027 }
1028 }
1029 }
1030
JsHandleAnimationFrame(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & methodName)1031 shared_ptr<JsValue> JsHandleAnimationFrame(
1032 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& methodName)
1033 {
1034 std::string callbackId = arg->ToString(runtime);
1035 if (callbackId.empty()) {
1036 LOGW("system animation callbackId is null");
1037 return runtime->NewNull();
1038 }
1039
1040 if (methodName == ANIMATION_REQUEST_ANIMATION_FRAME) {
1041 GetFrontendDelegate(runtime)->RequestAnimationFrame(callbackId);
1042 } else if (methodName == ANIMATION_CANCEL_ANIMATION_FRAME) {
1043 GetFrontendDelegate(runtime)->CancelAnimationFrame(callbackId);
1044 } else {
1045 LOGW("animationFrame not support method = %{private}s", methodName.c_str());
1046 }
1047 return runtime->NewNull();
1048 }
1049
JsHandleCallback(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & methodName)1050 shared_ptr<JsValue> JsHandleCallback(
1051 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& methodName)
1052 {
1053 if (methodName == CALLBACK_NATIVE) {
1054 if (arg->IsObject(runtime) && arg->IsArray(runtime)) {
1055 shared_ptr<JsValue> callbackId = arg->GetProperty(runtime, 0);
1056 shared_ptr<JsValue> result = arg->GetProperty(runtime, 1);
1057 std::string callbackIdStr = callbackId->ToString(runtime);
1058 std::string resultStr = result->ToString(runtime);
1059
1060 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(resultStr);
1061 if (argsPtr && argsPtr->GetValue(KEY_STEPPER_PENDING_INDEX) != nullptr) {
1062 auto jsonValue = argsPtr->GetValue(KEY_STEPPER_PENDING_INDEX);
1063 if (jsonValue->IsString()) {
1064 resultStr = jsonValue->GetString();
1065 } else if (jsonValue->IsNumber()) {
1066 resultStr = jsonValue->ToString();
1067 }
1068 }
1069 GetFrontendDelegate(runtime)->SetCallBackResult(callbackIdStr, resultStr);
1070 }
1071 } else if (methodName == APP_DESTROY_FINISH) {
1072 } else {
1073 LOGW("internal.jsResult not support method = %{private}s", methodName.c_str());
1074 }
1075
1076 return runtime->NewNull();
1077 }
1078
JsHandleAppApi(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & methodName)1079 shared_ptr<JsValue> JsHandleAppApi(
1080 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& methodName)
1081 {
1082 if (methodName == APP_GET_INFO) {
1083 return GetAppInfo(runtime);
1084 } else if (methodName == APP_TERMINATE) {
1085 Terminate(runtime);
1086 } else if (methodName == APP_GET_PACKAGE_INFO) {
1087 GetPackageInfo(runtime, arg);
1088 } else if (methodName == APP_REQUEST_FULL_WINDOW) {
1089 RequestFullWindow(runtime, arg);
1090 } else if (methodName == APP_SCREEN_ON_VISIBLE) {
1091 SetScreenOnVisible(runtime, arg);
1092 } else {
1093 LOGW("system.app not support method = %{private}s", methodName.c_str());
1094 }
1095 return runtime->NewNull();
1096 }
1097
JsParseRouteUrl(const std::unique_ptr<JsonValue> & argsPtr,const std::string & key)1098 std::string JsParseRouteUrl(const std::unique_ptr<JsonValue>& argsPtr, const std::string& key)
1099 {
1100 std::string pageRoute;
1101 if (argsPtr != nullptr && argsPtr->GetValue(key) != nullptr && argsPtr->GetValue(key)->IsString()) {
1102 pageRoute = argsPtr->GetValue(key)->GetString();
1103 }
1104 return pageRoute;
1105 }
1106
GetParams(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,std::map<std::string,std::string> & params)1107 bool GetParams(
1108 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, std::map<std::string, std::string>& params)
1109 {
1110 if (!runtime) {
1111 LOGE("fail to get params due to runtime is illegal");
1112 return false;
1113 }
1114 int32_t len = 0;
1115 shared_ptr<JsValue> properties;
1116 if (!arg->GetPropertyNames(runtime, properties, len)) {
1117 LOGE("GetParams fail to get object property list!");
1118 return false;
1119 }
1120 for (int32_t i = 0; i < len; ++i) {
1121 shared_ptr<JsValue> key = properties->GetElement(runtime, i);
1122 shared_ptr<JsValue> val = arg->GetProperty(runtime, key);
1123 std::string keyStr = key->ToString(runtime);
1124 std::string valStr = val->ToString(runtime);
1125 params[keyStr] = valStr;
1126 }
1127 return true;
1128 }
1129
GetParamsWithCallbackId(const shared_ptr<JsRuntime> & runtime,const std::vector<shared_ptr<JsValue>> & argv,std::map<std::string,std::string> & params,std::string & callbackId)1130 bool GetParamsWithCallbackId(const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1131 std::map<std::string, std::string>& params, std::string& callbackId)
1132 {
1133 if (!runtime) {
1134 LOGE("fail to get params due to runtime is illegal");
1135 return false;
1136 }
1137 if (argv.size() < 2) {
1138 LOGE("fail to get params due to length is illegal");
1139 return false;
1140 }
1141 if (!GetParams(runtime, argv[0], params)) {
1142 return false;
1143 }
1144 if (!argv[1]->IsString(runtime)) {
1145 return false;
1146 }
1147 callbackId = argv[1]->ToString(runtime);
1148 return true;
1149 }
1150
ParseResourceStringParam(const char * paramName,const std::map<std::string,std::string> & params,std::string & str)1151 bool ParseResourceStringParam(const char* paramName, const std::map<std::string, std::string>& params, std::string& str)
1152 {
1153 std::string strName(paramName);
1154 auto iter = params.find(strName);
1155 if (iter != params.end()) {
1156 str = iter->second;
1157 return true;
1158 }
1159 return false;
1160 }
1161
ParseResourceNumberParam(const char * paramName,const std::map<std::string,std::string> & params,int32_t & num)1162 bool ParseResourceNumberParam(const char* paramName, const std::map<std::string, std::string>& params, int32_t& num)
1163 {
1164 std::string numName(paramName);
1165 auto iter = params.find(numName);
1166 if (iter != params.end()) {
1167 num = ParseResourceInputNumberParam(iter->second);
1168 return true;
1169 }
1170 return false;
1171 }
1172
ParseResourceParam(const std::map<std::string,std::string> & params,std::string & uri,int32_t & position,int32_t & length)1173 void ParseResourceParam(
1174 const std::map<std::string, std::string>& params, std::string& uri, int32_t& position, int32_t& length)
1175 {
1176 ParseResourceStringParam(READ_KEY_URI, params, uri);
1177 ParseResourceNumberParam(READ_KEY_POSITION, params, position);
1178 ParseResourceNumberParam(READ_KEY_LENGTH, params, length);
1179 }
1180
JsReadText(const shared_ptr<JsRuntime> & runtime,const std::vector<shared_ptr<JsValue>> & argv)1181 shared_ptr<JsValue> JsReadText(const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv)
1182 {
1183 if (!runtime) {
1184 LOGE("JsReadText failed. runtime is null.");
1185 return nullptr;
1186 }
1187 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1188 if (!engine) {
1189 LOGE("JsReadText failed. engine is null.");
1190 return runtime->NewUndefined();
1191 }
1192 std::map<std::string, std::string> params;
1193 std::string callbackId;
1194 if (!GetParamsWithCallbackId(runtime, argv, params, callbackId)) {
1195 LOGE("JsReadText, get params or callbackId failed!");
1196 return runtime->NewUndefined();
1197 }
1198 std::string uri;
1199 ParseResourceStringParam(READ_KEY_URI, params, uri);
1200 std::smatch result;
1201 if (!std::regex_match(uri, result, URI_PATTERN)) {
1202 LOGE("JsReadText uri regex match failed");
1203 engine->CallJs(callbackId, R"({"arguments":["file uri pattern not correct", 202],"method":"fail"})");
1204 return runtime->NewUndefined();
1205 }
1206
1207 std::string fileText;
1208 auto delegate = engine->GetFrontendDelegate();
1209 if (!delegate) {
1210 LOGE("JsReadText failed. delegate is null.");
1211 return runtime->NewUndefined();
1212 }
1213 if (!(delegate->GetResourceData(uri, fileText))) {
1214 LOGE("JsReadText get text data failed");
1215 engine->CallJs(callbackId, R"({"arguments":["get text data failed", 301],"method":"fail"})");
1216 return runtime->NewUndefined();
1217 }
1218
1219 auto fileLength = ParseUtf8TextLength(fileText);
1220 int32_t position = 0;
1221 int32_t length = 0;
1222 if (!ParseResourceNumberParam(READ_KEY_POSITION, params, position)) {
1223 position = 1;
1224 }
1225
1226 if (!ParseResourceNumberParam(READ_KEY_LENGTH, params, length) || (length > fileLength - position + 1)) {
1227 length = (fileLength - position + 1 <= 0) ? 0 : fileLength - position + 1;
1228 }
1229
1230 if (fileLength == 0) {
1231 if ((position <= 0) || (length < 0)) {
1232 engine->CallJs(
1233 callbackId, R"({"arguments":["wrong start position or wrong read length", 202],"method":"fail"})");
1234 return runtime->NewUndefined();
1235 }
1236 } else {
1237 if ((position > fileLength) || (position <= 0) || (length < 0)) {
1238 engine->CallJs(
1239 callbackId, R"({"arguments":["wrong start position or wrong read length", 202],"method":"fail"})");
1240 return runtime->NewUndefined();
1241 }
1242
1243 size_t substrPos = static_cast<size_t>(ParseUtf8TextSubstrStartPos(fileText, position));
1244 size_t substrEndPos = static_cast<size_t>(ParseUtf8TextSubstrEndPos(fileText, position + length - 1));
1245 fileText = fileText.substr(substrPos - 1, substrEndPos - substrPos + 1);
1246 HandleEscapeCharaterInUtf8TextForJson(fileText);
1247 }
1248
1249 engine->CallJs(callbackId,
1250 std::string("{\"arguments\":[").append("{\"text\":\"").append(fileText).append("\"}],\"method\":\"success\"}"));
1251 return runtime->NewUndefined();
1252 }
1253
JsReadArrayBuffer(const shared_ptr<JsRuntime> & runtime,const std::vector<shared_ptr<JsValue>> & argv)1254 shared_ptr<JsValue> JsReadArrayBuffer(
1255 const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv)
1256 {
1257 if (!runtime) {
1258 LOGE("JsReadArrayBuffer failed. runtime is null.");
1259 return nullptr;
1260 }
1261 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1262 if (!engine) {
1263 LOGE("JsReadArrayBuffer failed. engine is null.");
1264 return runtime->NewUndefined();
1265 }
1266 std::map<std::string, std::string> params;
1267 std::string callbackId;
1268 if (!GetParamsWithCallbackId(runtime, argv, params, callbackId)) {
1269 LOGE("JsReadArrayBuffer, get params or callbackId failed!");
1270 return runtime->NewUndefined();
1271 }
1272 std::string uri;
1273 int32_t position = 1;
1274 int32_t length = MAX_READ_TEXT_LENGTH;
1275 ParseResourceParam(params, uri, position, length);
1276 std::smatch result;
1277 if (!std::regex_match(uri, result, URI_PATTERN)) {
1278 LOGE("JsReadArrayBuffer uri regex match failed");
1279 engine->CallJs(callbackId, R"({"arguments":["file uri pattern not correct", 200],"method":"fail"})");
1280 return runtime->NewUndefined();
1281 }
1282
1283 auto delegate = engine->GetFrontendDelegate();
1284 if (!delegate) {
1285 LOGE("JsReadArrayBuffer failed. delegate is null.");
1286 return runtime->NewUndefined();
1287 }
1288 std::vector<uint8_t> binaryContent;
1289 if (!(delegate->GetResourceData(uri, binaryContent))) {
1290 LOGE("JsReadArrayBuffer get buffer data failed");
1291 engine->CallJs(callbackId, R"({"arguments":["get buffer data failed", 301],"method":"fail"})");
1292 return runtime->NewUndefined();
1293 }
1294
1295 auto fileLength = static_cast<int32_t>(binaryContent.size());
1296 if (position > fileLength || position <= 0 || length <= 0) {
1297 LOGE("JsReadArrayBuffer position fileLength failed");
1298 engine->CallJs(
1299 callbackId, R"({"arguments":["wrong start position or wrong read length", 301],"method":"fail"})");
1300 return runtime->NewUndefined();
1301 }
1302
1303 length = position + length - 1 > fileLength ? fileLength - position + 1 : length;
1304 shared_ptr<JsValue> binaryData = runtime->NewObject();
1305 shared_ptr<JsValue> binaryArray = runtime->NewArray();
1306 for (int32_t i = 0; i < length; ++i) {
1307 binaryArray->SetProperty(runtime, runtime->NewInt32(i), runtime->NewInt32(binaryContent[position - 1 + i]));
1308 }
1309 binaryData->SetProperty(runtime, "buffer", binaryArray);
1310 engine->CallJs(callbackId, R"({"arguments":["read array buffer success"],"method":"success"})");
1311 return binaryData;
1312 }
1313
JsHandleReadResource(const shared_ptr<JsRuntime> & runtime,const std::vector<shared_ptr<JsValue>> & argv,const std::string & methodName)1314 shared_ptr<JsValue> JsHandleReadResource(
1315 const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv, const std::string& methodName)
1316 {
1317 if (methodName == READ_TEXT) {
1318 return JsReadText(runtime, argv);
1319 } else if (methodName == READ_ARRAY_BUFFER) {
1320 return JsReadArrayBuffer(runtime, argv);
1321 } else {
1322 LOGW("system.resource not support method = %{private}s", methodName.c_str());
1323 }
1324 return runtime->NewUndefined();
1325 }
1326
JsHandleOffscreenCanvas(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & methodName)1327 shared_ptr<JsValue> JsHandleOffscreenCanvas(
1328 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& methodName)
1329 {
1330 auto page = GetRunningPage(runtime);
1331 if (page == nullptr) {
1332 return runtime->NewUndefined();
1333 }
1334
1335 if (methodName == OFFSCREEN_CANVAS_CREATE) {
1336 int32_t width = ParseIntParams(runtime, arg, "width");
1337 int32_t height = ParseIntParams(runtime, arg, "height");
1338
1339 auto pipelineContext = GetFrontendDelegate(runtime)->GetPipelineContext();
1340 auto bridge = AceType::MakeRefPtr<JsiOffscreenCanvasBridge>(pipelineContext, width, height);
1341 page->PushOffscreenCanvasBridge(bridge->GetBridgeId(), bridge);
1342 return bridge->GetBridge(runtime);
1343 }
1344 return runtime->NewUndefined();
1345 }
1346
JsCallConfiguration(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & methodName)1347 shared_ptr<JsValue> JsCallConfiguration(
1348 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& methodName)
1349 {
1350 if (CONFIGURATION_GET_LOCALE == methodName) {
1351 return GetLocale(runtime);
1352 } else if (CONFIGURATION_SET_LOCALE == methodName) {
1353 SetLocale(runtime, arg);
1354 }
1355 return runtime->NewNull();
1356 }
1357
JsGetDeviceInfo(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)1358 shared_ptr<JsValue> JsGetDeviceInfo(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
1359 {
1360 std::string callbackId = arg->ToString(runtime);
1361 if (callbackId.empty()) {
1362 LOGE("system device getInfo callBackID is null");
1363 } else {
1364 std::string info = GetDeviceInfo();
1365 auto engineInstance = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1366 if (info.find("N/A") != std::string::npos) {
1367 engineInstance->CallJs(
1368 callbackId, std::string("{\"arguments\":[").append(info).append(",200],\"method\":\"fail\"}"), false);
1369 } else {
1370 engineInstance->CallJs(
1371 callbackId, std::string("{\"arguments\":[").append(info).append("],\"method\":\"success\"}"), false);
1372 }
1373 }
1374
1375 return runtime->NewNull();
1376 }
1377
JsHandleImage(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)1378 shared_ptr<JsValue> JsHandleImage(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
1379 {
1380 auto src = ParseRouteUrl(runtime, arg, "src");
1381 auto success = ParseRouteUrl(runtime, arg, "success");
1382 auto fail = ParseRouteUrl(runtime, arg, "fail");
1383
1384 auto engineInstance = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1385 if (!engineInstance) {
1386 return runtime->NewNull();
1387 }
1388
1389 auto&& callback = [engineInstance, success, fail](bool callbackType, int32_t width, int32_t height) {
1390 if (callbackType) {
1391 engineInstance->CallJs(success,
1392 std::string("{\"width\":")
1393 .append(std::to_string(width))
1394 .append(", \"height\":")
1395 .append(std::to_string(height))
1396 .append("}"),
1397 false);
1398 } else {
1399 engineInstance->CallJs(fail, std::string("\"fail\",null"), false);
1400 }
1401 };
1402 engineInstance->GetFrontendDelegate()->HandleImage(src, callback);
1403 return runtime->NewNull();
1404 }
1405
JsHandleGridLayout(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & methodName)1406 shared_ptr<JsValue> JsHandleGridLayout(
1407 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& methodName)
1408 {
1409 if (!runtime) {
1410 LOGE("JsHandleGridLayout failed. runtime is null.");
1411 return nullptr;
1412 }
1413 if (methodName == GRID_GET_SYSTEM_LAYOUT_INFO) {
1414 return runtime->NewString(GridSystemManager::GetInstance().GetCurrentGridInfo().ToString());
1415 } else {
1416 LOGW("grid not support method = %{public}s", methodName.c_str());
1417 return runtime->NewUndefined();
1418 }
1419 }
1420
JsHandleMediaQuery(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & methodName)1421 shared_ptr<JsValue> JsHandleMediaQuery(
1422 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& methodName)
1423 {
1424 if (methodName == ADD_LISTENER) {
1425 AddListener(runtime, arg);
1426 } else if (methodName == GET_DEVICE_TYPE) {
1427 auto engineInstance = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1428 if (engineInstance) {
1429 auto mediaQuery = engineInstance->GetFrontendDelegate()->GetMediaQueryInfoInstance();
1430 if (mediaQuery) {
1431 return runtime->NewString(mediaQuery->GetDeviceType());
1432 }
1433 }
1434 } else {
1435 LOGW("system.mediaquery not support method = %{private}s", methodName.c_str());
1436 }
1437 return runtime->NewNull();
1438 }
1439
JsParseDialogButtons(const std::unique_ptr<JsonValue> & argsPtr,const std::string & key)1440 std::vector<ButtonInfo> JsParseDialogButtons(const std::unique_ptr<JsonValue>& argsPtr, const std::string& key)
1441 {
1442 std::vector<ButtonInfo> dialogButtons;
1443 if (argsPtr != nullptr && argsPtr->GetValue(key) != nullptr && argsPtr->GetValue(key)->IsArray()) {
1444 for (int32_t i = 0; i < argsPtr->GetValue(key)->GetArraySize(); i++) {
1445 auto button = argsPtr->GetValue(key)->GetArrayItem(i);
1446 if (!button->GetValue("text")->IsString()) {
1447 continue;
1448 }
1449 ButtonInfo buttonInfo;
1450 if (button->GetValue("text")) {
1451 buttonInfo.text = button->GetValue("text")->GetString();
1452 }
1453 if (button->GetValue("color")) {
1454 buttonInfo.textColor = button->GetValue("color")->GetString();
1455 }
1456 dialogButtons.emplace_back(buttonInfo);
1457 }
1458 }
1459 return dialogButtons;
1460 }
1461
ShowActionMenu(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)1462 void ShowActionMenu(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
1463 {
1464 if (!runtime) {
1465 LOGE("ShowActionMenu failed. runtime is null.");
1466 return;
1467 }
1468 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1469 if (!engine) {
1470 LOGE("ShowActionMenu failed. engine is null.");
1471 return;
1472 }
1473 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(arg->ToString(runtime));
1474 if (argsPtr == nullptr) {
1475 LOGE("ShowActionMenu failed. argsPtr is nullptr");
1476 return;
1477 }
1478 std::vector<ButtonInfo> buttons = JsParseDialogButtons(argsPtr, PROMPT_KEY_BUTTONS);
1479 if (buttons.empty() || buttons.size() > 6) { // The number of buttons cannot be zero or more than six
1480 LOGE("buttons is invalid");
1481 if (argsPtr->IsObject()) {
1482 const std::string fail = JsParseRouteUrl(argsPtr, COMMON_FAIL);
1483 const std::string complete = JsParseRouteUrl(argsPtr, COMMON_COMPLETE);
1484 engine->CallJs(fail, R"({"errMsg":"enableAlertBeforeBackPage:buttons is invalid"})");
1485 engine->CallJs(complete, R"({"errMsg":"enableAlertBeforeBackPage:buttons is invalid"})");
1486 } else {
1487 std::string callBackStr = arg->ToString(runtime);
1488 // Get callbackId and clear redundant symbols, 2 is available min string length
1489 if (callBackStr.size() > 2 && callBackStr.front() == '\"' && callBackStr.back() == '\"') {
1490 callBackStr = callBackStr.substr(1, callBackStr.size() - 2);
1491 engine->CallJs(callBackStr,
1492 R"({"arguments":[{"errMsg":"enableAlertBeforeBackPage:buttons is invalid"}],"method":"fail"})");
1493 }
1494 }
1495 return;
1496 }
1497
1498 const std::string title = JsParseRouteUrl(argsPtr, PROMPT_KEY_TITLE);
1499 const std::string success = JsParseRouteUrl(argsPtr, COMMON_SUCCESS);
1500 const std::string fail = JsParseRouteUrl(argsPtr, COMMON_FAIL);
1501 const std::string complete = JsParseRouteUrl(argsPtr, COMMON_COMPLETE);
1502 auto callback = [engine, success, fail, complete](int32_t callbackType, int32_t successType) {
1503 switch (callbackType) {
1504 case 0:
1505 engine->CallJs(success, std::string(R"({"errMsg":"showActionMenu:ok","tapIndex":)")
1506 .append(std::to_string(successType))
1507 .append("}")
1508 .c_str());
1509 engine->CallJs(complete, std::string(R"({"errMsg":"showActionMenu:ok","tapIndex":)")
1510 .append(std::to_string(successType))
1511 .append("}")
1512 .c_str());
1513 break;
1514 case 1:
1515 engine->CallJs(fail, R"({"errMsg":"showActionMenu:fail cancel"})");
1516 engine->CallJs(complete, R"({"errMsg":"showActionMenu:fail cancel"})");
1517 break;
1518 default:
1519 LOGE("callbackType is invalid");
1520 break;
1521 }
1522 };
1523 auto delegate = engine->GetFrontendDelegate();
1524 if (!delegate) {
1525 LOGE("ShowActionMenu failed. delegate is null.");
1526 return;
1527 }
1528 delegate->ShowActionMenu(title, buttons, std::move(callback));
1529 }
1530
JsHandlePrompt(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & methodName)1531 shared_ptr<JsValue> JsHandlePrompt(
1532 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& methodName)
1533 {
1534 if (methodName == PROMPT_SHOW_TOAST) {
1535 ShowToast(runtime, arg);
1536 } else if (methodName == PROMPT_SHOW_DIALOG) {
1537 ShowDialog(runtime, arg);
1538 } else if (methodName == PROMPT_SHOW_ACTION_MENU) {
1539 ShowActionMenu(runtime, arg);
1540 } else {
1541 LOGW("system.prompt not support method = %{private}s", methodName.c_str());
1542 }
1543 return runtime->NewNull();
1544 }
1545
EnableAlertBeforeBackPage(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)1546 shared_ptr<JsValue> EnableAlertBeforeBackPage(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
1547 {
1548 if (!runtime) {
1549 LOGE("EnableAlertBeforeBackPage failed. runtime is null.");
1550 return nullptr;
1551 }
1552 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1553 if (!engine) {
1554 LOGE("EnableAlertBeforeBackPage failed. engine is null.");
1555 return runtime->NewUndefined();
1556 }
1557 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(arg->ToString(runtime));
1558 if (argsPtr != nullptr && argsPtr->IsObject()) {
1559 if (argsPtr->GetValue(PROMPT_KEY_MESSAGE) == nullptr || !argsPtr->GetValue(PROMPT_KEY_MESSAGE)->IsString()) {
1560 LOGE("enableAlertBeforeBackPage message is null");
1561 const std::string fail = JsParseRouteUrl(argsPtr, COMMON_FAIL);
1562 const std::string complete = JsParseRouteUrl(argsPtr, COMMON_COMPLETE);
1563 engine->CallJs(fail, R"({"errMsg":"enableAlertBeforeBackPage:massage is null"})");
1564 engine->CallJs(complete, R"({"errMsg":"enableAlertBeforeBackPage:massage is null"})");
1565 return runtime->NewUndefined();
1566 }
1567 } else {
1568 LOGE("enableAlertBeforeBackPage message is null");
1569 std::string callBackStr = arg->ToString(runtime);
1570 // Get callbackId and clear redundant symbols, 2 is available min string length
1571 if (callBackStr.size() > 2 && callBackStr.front() == '\"' && callBackStr.back() == '\"') {
1572 callBackStr = callBackStr.substr(1, callBackStr.size() - 2);
1573 engine->CallJs(callBackStr,
1574 R"({"arguments":[{"errMsg":"enableAlertBeforeBackPage:massage is null"}],"method":"fail"})");
1575 }
1576 return runtime->NewUndefined();
1577 }
1578
1579 const std::string message = JsParseRouteUrl(argsPtr, PROMPT_KEY_MESSAGE);
1580 const std::string success = JsParseRouteUrl(argsPtr, COMMON_SUCCESS);
1581 const std::string fail = JsParseRouteUrl(argsPtr, COMMON_FAIL);
1582 const std::string complete = JsParseRouteUrl(argsPtr, COMMON_COMPLETE);
1583 auto callback = [engine, success, fail, complete](int32_t callbackType) {
1584 switch (callbackType) {
1585 case 1:
1586 engine->CallJs(success, R"({"errMsg":"enableAlertBeforeBackPage:ok"})");
1587 engine->CallJs(complete, R"({"errMsg":"enableAlertBeforeBackPage:ok"})");
1588 break;
1589 case 0:
1590 engine->CallJs(fail, R"({"errMsg":"enableAlertBeforeBackPage:fail cancel"})");
1591 engine->CallJs(complete, R"({"errMsg":"enableAlertBeforeBackPage:fail cancel"})");
1592 break;
1593 default:
1594 LOGE("callbackType is invalid");
1595 break;
1596 }
1597 };
1598 auto delegate = engine->GetFrontendDelegate();
1599 if (!delegate) {
1600 LOGE("EnableAlertBeforeBackPage failed. delegate is null.");
1601 return runtime->NewUndefined();
1602 }
1603 delegate->EnableAlertBeforeBackPage(message, std::move(callback));
1604 return runtime->NewUndefined();
1605 }
1606
DisableAlertBeforeBackPage(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)1607 shared_ptr<JsValue> DisableAlertBeforeBackPage(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
1608 {
1609 if (!runtime) {
1610 LOGE("DisableAlertBeforeBackPage failed. runtime is null.");
1611 return nullptr;
1612 }
1613 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1614 if (!engine) {
1615 LOGE("DisableAlertBeforeBackPage failed. engine is null.");
1616 return runtime->NewUndefined();
1617 }
1618 auto delegate = engine->GetFrontendDelegate();
1619 if (!delegate) {
1620 LOGE("DisableAlertBeforeBackPage failed. delegate is null.");
1621 return runtime->NewUndefined();
1622 }
1623 delegate->DisableAlertBeforeBackPage();
1624 std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(arg->ToString(runtime));
1625 if (argsPtr->IsObject()) {
1626 const std::string success = JsParseRouteUrl(argsPtr, COMMON_SUCCESS);
1627 const std::string complete = JsParseRouteUrl(argsPtr, COMMON_COMPLETE);
1628 engine->CallJs(success, R"({"errMsg":"disableAlertBeforeBackPage:ok"})");
1629 engine->CallJs(complete, R"({"errMsg":"disableAlertBeforeBackPage:ok"})");
1630 return runtime->NewUndefined();
1631 }
1632
1633 std::string callBackStr = arg->ToString(runtime);
1634 // Get callbackId and clear redundant symbols, 2 is available min string length
1635 if (callBackStr.size() > 2 && callBackStr.front() == '\"' && callBackStr.back() == '\"') {
1636 callBackStr = callBackStr.substr(1, callBackStr.size() - 2);
1637 engine->CallJs(callBackStr, R"({"arguments":[{"errMsg":"disableAlertBeforeBackPage:ok"}],"method":"success"})");
1638 }
1639 return runtime->NewUndefined();
1640 }
1641
PostponePageTransition(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)1642 shared_ptr<JsValue> PostponePageTransition(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
1643 {
1644 if (!runtime) {
1645 LOGE("PostponePageTransition failed. runtime is null.");
1646 return nullptr;
1647 }
1648 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1649 if (!engine) {
1650 LOGE("PostponePageTransition failed. engine is null.");
1651 return runtime->NewUndefined();
1652 }
1653 auto delegate = engine->GetFrontendDelegate();
1654 if (!delegate) {
1655 LOGE("PostponePageTransition failed. delegate is null.");
1656 return runtime->NewUndefined();
1657 }
1658 delegate->PostponePageTransition();
1659 return runtime->NewUndefined();
1660 }
1661
LaunchPageTransition(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)1662 shared_ptr<JsValue> LaunchPageTransition(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
1663 {
1664 if (!runtime) {
1665 LOGE("LaunchPageTransition failed. runtime is null.");
1666 return nullptr;
1667 }
1668 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1669 if (!engine) {
1670 LOGE("LaunchPageTransition failed. engine is null.");
1671 return runtime->NewUndefined();
1672 }
1673 auto delegate = engine->GetFrontendDelegate();
1674 if (!delegate) {
1675 LOGE("LaunchPageTransition failed. delegate is null.");
1676 return runtime->NewUndefined();
1677 }
1678 delegate->LaunchPageTransition();
1679 return runtime->NewUndefined();
1680 }
1681
JsHandlePageRoute(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & methodName)1682 shared_ptr<JsValue> JsHandlePageRoute(
1683 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& methodName)
1684 {
1685 std::string uri = "";
1686 if (methodName == ROUTE_PAGE_BACK) {
1687 uri = ParseRouteUrlSpecial(runtime, arg);
1688 } else {
1689 uri = ParseRouteUrl(runtime, arg, ROUTE_KEY_URI);
1690 }
1691 std::string params = ParseRouteParams(runtime, arg, ROUTE_KEY_PARAMS);
1692 bool dontOverwrite = ParseRouteOverwrite(runtime, arg, ROUTE_KEY_DONT_OVERWRITE);
1693
1694 std::unique_ptr<JsonValue> routerParamsData = JsonUtil::Create(true);
1695 routerParamsData->Put("paramsData", JsonUtil::ParseJsonString(params));
1696 routerParamsData->Put("dontOverwrite", dontOverwrite);
1697 params = routerParamsData->ToString();
1698
1699 auto engineInstance = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
1700 if (!engineInstance) {
1701 LOGE("engineInstance is null");
1702 return runtime->NewNull();
1703 }
1704 // Operator map for page route.
1705 static const LinearMapNode<shared_ptr<JsValue> (*)(const std::string&, const std::string&, JsiEngineInstance&)>
1706 pageRouteOperators[] = {
1707 { ROUTE_PAGE_BACK,
1708 [](const std::string& uri, const std::string& params, JsiEngineInstance& instance) {
1709 instance.GetFrontendDelegate()->Back(uri, params);
1710 return instance.GetJsRuntime()->NewNull();
1711 } },
1712 { ROUTE_PAGE_CLEAR,
1713 [](const std::string& uri, const std::string& params, JsiEngineInstance& instance) {
1714 instance.GetFrontendDelegate()->Clear();
1715 return instance.GetJsRuntime()->NewNull();
1716 } },
1717 { ROUTE_PAGE_GET_LENGTH,
1718 [](const std::string& uri, const std::string& params, JsiEngineInstance& instance) {
1719 int32_t routeLength = instance.GetFrontendDelegate()->GetStackSize();
1720 std::string indexLength = std::to_string(routeLength);
1721 return instance.GetJsRuntime()->NewString(indexLength);
1722 } },
1723 { ROUTE_PAGE_GET_STATE,
1724 [](const std::string& uri, const std::string& params, JsiEngineInstance& instance) {
1725 int32_t routeIndex = 0;
1726 std::string routeName;
1727 std::string routePath;
1728 instance.GetFrontendDelegate()->GetState(routeIndex, routeName, routePath);
1729
1730 shared_ptr<JsRuntime> runtime = instance.GetJsRuntime();
1731 shared_ptr<JsValue> routeData = runtime->NewObject();
1732 routeData->SetProperty(runtime, "index", runtime->NewNumber(routeIndex));
1733 routeData->SetProperty(runtime, "name", runtime->NewString(routeName));
1734 routeData->SetProperty(runtime, "path", runtime->NewString(routePath));
1735 return routeData;
1736 } },
1737 { ROUTE_PAGE_PUSH,
1738 [](const std::string& uri, const std::string& params, JsiEngineInstance& instance) {
1739 instance.GetFrontendDelegate()->Push(uri, params);
1740 return instance.GetJsRuntime()->NewNull();
1741 } },
1742 { ROUTE_PAGE_REPLACE,
1743 [](const std::string& uri, const std::string& params, JsiEngineInstance& instance) {
1744 instance.GetFrontendDelegate()->Replace(uri, params);
1745 return instance.GetJsRuntime()->NewNull();
1746 } },
1747 };
1748 auto operatorIter = BinarySearchFindIndex(pageRouteOperators, ArraySize(pageRouteOperators), methodName.c_str());
1749 if (operatorIter != -1) {
1750 return pageRouteOperators[operatorIter].value(uri, params, *engineInstance);
1751 } else if (methodName == ROUTE_ENABLE_ALERT_BEFORE_BACK_PAGE) {
1752 return EnableAlertBeforeBackPage(runtime, arg);
1753 } else if (methodName == ROUTE_DISABLE_ALERT_BEFORE_BACK_PAGE) {
1754 return DisableAlertBeforeBackPage(runtime, arg);
1755 } else if (methodName == ROUTE_POSTPONE) {
1756 return PostponePageTransition(runtime, arg);
1757 } else if (methodName == ROUTE_LAUNCH) {
1758 return LaunchPageTransition(runtime, arg);
1759 } else {
1760 LOGW("system.router not support method = %{private}s", methodName.c_str());
1761 }
1762 return runtime->NewNull();
1763 }
1764
JsHandleSetTimeout(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & methodName)1765 shared_ptr<JsValue> JsHandleSetTimeout(
1766 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& methodName)
1767 {
1768 if (methodName == SET_TIMEOUT) {
1769 SetTimer(runtime, arg, false);
1770 } else if (methodName == CLEAR_TIMEOUT || methodName == CLEAR_INTERVAL) {
1771 ClearTimeout(runtime, arg);
1772 } else if (methodName == SET_INTERVAL) {
1773 SetTimer(runtime, arg, true);
1774 } else {
1775 LOGW("Unsupported method for timer module!");
1776 }
1777 return runtime->NewNull();
1778 }
1779
JsHandleAnimator(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg,const std::string & methodName)1780 shared_ptr<JsValue> JsHandleAnimator(
1781 const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg, const std::string& methodName)
1782 {
1783 if (!runtime) {
1784 LOGE("runtime is nullptr");
1785 return nullptr;
1786 }
1787 if (!arg) {
1788 LOGE("arg is nullptr");
1789 runtime->ThrowError("Parameter error. The number of parameters must be greater than or equal to 1.",
1790 ERROR_CODE_PARAM_INVALID);
1791 return runtime->NewNull();
1792 }
1793 auto page = GetStagingPage(runtime);
1794 if (page == nullptr) {
1795 LOGE("page is nullptr");
1796 return runtime->NewNull();
1797 }
1798 std::string arguments = arg->ToString(runtime);
1799 // argv[1] is "1" when input null.
1800 if (arguments == "\"1\"") {
1801 runtime->ThrowError("Parameter error. The number of parameters must be greater than or equal to 1.",
1802 ERROR_CODE_PARAM_INVALID);
1803 return runtime->NewNull();
1804 }
1805 if (methodName == ANIMATOR_CREATE_ANIMATOR || methodName == ANIMATOR_CREATE) {
1806 int32_t bridgeId = JsiAnimatorBridgeUtils::JsCreateBridgeId();
1807 auto animatorContext = JsiAnimatorBridgeUtils::CreateAnimatorContext(runtime, page->GetPageId(), bridgeId);
1808 auto animatorBridge = AceType::MakeRefPtr<JsiAnimatorBridge>(runtime, animatorContext);
1809 auto task = AceType::MakeRefPtr<JsiAnimatorTaskCreate>(runtime, animatorBridge, arguments);
1810 page->PushCommand(Referenced::MakeRefPtr<JsCommandAnimator>(bridgeId, task));
1811 return animatorContext;
1812 }
1813 return runtime->NewNull();
1814 }
1815
JsHandleModule(const std::string & moduleName,const std::string & methodName,const shared_ptr<JsRuntime> & runtime,const std::vector<shared_ptr<JsValue>> & argv)1816 shared_ptr<JsValue> JsHandleModule(const std::string& moduleName, const std::string& methodName,
1817 const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv)
1818 {
1819 static const LinearMapNode<shared_ptr<JsValue> (*)(
1820 const shared_ptr<JsRuntime>&, const std::vector<shared_ptr<JsValue>>&, const std::string&)>
1821 jsHandleMap[] = {
1822 { "animation",
1823 [](const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1824 const std::string& methodName) { return JsHandleAnimationFrame(runtime, argv[1], methodName); } },
1825 { "internal.jsResult",
1826 [](const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1827 const std::string& methodName) { return JsHandleCallback(runtime, argv[1], methodName); } },
1828 { "ohos.animator",
1829 [](const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1830 const std::string& methodName) { return JsHandleAnimator(runtime, argv[1], methodName); } },
1831 { "system.app",
1832 [](const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1833 const std::string& methodName) { return JsHandleAppApi(runtime, argv[1], methodName); } },
1834 { "system.configuration",
1835 [](const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1836 const std::string& methodName) { return JsCallConfiguration(runtime, argv[1], methodName); } },
1837 { "system.device",
1838 [](const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1839 const std::string& methodName) {
1840 if (methodName == "getInfo") {
1841 return JsGetDeviceInfo(runtime, argv[1]);
1842 } else {
1843 return runtime->NewNull();
1844 }
1845 } },
1846 { "system.grid",
1847 [](const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1848 const std::string& methodName) { return JsHandleGridLayout(runtime, argv[1], methodName); } },
1849 { "system.image", [](const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1850 const std::string& methodName) { return JsHandleImage(runtime, argv[1]); } },
1851 { "system.mediaquery",
1852 [](const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1853 const std::string& methodName) { return JsHandleMediaQuery(runtime, argv[1], methodName); } },
1854 { "system.offscreenCanvas",
1855 [](const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1856 const std::string& methodName) { return JsHandleOffscreenCanvas(runtime, argv[1], methodName); } },
1857 { "system.prompt",
1858 [](const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1859 const std::string& methodName) { return JsHandlePrompt(runtime, argv[1], methodName); } },
1860 { "system.resource",
1861 [](const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1862 const std::string& methodName) { return JsHandleReadResource(runtime, argv, methodName); } },
1863 { "system.router",
1864 [](const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1865 const std::string& methodName) { return JsHandlePageRoute(runtime, argv[1], methodName); } },
1866 { "timer",
1867 [](const shared_ptr<JsRuntime>& runtime, const std::vector<shared_ptr<JsValue>>& argv,
1868 const std::string& methodName) { return JsHandleSetTimeout(runtime, argv[1], methodName); } },
1869 };
1870
1871 auto jsHandleIter = BinarySearchFindIndex(jsHandleMap, ArraySize(jsHandleMap), moduleName.c_str());
1872 if (jsHandleIter != -1) {
1873 return jsHandleMap[jsHandleIter].value(runtime, std::move(argv), methodName);
1874 }
1875 return runtime->NewUndefined();
1876 }
1877
1878 // native implementation for js function: ace.domCreateBody()
JsDomCreateBody(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1879 shared_ptr<JsValue> JsDomCreateBody(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
1880 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1881 {
1882 if (argc != CREATE_BODY_ARGS_LEN) {
1883 LOGE("The arg is wrong, it is supposed to have %{public}d arguments", CREATE_BODY_ARGS_LEN);
1884 return runtime->NewUndefined();
1885 }
1886
1887 auto page = GetStagingPage(runtime);
1888 if (page == nullptr) {
1889 LOGE("GetStagingPage return nullptr");
1890 return runtime->NewUndefined();
1891 }
1892
1893 const int32_t pageId = page->GetPageId();
1894 int32_t nodeId = DOM_ROOT_NODE_ID_BASE + pageId;
1895 std::string tag = argv[CREATE_BODY_TAG_IDX]->ToString(runtime);
1896 auto command = Referenced::MakeRefPtr<JsCommandCreateDomBody>(tag.c_str(), nodeId);
1897 SetDomAttributes(runtime, argv[CREATE_BODY_ATTR_IDX], *command);
1898 SetDomStyle(runtime, argv[CREATE_BODY_STYLE_IDX], *command);
1899 AddDomEvent(runtime, argv[CREATE_BODY_EVENT_IDX], *command);
1900 page->PushCommand(command);
1901 return runtime->NewUndefined();
1902 }
1903
JsDomAddElement(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1904 shared_ptr<JsValue> JsDomAddElement(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
1905 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1906 {
1907 if (argc != ADD_ELEMENT_ARGS_LEN) {
1908 LOGE("The argc is wrong, it is supposed to have %{public}d arguments", ADD_ELEMENT_ARGS_LEN);
1909 return runtime->NewUndefined();
1910 }
1911 auto page = GetStagingPage(runtime);
1912 if (page == nullptr) {
1913 LOGE("GetStagingPage return nullptr");
1914 return runtime->NewUndefined();
1915 }
1916
1917 const int32_t instanceId = argv[ADD_ELEMENT_INSTANCE_ID]->ToInt32(runtime);
1918 if (page->GetPageId() != instanceId) {
1919 page = GetFrontendDelegate(runtime)->GetPage(instanceId);
1920 if (page == nullptr) {
1921 LOGE("JsDomAddElement fail to get page, pageId: %{public}d", instanceId);
1922 return runtime->NewUndefined();
1923 }
1924 }
1925
1926 const int32_t pageId = page->GetPageId();
1927 int32_t parentNodeId = argv[ADD_ELEMENT_PARID_IDX]->ToInt32(runtime);
1928 parentNodeId = parentNodeId == 0 ? (DOM_ROOT_NODE_ID_BASE + pageId) : parentNodeId;
1929
1930 int32_t nodeId = argv[ADD_ELEMENT_NODEID_IDX]->ToInt32(runtime);
1931 std::string tag = argv[ADD_ELEMENT_TAG_IDX]->ToString(runtime);
1932
1933 auto command = Referenced::MakeRefPtr<JsCommandAddDomElement>(tag.c_str(), nodeId, parentNodeId);
1934 SetDomAttributes(runtime, argv[ADD_ELEMENT_ATTR_IDX], *command);
1935 SetDomStyle(runtime, argv[ADD_ELEMENT_STYLE_IDX], *command);
1936 AddDomEvent(runtime, argv[ADD_ELEMENT_EVENT_INDEX], *command);
1937 int32_t itemIndex = argv[ADD_ELEMENT_ITEM_INDEX]->ToInt32(runtime);
1938 if (argv[ADD_ELEMENT_CUSTOM_INDEX]->IsBoolean(runtime)) {
1939 bool isCustomComponent = argv[ADD_ELEMENT_CUSTOM_INDEX]->ToBoolean(runtime);
1940 command->SetIsCustomComponent(isCustomComponent);
1941 }
1942 command->SetForIndex(itemIndex);
1943 page->PushCommand(command);
1944 // Flush command as fragment immediately when pushed too many commands.
1945 if (!page->CheckPageCreated() && page->GetCommandSize() > FRAGMENT_SIZE) {
1946 page->FlushCommands();
1947 }
1948 return runtime->NewNull();
1949 }
1950
1951 // native implementation for js function: ace.removeElement()
JsRemoveElement(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1952 shared_ptr<JsValue> JsRemoveElement(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
1953 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1954 {
1955 if (argc != REMOVE_ELEMENT_ARGS_LEN) {
1956 LOGE("The arg is wrong, it is supposed to have %{public}d arguments", REMOVE_ELEMENT_ARGS_LEN);
1957 return runtime->NewUndefined();
1958 }
1959
1960 auto page = GetStagingPage(runtime);
1961 if (page == nullptr) {
1962 LOGE("GetStagingPage return nullptr");
1963 return runtime->NewUndefined();
1964 }
1965
1966 const int32_t instanceId = argv[REMOVE_ELEMENT_INSTANCE_ID]->ToInt32(runtime);
1967 if (page->GetPageId() != instanceId) {
1968 page = GetFrontendDelegate(runtime)->GetPage(instanceId);
1969 if (page == nullptr) {
1970 LOGE("JsRemoveElement fail to get page, pageId: %{public}d", instanceId);
1971 return runtime->NewUndefined();
1972 }
1973 }
1974
1975 int32_t nodeId = argv[REMOVE_ELEMENT_ID_IDX]->ToInt32(runtime);
1976 nodeId = (nodeId == 0) ? DOM_ROOT_NODE_ID_BASE + page->GetPageId() : nodeId;
1977 page->PushCommand(Referenced::MakeRefPtr<JsCommandRemoveDomElement>(nodeId));
1978 return runtime->NewUndefined();
1979 }
1980
1981 // native implementation for js function: ace.updateElementAttrs()
JsUpdateElementAttrs(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)1982 shared_ptr<JsValue> JsUpdateElementAttrs(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
1983 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
1984 {
1985 if (argc != UPLOAD_ELEMENT_ARGS_LEN) {
1986 LOGE("The arg is wrong, it is supposed to have %{public}d arguments", UPLOAD_ELEMENT_ARGS_LEN);
1987 return runtime->NewUndefined();
1988 }
1989
1990 auto page = GetStagingPage(runtime);
1991 if (page == nullptr) {
1992 LOGE("GetStagingPage return nullptr");
1993 return runtime->NewUndefined();
1994 }
1995
1996 const int32_t instanceId = argv[UPLOAD_ELEMENT_INSTANCE_ID]->ToInt32(runtime);
1997 if (page->GetPageId() != instanceId) {
1998 page = GetFrontendDelegate(runtime)->GetPage(instanceId);
1999 if (page == nullptr) {
2000 LOGE("JsRemoveElement fail to get page, pageId: %{public}d", instanceId);
2001 return runtime->NewUndefined();
2002 }
2003 }
2004
2005 int32_t nodeId = argv[UPLOAD_ELEMENT_NID_IDX]->ToInt32(runtime);
2006 nodeId = (nodeId == 0) ? DOM_ROOT_NODE_ID_BASE + page->GetPageId() : nodeId;
2007 auto command = Referenced::MakeRefPtr<JsCommandUpdateDomElementAttrs>(nodeId);
2008 if (SetDomAttributes(runtime, argv[UPLOAD_ELEMENT_DOM_IDX], *command)) {
2009 page->ReserveShowCommand(command);
2010 }
2011 page->PushCommand(command);
2012 return runtime->NewUndefined();
2013 }
2014
2015 // native implementation for js function: ace.updateElementStyles()
JsUpdateElementStyles(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2016 shared_ptr<JsValue> JsUpdateElementStyles(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2017 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2018 {
2019 if (argc != UPLOAD_ELEMENT_ARGS_LEN) {
2020 LOGE("The arg is wrong, it is supposed to have %{public}d arguments", UPLOAD_ELEMENT_ARGS_LEN);
2021 return runtime->NewUndefined();
2022 }
2023
2024 auto page = GetStagingPage(runtime);
2025 if (page == nullptr) {
2026 LOGE("GetStagingPage return nullptr");
2027 return runtime->NewUndefined();
2028 }
2029
2030 const int32_t instanceId = argv[UPLOAD_ELEMENT_INSTANCE_ID]->ToInt32(runtime);
2031 if (page->GetPageId() != instanceId) {
2032 page = GetFrontendDelegate(runtime)->GetPage(instanceId);
2033 if (page == nullptr) {
2034 LOGE("JsRemoveElement fail to get page, pageId: %{public}d", instanceId);
2035 return runtime->NewUndefined();
2036 }
2037 }
2038
2039 int32_t nodeId = argv[UPLOAD_ELEMENT_NID_IDX]->ToInt32(runtime);
2040 nodeId = (nodeId == 0) ? DOM_ROOT_NODE_ID_BASE + page->GetPageId() : nodeId;
2041 auto command = Referenced::MakeRefPtr<JsCommandUpdateDomElementStyles>(nodeId);
2042 SetDomStyle(runtime, argv[UPLOAD_ELEMENT_DOM_IDX], *command);
2043 page->PushCommand(command);
2044 return runtime->NewUndefined();
2045 }
2046
2047 // native implementation for js function: ace.onCreateFinish()
JsOnCreateFinish(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2048 shared_ptr<JsValue> JsOnCreateFinish(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2049 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2050 {
2051 auto page = GetStagingPage(runtime);
2052 if (page == nullptr) {
2053 LOGE("GetStagingPage return nullptr");
2054 return runtime->NewUndefined();
2055 }
2056
2057 page->SetPageCreated();
2058 return runtime->NewUndefined();
2059 }
2060
2061 // native implementation for js function: ace.onUpdateFinish()
JsOnUpdateFinish(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2062 shared_ptr<JsValue> JsOnUpdateFinish(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2063 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2064 {
2065 auto page = GetStagingPage(runtime);
2066 if (page == nullptr) {
2067 LOGE("GetStagingPage return nullptr");
2068 return runtime->NewUndefined();
2069 }
2070
2071 if (page->CheckPageCreated()) {
2072 GetFrontendDelegate(runtime)->TriggerPageUpdate(page->GetPageId());
2073 }
2074 return runtime->NewUndefined();
2075 }
2076
2077 // native implementation for js function: ace.callNative()
JsCallNative(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2078 shared_ptr<JsValue> JsCallNative(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2079 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2080 {
2081 if (argc != NATIVE_ARGS_LEN) {
2082 LOGE("The arg is wrong, it is supposed to have %{public}d arguments", NATIVE_ARGS_LEN);
2083 return runtime->NewUndefined();
2084 }
2085
2086 std::string moduleAndMethod = argv[NATIVE_ARGS_METHOD_IDX]->ToString(runtime);
2087
2088 std::unique_ptr<JsonValue> moduleAndMethodPtr = JsonUtil::ParseJsonString(moduleAndMethod);
2089 if (!moduleAndMethodPtr) {
2090 LOGE("Get moduleAndMethod from argv failed");
2091 return runtime->NewUndefined();
2092 }
2093
2094 std::unique_ptr<JsonValue> modulePtr = moduleAndMethodPtr->GetValue("module");
2095 if (!modulePtr) {
2096 LOGE("Get module from moduleAndMethodPtr failed");
2097 return runtime->NewUndefined();
2098 }
2099
2100 std::unique_ptr<JsonValue> methodPtr = moduleAndMethodPtr->GetValue("method");
2101 if (!methodPtr) {
2102 LOGE("Get method from moduleAndMethodPtr failed");
2103 return runtime->NewUndefined();
2104 }
2105
2106 const std::string moduleName = modulePtr->GetString();
2107 const std::string methodName = methodPtr->GetString();
2108
2109 return JsHandleModule(moduleName, methodName, runtime, argv);
2110 }
2111
2112 // native implementation for js function: ace.callComponent()
JsCallComponent(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2113 shared_ptr<JsValue> JsCallComponent(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2114 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2115 {
2116 if (argc != COMPONENT_ARGS_LEN) {
2117 LOGE("The arg is wrong, it is supposed to have %{public}d arguments", COMPONENT_ARGS_LEN);
2118 return runtime->NewUndefined();
2119 }
2120
2121 auto page = GetRunningPage(runtime);
2122 if (page == nullptr) {
2123 return runtime->NewUndefined();
2124 }
2125 int32_t nodeId = argv[COMPONENT_ARGS_ID_IDX]->ToInt32(runtime);
2126 nodeId = (nodeId == 0) ? DOM_ROOT_NODE_ID_BASE + page->GetPageId() : nodeId;
2127 std::string methodName = argv[COMPONENT_ARGS_METHOD_IDX]->ToString(runtime);
2128 std::string arguments = argv[COMPONENT_ARGS_IDX]->ToString(runtime);
2129
2130 if (std::strcmp(methodName.c_str(), "getContext") == 0) {
2131 auto canvasBridge = AceType::DynamicCast<JsiCanvasBridge>(page->GetBridgeById(nodeId));
2132 if (canvasBridge) {
2133 canvasBridge->HandleJsContext(runtime, nodeId, arguments);
2134 return canvasBridge->GetRenderContext();
2135 }
2136 return runtime->NewUndefined();
2137 } else if (std::strcmp(methodName.c_str(), "toDataURL") == 0) {
2138 auto bridge = AceType::DynamicCast<JsiCanvasBridge>(page->GetBridgeById(nodeId));
2139 if (bridge) {
2140 bridge->HandleToDataURL(runtime, nodeId, arguments);
2141 return bridge->GetDataURL();
2142 }
2143 } else if (std::strcmp(methodName.c_str(), "getBoundingClientRect") == 0) {
2144 return JsiComponentApiBridge::JsGetBoundingRect(runtime, nodeId);
2145 } else if (std::strcmp(methodName.c_str(), "getInspector") == 0) {
2146 return JsiComponentApiBridge::JsGetInspector(runtime, nodeId);
2147 } else if (std::strcmp(methodName.c_str(), "getScrollOffset") == 0) {
2148 return JsiComponentApiBridge::JsGetScrollOffset(runtime, nodeId);
2149 } else if (std::strcmp(methodName.c_str(), "scrollTo") == 0) {
2150 JsiComponentApiBridge::JsScrollTo(runtime, arguments, nodeId);
2151 return runtime->NewUndefined();
2152 } else if (std::strcmp(methodName.c_str(), "getXComponentContext") == 0) {
2153 #ifdef XCOMPONENT_SUPPORTED
2154 auto bridge = AceType::DynamicCast<JsiXComponentBridge>(page->GetXComponentBridgeById(nodeId));
2155 if (bridge) {
2156 bridge->HandleContext(runtime, nodeId, arguments);
2157 return bridge->GetRenderContext();
2158 }
2159 return runtime->NewUndefined();
2160 } else if (std::strcmp(methodName.c_str(), "getXComponentSurfaceId") == 0) {
2161 return JsiXComponentBridge::JsGetXComponentSurfaceId(runtime, nodeId);
2162 } else if (std::strcmp(methodName.c_str(), "setXComponentSurfaceSize") == 0) {
2163 JsiXComponentBridge::JsSetXComponentSurfaceSize(runtime, arguments, nodeId);
2164 return runtime->NewUndefined();
2165 #endif
2166 }
2167
2168 shared_ptr<JsValue> resultValue = runtime->NewUndefined();
2169 if (std::strcmp(methodName.c_str(), "animate") == 0) {
2170 resultValue = JsiAnimationBridgeUtils::CreateAnimationContext(runtime, page->GetPageId(), nodeId);
2171 auto animationBridge = AceType::MakeRefPtr<JsiAnimationBridge>(runtime, resultValue, nodeId);
2172 auto task = AceType::MakeRefPtr<JsiAnimationBridgeTaskCreate>(runtime, animationBridge, arguments);
2173 page->PushCommand(Referenced::MakeRefPtr<JsCommandAnimation>(nodeId, task));
2174 } else if (std::strcmp(methodName.c_str(), "currentOffset") == 0) {
2175 return JsiListBridge::JsGetCurrentOffset(runtime, nodeId);
2176 } else if (std::strcmp(methodName.c_str(), "getState") == 0) {
2177 return JsiImageAnimatorBridge::JsGetState(runtime, nodeId);
2178 } else if (std::strcmp(methodName.c_str(), "addChild") == 0) {
2179 auto sPage = GetStagingPage(runtime);
2180 if (sPage == nullptr) {
2181 return runtime->NewUndefined();
2182 }
2183 int32_t childNodeId = 0;
2184 std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(arguments);
2185 if (argsValue && argsValue->IsArray()) {
2186 std::unique_ptr<JsonValue> cNodeId = argsValue->GetArrayItem(0)->GetValue("__nodeId");
2187 if (cNodeId && cNodeId->IsNumber()) {
2188 childNodeId = cNodeId->GetInt();
2189 }
2190 }
2191 auto domDocument = sPage->GetDomDocument();
2192 if (domDocument) {
2193 RefPtr<DOMNode> node = domDocument->GetDOMNodeById(childNodeId);
2194 if (node == nullptr) {
2195 LOGE("node is nullptr");
2196 }
2197 auto command = Referenced::MakeRefPtr<JsCommandAppendElement>(node ? node->GetTag() : "", childNodeId,
2198 nodeId);
2199 sPage->PushCommand(command);
2200 if (!sPage->CheckPageCreated() && sPage->GetCommandSize() > FRAGMENT_SIZE) {
2201 sPage->FlushCommands();
2202 }
2203 }
2204 return runtime->NewUndefined();
2205 } else {
2206 page->PushCommand(Referenced::MakeRefPtr<JsCommandCallDomElementMethod>(nodeId, methodName, arguments));
2207 }
2208 // focus method should delayed util show attribute update.
2209 if (page->CheckPageCreated() && strlen(DOM_FOCUS) >= strlen(methodName.c_str()) &&
2210 strcmp(DOM_FOCUS, methodName.c_str()) != 0) {
2211 GetFrontendDelegate(runtime)->TriggerPageUpdate(page->GetPageId(), true);
2212 }
2213 return resultValue;
2214 }
2215
GetNodeId(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & arg)2216 int GetNodeId(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& arg)
2217 {
2218 int32_t id = 0;
2219 auto nodeId = arg->GetProperty(runtime, "__nodeId");
2220 if (nodeId && nodeId->IsInt32(runtime)) {
2221 id = nodeId->ToInt32(runtime);
2222 }
2223 id = id < 0 ? 0 : id;
2224 return id;
2225 }
2226
AppClearData(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2227 std::shared_ptr<JsValue> AppClearData(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2228 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2229 {
2230 if (!clipboard) {
2231 auto pipelineContext = GetFrontendDelegate(runtime)->GetPipelineContext();
2232 clipboard = ClipboardProxy::GetInstance()->GetClipboard(pipelineContext->GetTaskExecutor());
2233 }
2234 auto page = GetStagingPage(runtime);
2235 if (page == nullptr) {
2236 LOGE("page is nullptr");
2237 return runtime->NewUndefined();
2238 }
2239 if (argv.empty() || argc == 0) {
2240 if (JsiEngineInstance::dataMap_.size() > 0) {
2241 JsiEngineInstance::dataMap_.clear();
2242 clipboard->SetData("");
2243 return runtime->NewBoolean(true);
2244 }
2245 }
2246 if (JsiEngineInstance::dataMap_.count(argv[0]->ToString(runtime)) == 1) {
2247 JsiEngineInstance::dataMap_.erase(argv[0]->ToString(runtime));
2248 std::string strResult;
2249 strResult.append("{");
2250 std::map<const std::string, std::string>::iterator iter = JsiEngineInstance::dataMap_.begin();
2251 while (iter != JsiEngineInstance::dataMap_.end()) {
2252 std::string key = iter->first;
2253 std::string val = iter->second;
2254 strResult.append("\"")
2255 .append(key)
2256 .append("\":")
2257 .append(val);
2258 ++iter;
2259 if (iter != JsiEngineInstance::dataMap_.end()) {
2260 strResult.append(",");
2261 }
2262 }
2263 strResult.append("}");
2264 clipboard->SetData(strResult);
2265 return runtime->NewBoolean(true);
2266 }
2267 return runtime->NewBoolean(false);
2268 }
2269
AppSetData(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2270 shared_ptr<JsValue> AppSetData(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2271 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2272 {
2273 if (!clipboard) {
2274 auto pipelineContext = GetFrontendDelegate(runtime)->GetPipelineContext();
2275 clipboard = ClipboardProxy::GetInstance()->GetClipboard(pipelineContext->GetTaskExecutor());
2276 }
2277 auto page = GetStagingPage(runtime);
2278 if (page == nullptr) {
2279 LOGE("page is nullptr");
2280 return runtime->NewUndefined();
2281 }
2282 if (argv.empty() || argc != 2) {
2283 return runtime->NewBoolean(false);
2284 }
2285 JsiEngineInstance::dataMap_[argv[0]->ToString(runtime)] = argv[1]->GetJsonString(runtime);
2286
2287 std::string strResult;
2288 strResult.append("{");
2289 std::map<const std::string, std::string>::iterator iter = JsiEngineInstance::dataMap_.begin();
2290 while (iter != JsiEngineInstance::dataMap_.end()) {
2291 std::string key = iter->first;
2292 std::string val = iter->second;
2293 strResult.append("\"").append(key).append("\":").append(val);
2294 ++iter;
2295 if (iter != JsiEngineInstance::dataMap_.end()) {
2296 strResult.append(",");
2297 }
2298 }
2299 strResult.append("}");
2300 clipboard->SetData(strResult);
2301 return runtime->NewBoolean(true);
2302 }
2303
AppGetData(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2304 shared_ptr<JsValue> AppGetData(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2305 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2306 {
2307 if (!clipboard) {
2308 auto pipelineContext = GetFrontendDelegate(runtime)->GetPipelineContext();
2309 clipboard = ClipboardProxy::GetInstance()->GetClipboard(pipelineContext->GetTaskExecutor());
2310 }
2311 auto page = GetStagingPage(runtime);
2312 if (page == nullptr) {
2313 LOGE("page is nullptr");
2314 return runtime->NewUndefined();
2315 }
2316 if (argv.empty() || argc == 0) {
2317 LOGE("argc = 0");
2318 return runtime->NewBoolean(false);
2319 }
2320 std::string clipData;
2321 std::string* clipDataPtr = &clipData;
2322 std::string key = argv[0]->ToString(runtime);
2323 auto callback = [key, clipDataPtr](const std::string& data) {
2324 auto clipboardObj = JsonUtil::ParseJsonString(data);
2325 auto value = clipboardObj->GetValue(key);
2326 if (value) {
2327 *clipDataPtr = value->ToString();
2328 }
2329 };
2330 clipboard->GetData(callback, true);
2331 return runtime->ParseJson(clipData);
2332 }
2333
AppSetDataImage(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2334 shared_ptr<JsValue> AppSetDataImage(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2335 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2336 {
2337 auto page = GetStagingPage(runtime);
2338 if (page == nullptr) {
2339 LOGE("page is nullptr");
2340 return runtime->NewUndefined();
2341 }
2342 if (argv.empty() || argc != 3) {
2343 return runtime->NewBoolean(false);
2344 }
2345 #if !defined(PREVIEW)
2346 DOMDocument::pixelMap_ = CreatePixelMapFromNapiValue(runtime, argv[0]);
2347 if (argv[1] && argv[1]->IsInt32(runtime)) {
2348 DOMDocument::pixelMapOffsetX_ = argv[1]->ToInt32(runtime);
2349 }
2350 if (argv[2] && argv[2]->IsInt32(runtime)) {
2351 DOMDocument::pixelMapOffsetY_ = argv[2]->ToInt32(runtime);
2352 }
2353 if (!DOMDocument::pixelMap_) {
2354 return runtime->NewUndefined();
2355 }
2356 #endif
2357 return runtime->NewUndefined();
2358 }
2359
JsSetAttribute(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2360 shared_ptr<JsValue> JsSetAttribute(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2361 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2362 {
2363 if (argc != 2) {
2364 LOGE("the argc is error");
2365 return runtime->NewUndefined();
2366 }
2367 auto page = GetStagingPage(runtime);
2368 if (page == nullptr) {
2369 LOGE("GetStagingPage return nullptr");
2370 return runtime->NewUndefined();
2371 }
2372 if (!argv[0]->IsString(runtime) || !argv[1]->IsString(runtime)) {
2373 LOGE("args is not string ");
2374 return runtime->NewUndefined();
2375 }
2376 shared_ptr<JsValue> attr = runtime->NewObject();
2377 attr->SetProperty(runtime, argv[0], argv[1]);
2378
2379 int32_t nodeId = GetNodeId(runtime, thisObj);
2380 auto command = Referenced::MakeRefPtr<JsCommandUpdateDomElementAttrs>(nodeId);
2381 if (SetDomAttributes(runtime, attr, *command)) {
2382 page->ReserveShowCommand(command);
2383 }
2384 page->PushCommand(command);
2385 return runtime->NewUndefined();
2386 }
2387
JsSetStyle(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2388 shared_ptr<JsValue> JsSetStyle(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2389 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2390 {
2391 if (argc != 2) {
2392 LOGE("the argc is error");
2393 return runtime->NewBoolean(false);
2394 }
2395 auto page = GetStagingPage(runtime);
2396 if (page == nullptr) {
2397 LOGE("GetStagingPage return nullptr");
2398 return runtime->NewBoolean(false);
2399 }
2400 if (!argv[0]->IsString(runtime) || !argv[1]->IsString(runtime)) {
2401 LOGE("args is not string ");
2402 return runtime->NewBoolean(false);
2403 }
2404 shared_ptr<JsValue> style = runtime->NewObject();
2405 style->SetProperty(runtime, argv[0], argv[1]);
2406
2407 int32_t nodeId = GetNodeId(runtime, thisObj);
2408 auto command = Referenced::MakeRefPtr<JsCommandUpdateDomElementStyles>(nodeId);
2409 SetDomStyle(runtime, style, *command);
2410 page->PushCommand(command);
2411 return runtime->NewBoolean(true);
2412 }
2413
JsAppendChild(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2414 shared_ptr<JsValue> JsAppendChild(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2415 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2416 {
2417 auto page = GetStagingPage(runtime);
2418 if (page == nullptr) {
2419 LOGE("page is nullptr");
2420 return runtime->NewUndefined();
2421 }
2422 int32_t id = GetNodeId(runtime, argv[0]);
2423 auto domDocument = page->GetDomDocument();
2424 if (domDocument) {
2425 RefPtr<DOMNode> node = domDocument->GetDOMNodeById(id);
2426 if (node == nullptr) {
2427 LOGE("node is nullptr");
2428 }
2429 int32_t parentNodeId = GetNodeId(runtime, thisObj);
2430 RefPtr<DOMNode> parentNode = domDocument->GetDOMNodeById(parentNodeId);
2431 if (parentNode == nullptr) {
2432 LOGE("parentNodeId is nullptr");
2433 }
2434 if (parentNode != nullptr && node != nullptr) {
2435 parentNode->RemoveNode(node);
2436 }
2437 auto command = Referenced::MakeRefPtr<JsCommandAppendElement>(node ? node->GetTag() : "", id, parentNodeId);
2438 page->PushCommand(command);
2439 if (!page->CheckPageCreated() && page->GetCommandSize() > FRAGMENT_SIZE) {
2440 page->FlushCommands();
2441 }
2442 }
2443 return runtime->NewUndefined();
2444 }
2445
CreateDomElement(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2446 int32_t CreateDomElement(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2447 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2448 {
2449 if (argc != 1) {
2450 LOGE("the argc is error");
2451 return -1;
2452 }
2453 auto page = GetStagingPage(runtime);
2454 if (page == nullptr) {
2455 LOGE("GetStagingPage return nullptr");
2456 return -1;
2457 }
2458 int32_t nodeId = ++globalNodeId;
2459 std::string tag = argv[0]->ToString(runtime);
2460 auto command = Referenced::MakeRefPtr<JsCommandCreateDomElement>(tag.c_str(), nodeId);
2461 page->PushCommand(command);
2462 if (!page->CheckPageCreated() && page->GetCommandSize() > FRAGMENT_SIZE) {
2463 page->FlushCommands();
2464 }
2465 return globalNodeId;
2466 }
2467
JsFocus(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2468 shared_ptr<JsValue> JsFocus(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2469 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2470 {
2471 auto page = GetStagingPage(runtime);
2472 if (page == nullptr) {
2473 LOGE("page is nullptr");
2474 return runtime->NewUndefined();
2475 }
2476 if (page->CheckPageCreated()) {
2477 GetFrontendDelegate(runtime)->TriggerPageUpdate(page->GetPageId(), true);
2478 }
2479 return runtime->NewUndefined();
2480 }
2481
JsAnimate(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2482 shared_ptr<JsValue> JsAnimate(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2483 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2484 {
2485 auto page = GetStagingPage(runtime);
2486 if (page == nullptr) {
2487 LOGE("page is nullptr");
2488 return runtime->NewUndefined();
2489 }
2490 int32_t nodeId = GetNodeId(runtime, thisObj);
2491 std::string arguments = argv[0]->ToString(runtime);
2492 shared_ptr<JsValue> resultValue = runtime->NewUndefined();
2493 resultValue = JsiAnimationBridgeUtils::CreateAnimationContext(runtime, page->GetPageId(), nodeId);
2494 auto animationBridge = AceType::MakeRefPtr<JsiAnimationBridge>(runtime, resultValue, nodeId);
2495 auto task = AceType::MakeRefPtr<JsiAnimationBridgeTaskCreate>(runtime, animationBridge, arguments);
2496 page->PushCommand(Referenced::MakeRefPtr<JsCommandAnimation>(nodeId, task));
2497 return runtime->NewUndefined();
2498 }
2499
JsGetBoundingClientRect(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2500 shared_ptr<JsValue> JsGetBoundingClientRect(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2501 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2502 {
2503 int32_t nodeId = GetNodeId(runtime, thisObj);
2504 return JsiComponentApiBridge::JsGetBoundingRect(runtime, nodeId);
2505 }
2506
JsGetInspector(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2507 shared_ptr<JsValue> JsGetInspector(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2508 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2509 {
2510 int32_t nodeId = GetNodeId(runtime, thisObj);
2511 return JsiComponentApiBridge::JsGetInspector(runtime, nodeId);
2512 }
2513
JsCreateElement(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2514 shared_ptr<JsValue> JsCreateElement(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2515 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2516 {
2517 int32_t newNodeId = CreateDomElement(runtime, thisObj, argv, argc);
2518 shared_ptr<JsValue> node = runtime->NewObject();
2519 node->SetProperty(runtime, "__nodeId", runtime->NewInt32(newNodeId));
2520 node->SetProperty(runtime, "setAttribute", runtime->NewFunction(JsSetAttribute));
2521 node->SetProperty(runtime, "setStyle", runtime->NewFunction(JsSetStyle));
2522 node->SetProperty(runtime, "addChild", runtime->NewFunction(JsAppendChild));
2523 node->SetProperty(runtime, "focus", runtime->NewFunction(JsFocus));
2524 node->SetProperty(runtime, "animate", runtime->NewFunction(JsAnimate));
2525 node->SetProperty(runtime, "getBoundingClientRect", runtime->NewFunction(JsGetBoundingClientRect));
2526 node->SetProperty(runtime, "getInspector", runtime->NewFunction(JsGetInspector));
2527 return node;
2528 }
2529
2530 // 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)2531 shared_ptr<JsValue> JsPerfPrint(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2532 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2533 {
2534 std::string ret = JsApiPerf::GetInstance().PrintToLogs();
2535 return runtime->NewString(ret);
2536 }
2537
2538 // 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)2539 shared_ptr<JsValue> JsPerfSleep(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2540 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2541 {
2542 int32_t valInt = argv[0]->ToInt32(runtime);
2543 usleep(valInt);
2544 return runtime->NewNull();
2545 }
2546
2547 // 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)2548 shared_ptr<JsValue> JsPerfBegin(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2549 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2550 {
2551 int64_t currentTime = GetMicroTickCount();
2552 JsApiPerf::GetInstance().InsertJsBeginLog(argv[0]->ToString(runtime), currentTime);
2553 return runtime->NewNull();
2554 }
2555
2556 // 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)2557 shared_ptr<JsValue> JsPerfEnd(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2558 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2559 {
2560 int64_t currentTime = GetMicroTickCount();
2561 JsApiPerf::GetInstance().InsertJsEndLog(argv[0]->ToString(runtime), currentTime);
2562 return runtime->NewNull();
2563 }
2564
2565 // native implementation for js function: hiView.report()
JsHiViewReport(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2566 shared_ptr<JsValue> JsHiViewReport(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2567 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2568 {
2569 if (argc != HIVIEW_ARGS_LEN) {
2570 LOGE("argc error, argc = %{public}d", argc);
2571 return runtime->NewNull();
2572 }
2573 if (argv[HIVIEW_ARGS_ID_IDX]->IsNumber(runtime) && argv[HIVIEW_ARGS_JSON_IDX]->IsString(runtime)) {
2574 std::string eventId = argv[HIVIEW_ARGS_ID_IDX]->ToString(runtime);
2575 std::string eventJson = argv[HIVIEW_ARGS_JSON_IDX]->ToString(runtime);
2576 EventReport::JsEventReport(StringToInt(eventId), eventJson);
2577 } else {
2578 LOGE("parameter type error");
2579 }
2580 return runtime->NewNull();
2581 }
2582
2583 // native implementation for js function: i18nPluralRules.select()
JsPluralRulesFormat(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2584 shared_ptr<JsValue> JsPluralRulesFormat(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2585 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2586 {
2587 // Should have one parameters.
2588 if (argc != 1) {
2589 LOGE("argc error, argc = %{public}d", argc);
2590 return runtime->NewNull();
2591 }
2592 if (argv[0]->IsNumber(runtime)) {
2593 std::string choice = argv[0]->ToString(runtime);
2594 shared_ptr<JsValue> result =
2595 runtime->NewString(Localization::GetInstance()->PluralRulesFormat(StringToDouble(choice)));
2596 return result;
2597 } else {
2598 LOGE("parameter type error ");
2599 return runtime->NewNull();
2600 }
2601 }
2602
2603 // -----------------------
2604 // Start JsiEngineInstance
2605 // -----------------------
~JsiEngineInstance()2606 JsiEngineInstance::~JsiEngineInstance()
2607 {
2608 // Destroy group bridge
2609 auto groupJsBridge = frontendDelegate_->GetGroupJsBridge();
2610 if (groupJsBridge != nullptr) {
2611 groupJsBridge->Destroy();
2612 }
2613
2614 if (runningPage_) {
2615 runningPage_->OnJsEngineDestroy();
2616 }
2617
2618 if (stagingPage_) {
2619 stagingPage_->OnJsEngineDestroy();
2620 }
2621
2622 if (runtime_) {
2623 runtime_->RegisterUncaughtExceptionHandler(nullptr);
2624 runtime_->Reset();
2625 }
2626 runtime_.reset();
2627 runtime_ = nullptr;
2628 }
2629
FlushCommandBuffer(void * context,const std::string & command)2630 void JsiEngineInstance::FlushCommandBuffer(void* context, const std::string& command)
2631 {
2632 // These js code is put into jsfwk, No need to do any thing here.
2633 return;
2634 }
2635
GetJsRuntime() const2636 shared_ptr<JsRuntime> JsiEngineInstance::GetJsRuntime() const
2637 {
2638 return runtime_;
2639 }
2640
GetRunningPage() const2641 RefPtr<JsAcePage> JsiEngineInstance::GetRunningPage() const
2642 {
2643 std::lock_guard<std::mutex> lock(mutex_);
2644 return runningPage_;
2645 }
2646
GetStagingPage() const2647 RefPtr<JsAcePage> JsiEngineInstance::GetStagingPage() const
2648 {
2649 std::lock_guard<std::mutex> lock(mutex_);
2650 return stagingPage_;
2651 }
2652
GetJsMessageDispatcher() const2653 WeakPtr<JsMessageDispatcher> JsiEngineInstance::GetJsMessageDispatcher() const
2654 {
2655 return dispatcher_;
2656 }
2657
GetFrontendDelegate() const2658 RefPtr<FrontendDelegate> JsiEngineInstance::GetFrontendDelegate() const
2659 {
2660 return frontendDelegate_;
2661 }
2662
SetRunningPage(const RefPtr<JsAcePage> & page)2663 void JsiEngineInstance::SetRunningPage(const RefPtr<JsAcePage>& page)
2664 {
2665 std::lock_guard<std::mutex> lock(mutex_);
2666 runningPage_ = page;
2667 }
2668
SetStagingPage(const RefPtr<JsAcePage> & page)2669 void JsiEngineInstance::SetStagingPage(const RefPtr<JsAcePage>& page)
2670 {
2671 std::lock_guard<std::mutex> lock(mutex_);
2672 stagingPage_ = page;
2673 }
2674
ResetStagingPage(const RefPtr<JsAcePage> & page)2675 void JsiEngineInstance::ResetStagingPage(const RefPtr<JsAcePage>& page)
2676 {
2677 std::lock_guard<std::mutex> lock(mutex_);
2678 stagingPage_ = page;
2679 }
2680
SetJsMessageDispatcher(const WeakPtr<JsMessageDispatcher> & dispatcher)2681 void JsiEngineInstance::SetJsMessageDispatcher(const WeakPtr<JsMessageDispatcher>& dispatcher)
2682 {
2683 dispatcher_ = dispatcher;
2684 }
2685
RegisterAceModule()2686 void JsiEngineInstance::RegisterAceModule()
2687 {
2688 ACE_SCOPED_TRACE("JsiEngine::RegisterAceModule");
2689
2690 shared_ptr<JsValue> aceObj = runtime_->NewObject();
2691 if (!aceObj) {
2692 LOGE("RegisterAceModule failed. aceObj is null");
2693 return;
2694 }
2695 if (!aceObj->SetProperty(runtime_, "domCreateBody", runtime_->NewFunction(JsDomCreateBody))) {
2696 LOGE("RegisterAceModule domCreateBody failed.");
2697 }
2698 if (!aceObj->SetProperty(runtime_, "domAddElement", runtime_->NewFunction(JsDomAddElement))) {
2699 LOGE("RegisterAceModule domAddElement failed.");
2700 }
2701 if (!aceObj->SetProperty(runtime_, "removeElement", runtime_->NewFunction(JsRemoveElement))) {
2702 LOGE("RegisterAceModule removeElement failed.");
2703 }
2704 if (!aceObj->SetProperty(runtime_, "updateElementAttrs", runtime_->NewFunction(JsUpdateElementAttrs))) {
2705 LOGE("RegisterAceModule updateElementAttrs failed.");
2706 }
2707 if (!aceObj->SetProperty(runtime_, "updateElementStyles", runtime_->NewFunction(JsUpdateElementStyles))) {
2708 LOGE("RegisterAceModule updateElementStyles failed.");
2709 }
2710 if (!aceObj->SetProperty(runtime_, "onCreateFinish", runtime_->NewFunction(JsOnCreateFinish))) {
2711 LOGE("RegisterAceModule onCreateFinish failed.");
2712 }
2713 if (!aceObj->SetProperty(runtime_, "onUpdateFinish", runtime_->NewFunction(JsOnUpdateFinish))) {
2714 LOGE("RegisterAceModule onUpdateFinish failed.");
2715 }
2716 if (!aceObj->SetProperty(runtime_, "callNative", runtime_->NewFunction(JsCallNative))) {
2717 LOGE("RegisterAceModule callNative failed.");
2718 }
2719 if (!aceObj->SetProperty(runtime_, "callComponent", runtime_->NewFunction(JsCallComponent))) {
2720 LOGE("RegisterAceModule callComponent failed.");
2721 }
2722
2723 shared_ptr<JsValue> global = runtime_->GetGlobal();
2724 if (!global->SetProperty(runtime_, "ace", aceObj)) {
2725 LOGE("RegisterAceModule ace failed.");
2726 }
2727 }
2728
JsCallNativeHandler(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2729 shared_ptr<JsValue> JsCallNativeHandler(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2730 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2731 {
2732 if (argc != 2 || !argv[0]->IsString(runtime) || !argv[1]->IsString(runtime)) {
2733 LOGE("JsCallNativeHandler: invalid parameters");
2734 return runtime->NewNull();
2735 }
2736
2737 auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
2738 if (engine == nullptr) {
2739 return runtime->NewNull();
2740 }
2741
2742 std::string event = argv[0]->ToString(runtime);
2743 std::string params = argv[1]->ToString(runtime);
2744 engine->GetDelegate()->CallNativeHandler(event, params);
2745 return runtime->NewNull();
2746 }
2747
RegisterConsoleModule()2748 void JsiEngineInstance::RegisterConsoleModule()
2749 {
2750 ACE_SCOPED_TRACE("JsiEngine::RegisterConsoleModule");
2751 shared_ptr<JsValue> global = runtime_->GetGlobal();
2752
2753 // app log method
2754 shared_ptr<JsValue> consoleObj = runtime_->NewObject();
2755 consoleObj->SetProperty(runtime_, "log", runtime_->NewFunction(JsiBaseUtils::AppInfoLogPrint));
2756 consoleObj->SetProperty(runtime_, "debug", runtime_->NewFunction(JsiBaseUtils::AppDebugLogPrint));
2757 consoleObj->SetProperty(runtime_, "info", runtime_->NewFunction(JsiBaseUtils::AppInfoLogPrint));
2758 consoleObj->SetProperty(runtime_, "warn", runtime_->NewFunction(JsiBaseUtils::AppWarnLogPrint));
2759 consoleObj->SetProperty(runtime_, "error", runtime_->NewFunction(JsiBaseUtils::AppErrorLogPrint));
2760 global->SetProperty(runtime_, "console", consoleObj);
2761
2762 // js framework log method
2763 shared_ptr<JsValue> aceConsoleObj = runtime_->NewObject();
2764 aceConsoleObj->SetProperty(runtime_, "log", runtime_->NewFunction(JsiBaseUtils::JsInfoLogPrint));
2765 aceConsoleObj->SetProperty(runtime_, "debug", runtime_->NewFunction(JsiBaseUtils::JsDebugLogPrint));
2766 aceConsoleObj->SetProperty(runtime_, "info", runtime_->NewFunction(JsiBaseUtils::JsInfoLogPrint));
2767 aceConsoleObj->SetProperty(runtime_, "warn", runtime_->NewFunction(JsiBaseUtils::JsWarnLogPrint));
2768 aceConsoleObj->SetProperty(runtime_, "error", runtime_->NewFunction(JsiBaseUtils::JsErrorLogPrint));
2769 global->SetProperty(runtime_, "aceConsole", aceConsoleObj);
2770 global->SetProperty(runtime_, "callNativeHandler", runtime_->NewFunction(JsCallNativeHandler));
2771 }
2772
RegisterConsoleModule(ArkNativeEngine * engine)2773 void JsiEngineInstance::RegisterConsoleModule(ArkNativeEngine* engine)
2774 {
2775 ACE_SCOPED_TRACE("JsiEngineInstance::RegisterConsoleModule");
2776 napi_env env = reinterpret_cast<napi_env>(engine);
2777 napi_value globalObj;
2778 napi_get_global(env, &globalObj);
2779 napi_valuetype valueType = napi_undefined;
2780 napi_typeof(env, globalObj, &valueType);
2781 if (valueType != napi_object) {
2782 LOGE("global is not NativeObject");
2783 return;
2784 }
2785
2786 napi_value logValue;
2787 napi_create_function(env, "log", strlen("log"), AppInfoLogPrint, nullptr, &logValue);
2788 napi_value debugValue;
2789 napi_create_function(env, "debug", strlen("debug"), AppDebugLogPrint, nullptr, &debugValue);
2790 napi_value infoValue;
2791 napi_create_function(env, "info", strlen("info"), AppInfoLogPrint, nullptr, &infoValue);
2792 napi_value warnValue;
2793 napi_create_function(env, "warn", strlen("warn"), AppWarnLogPrint, nullptr, &warnValue);
2794 napi_value errorValue;
2795 napi_create_function(env, "error", strlen("error"), AppErrorLogPrint, nullptr, &errorValue);
2796 napi_value consoleObj = nullptr;
2797 napi_create_object(env, &consoleObj);
2798 napi_set_named_property(env, consoleObj, "log", logValue);
2799 napi_set_named_property(env, consoleObj, "debug", debugValue);
2800 napi_set_named_property(env, consoleObj, "info", infoValue);
2801 napi_set_named_property(env, consoleObj, "warn", warnValue);
2802 napi_set_named_property(env, consoleObj, "error", errorValue);
2803 napi_set_named_property(env, globalObj, "console", consoleObj);
2804 }
2805
SyscapCanIUse(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)2806 shared_ptr<JsValue> SyscapCanIUse(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
2807 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
2808 {
2809 if (argc != 1) {
2810 LOGE("argc should be 1");
2811 return runtime->NewNull();
2812 }
2813 if (!argv[0]->IsString(runtime)) {
2814 LOGW("argv[0] is not IsString");
2815 return runtime->NewNull();
2816 }
2817
2818 std::string syscapString = argv[0]->ToString(runtime);
2819 bool ret = Ace::SystemProperties::IsSyscapExist(syscapString.c_str());
2820 return runtime->NewBoolean(ret);
2821 }
2822
RegisterSyscapModule()2823 void JsiEngineInstance::RegisterSyscapModule()
2824 {
2825 ACE_SCOPED_TRACE("JsiEngine::RegisterSyscapModule");
2826 shared_ptr<JsValue> global = runtime_->GetGlobal();
2827
2828 global->SetProperty(runtime_, CAN_IUSE, runtime_->NewFunction(SyscapCanIUse));
2829 }
2830
RegisterDocumentModule()2831 void JsiEngineInstance::RegisterDocumentModule()
2832 {
2833 ACE_SCOPED_TRACE("JsiEngine::RegisterDocumentModule");
2834 shared_ptr<JsValue> global = runtime_->GetGlobal();
2835 shared_ptr<JsValue> domObj = runtime_->NewObject();
2836 domObj->SetProperty(runtime_, "createElement", runtime_->NewFunction(JsCreateElement));
2837 global->SetProperty(runtime_, "dom", domObj);
2838 }
2839
RegisterPerfUtilModule()2840 void JsiEngineInstance::RegisterPerfUtilModule()
2841 {
2842 ACE_SCOPED_TRACE("JsiEngine::RegisterPerfUtilModule");
2843 shared_ptr<JsValue> perfObj = runtime_->NewObject();
2844 perfObj->SetProperty(runtime_, "printlog", runtime_->NewFunction(JsPerfPrint));
2845 perfObj->SetProperty(runtime_, "sleep", runtime_->NewFunction(JsPerfSleep));
2846 perfObj->SetProperty(runtime_, "begin", runtime_->NewFunction(JsPerfBegin));
2847 perfObj->SetProperty(runtime_, "end", runtime_->NewFunction(JsPerfEnd));
2848
2849 shared_ptr<JsValue> global = runtime_->GetGlobal();
2850 global->SetProperty(runtime_, "perfutil", perfObj);
2851 }
2852
RegisterHiViewModule()2853 void JsiEngineInstance::RegisterHiViewModule()
2854 {
2855 ACE_SCOPED_TRACE("JsiEngine::RegisterHiViewModule");
2856 shared_ptr<JsValue> hiViewObj = runtime_->NewObject();
2857 hiViewObj->SetProperty(runtime_, "report", runtime_->NewFunction(JsHiViewReport));
2858
2859 shared_ptr<JsValue> global = runtime_->GetGlobal();
2860 global->SetProperty(runtime_, "hiView", hiViewObj);
2861 }
2862
RegisterI18nPluralRulesModule()2863 void JsiEngineInstance::RegisterI18nPluralRulesModule()
2864 {
2865 ACE_SCOPED_TRACE("JsiEngine::RegisterI18nPluralRulesModule");
2866 shared_ptr<JsValue> i18nObj = runtime_->NewObject();
2867 i18nObj->SetProperty(runtime_, "select", runtime_->NewFunction(JsPluralRulesFormat));
2868
2869 shared_ptr<JsValue> global = runtime_->GetGlobal();
2870 global->SetProperty(runtime_, "i18nPluralRules", i18nObj);
2871 }
2872
RegisterFaPlugin()2873 void JsiEngineInstance::RegisterFaPlugin()
2874 {
2875 shared_ptr<JsValue> global = runtime_->GetGlobal();
2876 shared_ptr<JsValue> requireNapiFunc = global->GetProperty(runtime_, "requireNapi");
2877 if (!requireNapiFunc || !requireNapiFunc->IsFunction(runtime_)) {
2878 LOGW("requireNapi func not found");
2879 return;
2880 }
2881 std::vector<shared_ptr<JsValue>> argv = { runtime_->NewString("FeatureAbility") };
2882 requireNapiFunc->Call(runtime_, global, argv, argv.size());
2883 }
2884
InitJsEnv(bool debugger_mode,const std::unordered_map<std::string,void * > & extraNativeObject)2885 bool JsiEngineInstance::InitJsEnv(bool debugger_mode, const std::unordered_map<std::string, void*>& extraNativeObject)
2886 {
2887 ACE_SCOPED_TRACE("JsiEngine::InitJsEnv");
2888 runtime_.reset(new ArkJSRuntime());
2889 if (runtime_ == nullptr) {
2890 LOGE("Js Engine cannot allocate JSI JSRuntime");
2891 EventReport::SendJsException(JsExcepType::JS_ENGINE_INIT_ERR);
2892 return false;
2893 }
2894
2895 runtime_->SetLogPrint(PrintLog);
2896 std::string library_path = "";
2897 if (debugger_mode) {
2898 SetDebuggerPostTask(library_path);
2899 }
2900 if (!runtime_->Initialize(library_path, isDebugMode_, GetInstanceId())) {
2901 LOGE("Js Engine initialize runtime failed");
2902 return false;
2903 }
2904
2905 #if !defined(PREVIEW)
2906 for (const auto& [key, value] : extraNativeObject) {
2907 shared_ptr<JsValue> nativeValue = runtime_->NewNativePointer(value);
2908 runtime_->GetGlobal()->SetProperty(runtime_, key, nativeValue);
2909 }
2910
2911 auto arkRuntime = std::static_pointer_cast<ArkJSRuntime>(runtime_);
2912 arkRuntime->SetLanguage("js");
2913 runtime_->StartDebugger();
2914 #endif
2915
2916 RegisterAceModule();
2917 RegisterConsoleModule();
2918 RegisterSyscapModule();
2919 RegisterDocumentModule();
2920 RegisterPerfUtilModule();
2921 RegisterHiViewModule();
2922 RegisterI18nPluralRulesModule();
2923
2924 // load jsfwk
2925 #ifdef OHOS_PLATFORM
2926 if (!runtime_->ExecuteJsBin("/system/etc/strip.native.min.abc")) {
2927 LOGE("Failed to load js framework!");
2928 return false;
2929 }
2930 #else
2931 #if defined(PREVIEW)
2932 bool mockResult = runtime_->EvaluateJsCode((uint8_t*)_binary_jsMockSystemPlugin_abc_start,
2933 _binary_strip_native_min_abc_end - _binary_jsMockSystemPlugin_abc_start);
2934 if (!mockResult) {
2935 LOGE("Failed to load js mock api!");
2936 return false;
2937 }
2938 #endif
2939 bool jsfwkResult = runtime_->EvaluateJsCode((uint8_t*)_binary_strip_native_min_abc_start,
2940 _binary_strip_native_min_abc_end - _binary_strip_native_min_abc_start);
2941 if (!jsfwkResult) {
2942 LOGE("Failed to load js framework!");
2943 return false;
2944 }
2945 #endif
2946 // Init groupJsBridge
2947 InitGroupJsBridge();
2948
2949 runtime_->SetEmbedderData(this);
2950 runtime_->RegisterUncaughtExceptionHandler(JsiBaseUtils::ReportJsErrorEvent);
2951 return true;
2952 }
2953
InitGroupJsBridge()2954 void JsiEngineInstance::InitGroupJsBridge()
2955 {
2956 auto groupJsBridge = DynamicCast<JsiGroupJsBridge>(frontendDelegate_->GetGroupJsBridge());
2957 if (groupJsBridge == nullptr || groupJsBridge->InitializeGroupJsBridge(runtime_) == JS_CALL_FAIL) {
2958 LOGE("Js Engine Initialize GroupJsBridge failed!");
2959 EventReport::SendJsException(JsExcepType::JS_ENGINE_INIT_ERR);
2960 }
2961 }
2962
FireJsEvent(const std::string & eventStr)2963 bool JsiEngineInstance::FireJsEvent(const std::string& eventStr)
2964 {
2965 if (!runningPage_) {
2966 LOGW("js engine instance running page is not valid.");
2967 return false;
2968 }
2969 std::vector<shared_ptr<JsValue>> argv;
2970 argv.push_back(runtime_->NewString(std::to_string(runningPage_->GetPageId())));
2971 shared_ptr<JsValue> var1 = runtime_->ParseJson(eventStr);
2972 if (var1->IsArray(runtime_)) {
2973 shared_ptr<JsValue> varArray = var1->GetProperty(runtime_, 0);
2974 if (varArray->IsObject(runtime_)) {
2975 shared_ptr<JsValue> args = varArray->GetProperty(runtime_, "args");
2976 if (args->IsArray(runtime_)) {
2977 shared_ptr<JsValue> stdDrag = args->GetProperty(runtime_, 1);
2978 if (IsDragEvent(stdDrag->GetJsonString(runtime_))) {
2979 shared_ptr<JsValue> arrayType = args->GetProperty(runtime_, 2);
2980 if (arrayType->IsObject(runtime_)) {
2981 shared_ptr<JsValue> dataTransfer = runtime_->NewObject();
2982 dataTransfer->SetProperty(runtime_, "clearData", runtime_->NewFunction(AppClearData));
2983 dataTransfer->SetProperty(runtime_, "getData", runtime_->NewFunction(AppGetData));
2984 dataTransfer->SetProperty(runtime_, "setData", runtime_->NewFunction(AppSetData));
2985 dataTransfer->SetProperty(runtime_, "setDragImage", runtime_->NewFunction(AppSetDataImage));
2986 arrayType->SetProperty(runtime_, "dataTransfer", dataTransfer);
2987 }
2988 }
2989 }
2990 }
2991 }
2992 argv.push_back(var1);
2993
2994 shared_ptr<JsValue> global = runtime_->GetGlobal();
2995 shared_ptr<JsValue> func = global->GetProperty(runtime_, "callJS");
2996
2997 if (!func->IsFunction(runtime_)) {
2998 LOGE("\"callJs\" is not a function!");
2999 return false;
3000 }
3001 func->Call(runtime_, global, argv, argv.size());
3002 return true;
3003 }
3004
IsDragEvent(const std::string & param)3005 bool JsiEngineInstance::IsDragEvent(const std::string& param)
3006 {
3007 std::string::size_type idx = param.find("drag");
3008 return !(idx == std::string::npos);
3009 }
3010
CallJs(const std::string & callbackId,const std::string & args,bool keepAlive,bool isGlobal)3011 void JsiEngineInstance::CallJs(const std::string& callbackId, const std::string& args, bool keepAlive, bool isGlobal)
3012 {
3013 std::string keepAliveStr = keepAlive ? "true" : "false";
3014 std::string callBuff = std::string("[{\"args\": [\"")
3015 .append(callbackId)
3016 .append("\",")
3017 .append(args)
3018 .append(",")
3019 .append(keepAliveStr)
3020 .append("], \"method\":\"callback\"}]");
3021 int32_t instanceId = isGlobal ? DEFAULT_APP_ID : runningPage_->GetPageId();
3022
3023 std::vector<shared_ptr<JsValue>> argv;
3024 argv.push_back(runtime_->NewString(std::to_string(instanceId)));
3025 argv.push_back(runtime_->ParseJson(callBuff));
3026
3027 shared_ptr<JsValue> global = runtime_->GetGlobal();
3028 shared_ptr<JsValue> func = global->GetProperty(runtime_, "callJS");
3029 if (!func->IsFunction(runtime_)) {
3030 LOGE("\"callJs\" is not a function!");
3031 return;
3032 }
3033 func->Call(runtime_, global, argv, argv.size());
3034 }
3035
3036 #if defined(PREVIEW)
CallCurlFunction(const OHOS::Ace::RequestData & requestData,int32_t callbackId)3037 bool JsiEngineInstance::CallCurlFunction(const OHOS::Ace::RequestData& requestData, int32_t callbackId)
3038 {
3039 auto dispatcher = dispatcher_.Upgrade();
3040 if (dispatcher) {
3041 dispatcher->CallCurlFunction(requestData, callbackId);
3042 return true;
3043 } else {
3044 LOGW("Dispatcher Upgrade fail when dispatch request message to platform");
3045 return false;
3046 }
3047 }
3048 #endif
3049
SetDebuggerPostTask(std::string & library_path)3050 void JsiEngineInstance::SetDebuggerPostTask(std::string& library_path)
3051 {
3052 library_path = ARK_DEBUGGER_LIB_PATH;
3053 auto weakDelegate = AceType::WeakClaim(AceType::RawPtr(frontendDelegate_));
3054 auto&& postTask = [weakDelegate](std::function<void()>&& task) {
3055 auto delegate = weakDelegate.Upgrade();
3056 if (delegate == nullptr) {
3057 LOGE("delegate is nullptr");
3058 return;
3059 }
3060 delegate->PostJsTask(std::move(task));
3061 };
3062 std::static_pointer_cast<ArkJSRuntime>(runtime_)->SetDebuggerPostTask(postTask);
3063 }
3064
3065 // -----------------------
3066 // Start JsiEngine
3067 // -----------------------
Initialize(const RefPtr<FrontendDelegate> & delegate)3068 bool JsiEngine::Initialize(const RefPtr<FrontendDelegate>& delegate)
3069 {
3070 ACE_SCOPED_TRACE("JsiEngine::Initialize");
3071 engineInstance_ = AceType::MakeRefPtr<JsiEngineInstance>(delegate, instanceId_);
3072 engineInstance_->SetDebugMode(NeedDebugBreakPoint());
3073 bool result = engineInstance_->InitJsEnv(IsDebugVersion(), GetExtraNativeObject());
3074 if (!result) {
3075 LOGE("JsiEngine Initialize, init js env failed");
3076 return false;
3077 }
3078
3079 auto runtime = engineInstance_->GetJsRuntime();
3080 auto vm = std::static_pointer_cast<ArkJSRuntime>(runtime)->GetEcmaVm();
3081 if (vm == nullptr) {
3082 LOGE("JsiEngine Initialize, vm is null");
3083 return false;
3084 }
3085
3086 auto nativeEngine = new ArkNativeEngine(const_cast<EcmaVM*>(vm), static_cast<void*>(this));
3087 nativeEngine_ = nativeEngine;
3088 engineInstance_->SetNativeEngine(nativeEngine_);
3089 SetPostTask(nativeEngine_);
3090 #if !defined(PREVIEW)
3091 nativeEngine_->CheckUVLoop();
3092 #endif
3093
3094 ACE_DCHECK(delegate);
3095 if (delegate && delegate->GetAssetManager()) {
3096 std::vector<std::string> packagePath = delegate->GetAssetManager()->GetLibPath();
3097 auto appLibPathKey = delegate->GetAssetManager()->GetAppLibPathKey();
3098 if (!packagePath.empty()) {
3099 nativeEngine->SetPackagePath(appLibPathKey, packagePath);
3100 }
3101 }
3102 engineInstance_->RegisterFaPlugin();
3103 RegisterWorker();
3104
3105 return true;
3106 }
3107
SetPostTask(NativeEngine * nativeEngine)3108 void JsiEngine::SetPostTask(NativeEngine* nativeEngine)
3109 {
3110 auto weakDelegate = WeakPtr(engineInstance_->GetDelegate());
3111 auto&& postTask = [weakDelegate, weakEngine = AceType::WeakClaim(this), id = instanceId_](bool needSync) {
3112 auto delegate = weakDelegate.Upgrade();
3113 if (delegate == nullptr) {
3114 LOGE("delegate is nullptr");
3115 return;
3116 }
3117
3118 delegate->PostJsTask([weakEngine, needSync, id]() {
3119 auto jsEngine = weakEngine.Upgrade();
3120 if (jsEngine == nullptr) {
3121 LOGW("jsEngine is nullptr");
3122 return;
3123 }
3124 auto nativeEngine = jsEngine->GetNativeEngine();
3125 if (nativeEngine == nullptr) {
3126 return;
3127 }
3128 ContainerScope scope(id);
3129 nativeEngine->Loop(LOOP_NOWAIT, needSync);
3130 });
3131 };
3132 nativeEngine_->SetPostTask(postTask);
3133 }
3134
RegisterInitWorkerFunc()3135 void JsiEngine::RegisterInitWorkerFunc()
3136 {
3137 auto weakInstance = AceType::WeakClaim(AceType::RawPtr(engineInstance_));
3138 bool debugVersion = IsDebugVersion();
3139 std::string libraryPath = "";
3140 if (debugVersion) {
3141 libraryPath = ARK_DEBUGGER_LIB_PATH;
3142 }
3143 auto&& initWorkerFunc = [weakInstance, libraryPath, debugVersion, instanceId = instanceId_](
3144 NativeEngine* nativeEngine) {
3145 LOGI("WorkerCore RegisterInitWorkerFunc called");
3146 if (nativeEngine == nullptr) {
3147 LOGE("nativeEngine is nullptr");
3148 return;
3149 }
3150 auto arkNativeEngine = static_cast<ArkNativeEngine*>(nativeEngine);
3151 if (arkNativeEngine == nullptr) {
3152 LOGE("arkNativeEngine is nullptr");
3153 return;
3154 }
3155 auto instance = weakInstance.Upgrade();
3156 if (instance == nullptr) {
3157 LOGE("instance is nullptr");
3158 return;
3159 }
3160 #ifdef OHOS_PLATFORM
3161 auto tid = gettid();
3162 ConnectServerManager::Get().AddInstance(tid, "js");
3163 auto vm = const_cast<EcmaVM*>(arkNativeEngine->GetEcmaVm());
3164 auto workerPostTask = [nativeEngine](std::function<void()>&& callback) {
3165 nativeEngine->CallDebuggerPostTaskFunc(std::move(callback));
3166 };
3167 bool debugMode = AceApplicationInfo::GetInstance().IsNeedDebugBreakPoint();
3168 panda::JSNApi::DebugOption debugOption = { libraryPath.c_str(), debugMode };
3169 JSNApi::NotifyDebugMode(tid, vm, debugOption, tid, workerPostTask, debugVersion);
3170 #endif
3171 instance->RegisterConsoleModule(arkNativeEngine);
3172 // load jsfwk
3173 if (!arkNativeEngine->ExecuteJsBin("/system/etc/strip.native.min.abc")) {
3174 LOGE("Failed to load js framework!");
3175 }
3176 };
3177 nativeEngine_->SetInitWorkerFunc(initWorkerFunc);
3178 }
3179
3180 #ifdef OHOS_PLATFORM
RegisterOffWorkerFunc()3181 void JsiEngine::RegisterOffWorkerFunc()
3182 {
3183 auto weakInstance = AceType::WeakClaim(AceType::RawPtr(engineInstance_));
3184 bool debugVersion = IsDebugVersion();
3185 auto&& offWorkerFunc = [debugVersion](NativeEngine* nativeEngine) {
3186 LOGI("WorkerCore RegisterOffWorkerFunc called");
3187 if (!debugVersion) {
3188 return;
3189 }
3190 if (nativeEngine == nullptr) {
3191 LOGE("nativeEngine is nullptr");
3192 return;
3193 }
3194 auto arkNativeEngine = static_cast<ArkNativeEngine*>(nativeEngine);
3195 if (arkNativeEngine == nullptr) {
3196 LOGE("arkNativeEngine is nullptr");
3197 return;
3198 }
3199 ConnectServerManager::Get().RemoveInstance(gettid());
3200 auto vm = const_cast<EcmaVM*>(arkNativeEngine->GetEcmaVm());
3201 panda::JSNApi::StopDebugger(vm);
3202 };
3203 nativeEngine_->SetOffWorkerFunc(offWorkerFunc);
3204 }
3205 #endif
3206
RegisterAssetFunc()3207 void JsiEngine::RegisterAssetFunc()
3208 {
3209 auto weakDelegate = WeakPtr(engineInstance_->GetDelegate());
3210 auto&& assetFunc = [weakDelegate](const std::string& uri, std::vector<uint8_t>& content, std::string& ami) {
3211 LOGI("WorkerCore RegisterAssetFunc called");
3212 auto delegate = weakDelegate.Upgrade();
3213 if (delegate == nullptr) {
3214 LOGE("delegate is nullptr");
3215 return;
3216 }
3217 size_t index = uri.find_last_of(".");
3218 if (index == std::string::npos) {
3219 LOGE("invalid uri");
3220 } else {
3221 delegate->GetResourceData(uri.substr(0, index) + ".abc", content, ami);
3222 }
3223 };
3224 nativeEngine_->SetGetAssetFunc(assetFunc);
3225 }
3226
RegisterWorker()3227 void JsiEngine::RegisterWorker()
3228 {
3229 RegisterInitWorkerFunc();
3230 #ifdef OHOS_PLATFORM
3231 RegisterOffWorkerFunc();
3232 #endif
3233 RegisterAssetFunc();
3234 }
3235
~JsiEngine()3236 JsiEngine::~JsiEngine()
3237 {
3238 LOG_DESTROY();
3239 if (nativeEngine_ != nullptr) {
3240 #if !defined(PREVIEW)
3241 nativeEngine_->CancelCheckUVLoop();
3242 #endif
3243 delete nativeEngine_;
3244 nativeEngine_ = nullptr;
3245 }
3246 if (engineInstance_) {
3247 engineInstance_->SetNativeEngine(nullptr);
3248 }
3249 }
3250
GetLoadOptions(std::string & optionStr,bool isMainPage,bool hasAppCode)3251 void JsiEngine::GetLoadOptions(std::string& optionStr, bool isMainPage, bool hasAppCode)
3252 {
3253 ACE_DCHECK(engineInstance_);
3254 auto delegate = engineInstance_->GetFrontendDelegate();
3255 if (!delegate) {
3256 LOGW("GetLoadOptions error: delegate is null");
3257 return;
3258 }
3259 auto mediaQuery = delegate->GetMediaQueryInfoInstance();
3260 auto renderOption = MediaQueryInfo::GetMediaQueryJsonInfo();
3261 if (mediaQuery) {
3262 renderOption->Put("isInit", mediaQuery->GetIsInit());
3263 }
3264 renderOption->Put("pcPreview", PC_PREVIEW);
3265 renderOption->Put("appInstanceId", "10002");
3266 renderOption->Put("packageName", delegate->GetAppID().c_str());
3267
3268 // get resoureConfig
3269 delegate->GetResourceConfiguration(renderOption);
3270
3271 // get i18n message
3272 delegate->GetI18nData(renderOption);
3273 std::string language = AceApplicationInfo::GetInstance().GetLanguage();
3274 std::string region = AceApplicationInfo::GetInstance().GetCountryOrRegion();
3275 std::string local = language + "_" + region;
3276 renderOption->Put("language", local.c_str());
3277
3278 if (isMainPage && hasAppCode) {
3279 renderOption->Put("appCreate", "true");
3280 } else {
3281 renderOption->Put("appCreate", "false");
3282 }
3283 optionStr = renderOption->ToString();
3284 }
3285
ExecuteAbc(const std::string & fileName)3286 bool JsiEngine::ExecuteAbc(const std::string &fileName)
3287 {
3288 auto runtime = engineInstance_->GetJsRuntime();
3289 auto delegate = engineInstance_->GetDelegate();
3290
3291 std::vector<uint8_t> content;
3292 if (!delegate->GetAssetContent(fileName, content)) {
3293 return true;
3294 }
3295 #ifdef OHOS_PLATFORM
3296 const std::string abcPath = delegate->GetAssetPath(fileName).append(fileName);
3297 #else
3298 const std::string& abcPath = fileName;
3299 #endif
3300 if (!runtime->EvaluateJsCode(content.data(), content.size(), abcPath)) {
3301 LOGE("EvaluateJsCode \"%{private}s\" failed.", fileName.c_str());
3302 return false;
3303 }
3304 return true;
3305 }
3306
LoadJs(const std::string & url,const RefPtr<JsAcePage> & page,bool isMainPage)3307 void JsiEngine::LoadJs(const std::string& url, const RefPtr<JsAcePage>& page, bool isMainPage)
3308 {
3309 ACE_SCOPED_TRACE("JsiEngine::LoadJs");
3310 ACE_DCHECK(engineInstance_);
3311 engineInstance_->SetStagingPage(page);
3312 if (isMainPage) {
3313 ACE_DCHECK(!engineInstance_->GetRunningPage());
3314 engineInstance_->SetRunningPage(page);
3315 }
3316
3317 auto runtime = engineInstance_->GetJsRuntime();
3318 auto delegate = engineInstance_->GetFrontendDelegate();
3319
3320 // get source map
3321 std::string jsSourceMap;
3322 if (delegate->GetAssetContent(url + ".map", jsSourceMap)) {
3323 page->SetPageMap(jsSourceMap);
3324 } else {
3325 LOGI("js source map load failed!");
3326 }
3327 // get js bundle content
3328 shared_ptr<JsValue> jsCode = runtime->NewUndefined();
3329 shared_ptr<JsValue> jsAppCode = runtime->NewUndefined();
3330 const char js_ext[] = ".js";
3331 const char bin_ext[] = ".abc";
3332 auto pos = url.rfind(js_ext);
3333 if (pos != std::string::npos && pos == url.length() - (sizeof(js_ext) - 1)) {
3334 std::string urlName = url.substr(0, pos) + bin_ext;
3335
3336 if (isMainPage) {
3337 if (!ExecuteAbc("commons.abc")) {
3338 return;
3339 }
3340 if (!ExecuteAbc("vendors.abc")) {
3341 return;
3342 }
3343 std::string appMap;
3344 if (delegate->GetAssetContent("app.js.map", appMap)) {
3345 page->SetAppMap(appMap);
3346 } else {
3347 LOGI("app map load failed!");
3348 }
3349 if (!ExecuteAbc("app.abc")) {
3350 LOGE("ExecuteJsBin \"app.js\" failed.");
3351 return;
3352 }
3353 jsAppCode = runtime->GetGlobal()->GetProperty(runtime, "___mainEntry___");
3354 runtime->GetGlobal()->SetProperty(runtime, "___mainEntry___", runtime->NewUndefined());
3355 if (!jsAppCode->IsFunction(runtime)) {
3356 LOGE("appJsCode is not a function");
3357 return;
3358 }
3359 }
3360 if (!ExecuteAbc(urlName)) {
3361 return;
3362 }
3363
3364 jsCode = runtime->GetGlobal()->GetProperty(runtime, "___mainEntry___");
3365 runtime->GetGlobal()->SetProperty(runtime, "___mainEntry___", runtime->NewUndefined());
3366 if (!jsCode->IsFunction(runtime)) {
3367 LOGE("jsCode is not a function");
3368 return;
3369 }
3370 }
3371
3372 // get page params
3373 std::string jsonData = page->GetPageParams();
3374 if (jsonData.empty()) {
3375 jsonData = "{}";
3376 }
3377
3378 // get load options
3379 std::string optionStr;
3380 GetLoadOptions(optionStr, isMainPage, jsAppCode->IsFunction(runtime));
3381 shared_ptr<JsValue> instanceId = runtime->NewString(std::to_string(page->GetPageId()));
3382 shared_ptr<JsValue> renderOptions = runtime->ParseJson(optionStr);
3383 if (isMainPage && (!renderOptions || !renderOptions->SetProperty(runtime, "appCode", jsAppCode))) {
3384 LOGE("appCode property set failed.");
3385 return;
3386 }
3387 shared_ptr<JsValue> data = runtime->ParseJson(jsonData);
3388 shared_ptr<JsValue> info = runtime->NewObject();
3389 const std::vector<shared_ptr<JsValue>>& argv = { instanceId, jsCode, renderOptions, data, info };
3390
3391 shared_ptr<JsValue> global = runtime->GetGlobal();
3392 shared_ptr<JsValue> func = global->GetProperty(runtime, "createInstance");
3393
3394 if (!func) {
3395 LOGE("\"createInstance\" not found");
3396 return;
3397 }
3398 if (!func->IsFunction(runtime)) {
3399 LOGE("\"createInstance\" is not a function");
3400 return;
3401 }
3402
3403 func->Call(runtime, global, argv, argv.size());
3404 }
3405
3406 // Update running page
UpdateRunningPage(const RefPtr<JsAcePage> & page)3407 void JsiEngine::UpdateRunningPage(const RefPtr<JsAcePage>& page)
3408 {
3409 ACE_DCHECK(engineInstance_);
3410 engineInstance_->SetRunningPage(page);
3411 }
3412
3413 // Update staging page
UpdateStagingPage(const RefPtr<JsAcePage> & page)3414 void JsiEngine::UpdateStagingPage(const RefPtr<JsAcePage>& page)
3415 {
3416 ACE_DCHECK(engineInstance_);
3417 engineInstance_->SetStagingPage(page);
3418 }
3419
3420 // Reset loading page
ResetStagingPage()3421 void JsiEngine::ResetStagingPage()
3422 {
3423 ACE_DCHECK(engineInstance_);
3424 // weird
3425 auto runningPage = engineInstance_->GetRunningPage();
3426 engineInstance_->ResetStagingPage(runningPage);
3427 }
3428
SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher> & dispatcher)3429 void JsiEngine::SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher>& dispatcher)
3430 {
3431 ACE_DCHECK(engineInstance_);
3432 engineInstance_->SetJsMessageDispatcher(dispatcher);
3433 }
3434
FireAsyncEvent(const std::string & eventId,const std::string & param)3435 void JsiEngine::FireAsyncEvent(const std::string& eventId, const std::string& param)
3436 {
3437 ACE_DCHECK(engineInstance_);
3438
3439 std::string callBuf = std::string("[{\"args\": [\"")
3440 .append(eventId)
3441 .append("\",")
3442 .append(param)
3443 .append("], \"method\":\"fireEvent\"}]");
3444
3445 ACE_DCHECK(engineInstance_);
3446 if (!engineInstance_->FireJsEvent(callBuf.c_str())) {
3447 LOGE("Js Engine FireSyncEvent FAILED!");
3448 }
3449 }
3450
FireSyncEvent(const std::string & eventId,const std::string & param)3451 void JsiEngine::FireSyncEvent(const std::string& eventId, const std::string& param)
3452 {
3453 std::string callBuf = std::string("[{\"args\": [\"")
3454 .append(eventId)
3455 .append("\",")
3456 .append(param)
3457 .append("], \"method\":\"fireEventSync\"}]");
3458
3459 ACE_DCHECK(engineInstance_);
3460 if (!engineInstance_->FireJsEvent(callBuf.c_str())) {
3461 LOGE("Js Engine FireSyncEvent FAILED!");
3462 }
3463 }
3464
FireExternalEvent(const std::string & componentId,const uint32_t nodeId,const bool isDestroy)3465 void JsiEngine::FireExternalEvent(const std::string& componentId, const uint32_t nodeId, const bool isDestroy)
3466 {
3467 ACE_DCHECK(engineInstance_);
3468 if (isDestroy) {
3469 return;
3470 }
3471 auto runtime = engineInstance_->GetJsRuntime();
3472 auto page = GetRunningPage(runtime);
3473 if (page == nullptr) {
3474 LOGE("FireExternalEvent GetRunningPage is nullptr");
3475 return;
3476 }
3477 #ifdef XCOMPONENT_SUPPORTED
3478 std::string arguments;
3479 auto bridge = AceType::DynamicCast<JsiXComponentBridge>(page->GetXComponentBridgeById(nodeId));
3480 if (bridge) {
3481 bridge->HandleContext(runtime, nodeId, arguments);
3482 return;
3483 }
3484 #endif
3485 }
3486
3487 // Destroy page instance on Js
DestroyPageInstance(int32_t pageId)3488 void JsiEngine::DestroyPageInstance(int32_t pageId)
3489 {
3490 LOGI("JsiEngine DestroyPageInstance");
3491 shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
3492 const std::vector<shared_ptr<JsValue>>& argv = { runtime->NewString(std::to_string(pageId)) };
3493
3494 shared_ptr<JsValue> global = runtime->GetGlobal();
3495 shared_ptr<JsValue> func = global->GetProperty(runtime, "destroyInstance");
3496 if (!func || !func->IsFunction(runtime)) {
3497 LOGE("\"destroyInstance\" not found or is not a function!");
3498 return;
3499 }
3500 func->Call(runtime, global, argv, argv.size());
3501
3502 RunGarbageCollection();
3503 }
3504
3505 // destroy application instance according to packageName
DestroyApplication(const std::string & packageName)3506 void JsiEngine::DestroyApplication(const std::string& packageName)
3507 {
3508 LOGI("JsiEngine DestroyApplication");
3509 shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
3510 const std::vector<shared_ptr<JsValue>>& argv = { runtime->NewString(packageName) };
3511
3512 shared_ptr<JsValue> global = runtime->GetGlobal();
3513 shared_ptr<JsValue> func = global->GetProperty(runtime, "appDestroy");
3514 if (!func || !func->IsFunction(runtime)) {
3515 LOGE("\"appDestroy\" not found or is not a function!");
3516 return;
3517 }
3518 func->Call(runtime, global, argv, argv.size());
3519 }
3520
TimerCallback(const std::string & callbackId,const std::string & delay,bool isInterval)3521 void JsiEngine::TimerCallback(const std::string& callbackId, const std::string& delay, bool isInterval)
3522 {
3523 if (isInterval) {
3524 engineInstance_->CallJs(callbackId, std::string("{}"), true, true);
3525 engineInstance_->GetFrontendDelegate()->WaitTimer(callbackId, delay, isInterval, false);
3526 } else {
3527 engineInstance_->CallJs(callbackId, std::string("{}"), false, true);
3528 engineInstance_->GetFrontendDelegate()->ClearTimer(callbackId);
3529 }
3530 }
3531
MediaQueryCallback(const std::string & callbackId,const std::string & args)3532 void JsiEngine::MediaQueryCallback(const std::string& callbackId, const std::string& args)
3533 {
3534 if (!callbackId.empty() && engineInstance_) {
3535 engineInstance_->CallJs(callbackId, args, true, false);
3536 }
3537 }
3538
RequestAnimationCallback(const std::string & callbackId,uint64_t timeStamp)3539 void JsiEngine::RequestAnimationCallback(const std::string& callbackId, uint64_t timeStamp)
3540 {
3541 if (engineInstance_) {
3542 engineInstance_->CallJs(callbackId, std::to_string(timeStamp), false, true);
3543 engineInstance_->GetFrontendDelegate()->CancelAnimationFrame(callbackId);
3544 }
3545 }
3546
JsCallback(const std::string & callbackId,const std::string & args)3547 void JsiEngine::JsCallback(const std::string& callbackId, const std::string& args)
3548 {
3549 if (engineInstance_) {
3550 engineInstance_->CallJs(callbackId, args, true, false);
3551 }
3552 }
3553
RunGarbageCollection()3554 void JsiEngine::RunGarbageCollection()
3555 {
3556 if (engineInstance_ && engineInstance_->GetJsRuntime()) {
3557 engineInstance_->GetJsRuntime()->RunGC();
3558 }
3559 }
3560
DumpHeapSnapshot(bool isPrivate)3561 void JsiEngine::DumpHeapSnapshot(bool isPrivate)
3562 {
3563 if (engineInstance_ && engineInstance_->GetJsRuntime()) {
3564 engineInstance_->GetJsRuntime()->DumpHeapSnapshot(isPrivate);
3565 }
3566 }
3567
DestroyHeapProfiler()3568 void JsiEngine::DestroyHeapProfiler()
3569 {
3570 if (engineInstance_ && engineInstance_->GetJsRuntime()) {
3571 engineInstance_->GetJsRuntime()->DestroyHeapProfiler();
3572 }
3573 }
3574
ForceFullGC()3575 void JsiEngine::ForceFullGC()
3576 {
3577 if (engineInstance_ && engineInstance_->GetJsRuntime()) {
3578 engineInstance_->GetJsRuntime()->RunFullGC();
3579 }
3580 }
3581
GetStacktraceMessage()3582 std::string JsiEngine::GetStacktraceMessage()
3583 {
3584 auto arkNativeEngine = static_cast<ArkNativeEngine*>(nativeEngine_);
3585 if (!arkNativeEngine) {
3586 LOGE("GetStacktraceMessage arkNativeEngine is nullptr");
3587 return "";
3588 }
3589 std::string stack;
3590 bool getStackSuccess = false;
3591 if (arkNativeEngine->SuspendVM()) {
3592 getStackSuccess = arkNativeEngine->BuildJsStackTrace(stack);
3593 arkNativeEngine->ResumeVM();
3594 }
3595 if (!getStackSuccess) {
3596 LOGE("GetStacktraceMessage arkNativeEngine get stack failed");
3597 return "JS stacktrace is empty";
3598 }
3599
3600 auto runningPage = engineInstance_ ? engineInstance_->GetRunningPage() : nullptr;
3601 return JsiBaseUtils::TransSourceStack(runningPage, stack);
3602 }
3603
GetGroupJsBridge()3604 RefPtr<GroupJsBridge> JsiEngine::GetGroupJsBridge()
3605 {
3606 return AceType::MakeRefPtr<JsiGroupJsBridge>();
3607 }
3608
OnStartContinuation()3609 bool JsiEngine::OnStartContinuation()
3610 {
3611 LOGI("JsiEngine OnStartContinuation");
3612 shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
3613 if (!runtime) {
3614 LOGE("OnStartContinuation failed, runtime is null.");
3615 return false;
3616 }
3617
3618 return CallAppFunc("onStartContinuation");
3619 }
3620
OnCompleteContinuation(int32_t code)3621 void JsiEngine::OnCompleteContinuation(int32_t code)
3622 {
3623 LOGI("JsiEngine OnCompleteContinuation");
3624 shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
3625 if (!runtime) {
3626 LOGE("OnCompleteContinuation failed, runtime is null.");
3627 return;
3628 }
3629
3630 std::vector<shared_ptr<JsValue>> argv = { runtime->NewNumber(code) };
3631 CallAppFunc("onCompleteContinuation", argv);
3632 }
3633
OnRemoteTerminated()3634 void JsiEngine::OnRemoteTerminated()
3635 {
3636 LOGI("JsiEngine OnRemoteTerminated");
3637 shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
3638 if (!runtime) {
3639 LOGE("OnRemoteTerminated failed, runtime is null.");
3640 return;
3641 }
3642
3643 CallAppFunc("onRemoteTerminated");
3644 }
3645
OnSaveData(std::string & data)3646 void JsiEngine::OnSaveData(std::string& data)
3647 {
3648 LOGI("JsiEngine OnSaveData");
3649 shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
3650 if (!runtime) {
3651 LOGE("OnSaveData failed, runtime is null.");
3652 return;
3653 }
3654
3655 shared_ptr<JsValue> object = runtime->NewObject();
3656 std::vector<shared_ptr<JsValue>> argv = { object };
3657 if (CallAppFunc("onSaveData", argv)) {
3658 data = object->GetJsonString(runtime);
3659 }
3660 }
3661
OnRestoreData(const std::string & data)3662 bool JsiEngine::OnRestoreData(const std::string& data)
3663 {
3664 LOGI("JsiEngine OnRestoreData");
3665 shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
3666 if (!runtime) {
3667 LOGE("OnRestoreData failed, runtime is null.");
3668 return false;
3669 }
3670 shared_ptr<JsValue> result;
3671 shared_ptr<JsValue> jsonObj = runtime->ParseJson(data);
3672 if (jsonObj->IsUndefined(runtime) || jsonObj->IsException(runtime)) {
3673 LOGE("JsiEngine: Parse json for restore data failed.");
3674 return false;
3675 }
3676 std::vector<shared_ptr<JsValue>> argv = { jsonObj };
3677 return CallAppFunc("onRestoreData", argv);
3678 }
3679
CallAppFunc(const std::string & appFuncName)3680 bool JsiEngine::CallAppFunc(const std::string& appFuncName)
3681 {
3682 std::vector<shared_ptr<JsValue>> argv = {};
3683 return CallAppFunc(appFuncName, argv);
3684 }
3685
CallAppFunc(const std::string & appFuncName,std::vector<shared_ptr<JsValue>> & argv)3686 bool JsiEngine::CallAppFunc(const std::string& appFuncName, std::vector<shared_ptr<JsValue>>& argv)
3687 {
3688 shared_ptr<JsRuntime> runtime = engineInstance_->GetJsRuntime();
3689 ACE_DCHECK(runtime);
3690 shared_ptr<JsValue> global = runtime->GetGlobal();
3691 shared_ptr<JsValue> appObj = global->GetProperty(runtime, "aceapp");
3692 if (!appObj->IsObject(runtime)) {
3693 LOGE("property \"aceapp\" is not a object");
3694 return false;
3695 }
3696 shared_ptr<JsValue> defaultObject = appObj->GetProperty(runtime, "$def");
3697 if (!defaultObject->IsObject(runtime)) {
3698 LOGE("property \"$def\" is not a object");
3699 return false;
3700 }
3701 shared_ptr<JsValue> func = defaultObject->GetProperty(runtime, appFuncName);
3702 if (!func || !func->IsFunction(runtime)) {
3703 LOGE("%{public}s not found or is not a function!", appFuncName.c_str());
3704 return false;
3705 }
3706 shared_ptr<JsValue> result;
3707 result = func->Call(runtime, defaultObject, argv, argv.size());
3708 return (result->ToString(runtime) == "true");
3709 }
3710
3711 } // namespace OHOS::Ace::Framework
3712