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