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