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