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