• 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/declarative_frontend/jsview/action_sheet/js_action_sheet.h"
17 
18 #include <string>
19 #include <vector>
20 
21 #include "base/log/ace_scoring_log.h"
22 #include "bridge/common/utils/engine_helper.h"
23 #include "bridge/declarative_frontend/engine/functions/js_function.h"
24 #include "bridge/declarative_frontend/jsview/models/action_sheet_model_impl.h"
25 #include "core/common/container.h"
26 #include "core/components_ng/base/view_stack_processor.h"
27 #include "core/components_ng/pattern/action_sheet/action_sheet_model_ng.h"
28 
29 namespace OHOS::Ace {
30 std::unique_ptr<ActionSheetModel> ActionSheetModel::instance_ = nullptr;
31 std::mutex ActionSheetModel::mutex_;
32 
GetInstance()33 ActionSheetModel* ActionSheetModel::GetInstance()
34 {
35     if (!instance_) {
36         std::lock_guard<std::mutex> lock(mutex_);
37         if (!instance_) {
38 #ifdef NG_BUILD
39             instance_.reset(new NG::ActionSheetModelNG());
40 #else
41             if (Container::IsCurrentUseNewPipeline()) {
42                 instance_.reset(new NG::ActionSheetModelNG());
43             } else {
44                 instance_.reset(new Framework::ActionSheetModelImpl());
45             }
46 #endif
47         }
48     }
49     return instance_.get();
50 }
51 } // namespace OHOS::Ace
52 
53 namespace OHOS::Ace::Framework {
54 namespace {
55 const DimensionOffset ACTION_SHEET_OFFSET_DEFAULT = DimensionOffset(0.0_vp, -40.0_vp);
56 const DimensionOffset ACTION_SHEET_OFFSET_DEFAULT_TOP = DimensionOffset(0.0_vp, 40.0_vp);
57 const std::vector<DialogAlignment> DIALOG_ALIGNMENT = { DialogAlignment::TOP, DialogAlignment::CENTER,
58     DialogAlignment::BOTTOM, DialogAlignment::DEFAULT, DialogAlignment::TOP_START, DialogAlignment::TOP_END,
59     DialogAlignment::CENTER_START, DialogAlignment::CENTER_END, DialogAlignment::BOTTOM_START,
60     DialogAlignment::BOTTOM_END };
61 const std::vector<LevelMode> DIALOG_LEVEL_MODE = { LevelMode::OVERLAY, LevelMode::EMBEDDED };
62 const std::vector<ImmersiveMode> DIALOG_IMMERSIVE_MODE = { ImmersiveMode::DEFAULT, ImmersiveMode::EXTEND};
63 } // namespace
64 
SetParseStyle(ButtonInfo & buttonInfo,const int32_t styleValue)65 static void SetParseStyle(ButtonInfo& buttonInfo, const int32_t styleValue)
66 {
67     if (styleValue >= static_cast<int32_t>(DialogButtonStyle::DEFAULT) &&
68         styleValue <= static_cast<int32_t>(DialogButtonStyle::HIGHTLIGHT)) {
69         buttonInfo.dlgButtonStyle = static_cast<DialogButtonStyle>(styleValue);
70     }
71 }
72 
ParseSheetInfo(const JsiExecutionContext & execContext,JSRef<JSVal> val)73 ActionSheetInfo ParseSheetInfo(const JsiExecutionContext& execContext, JSRef<JSVal> val)
74 {
75     ActionSheetInfo sheetInfo;
76     if (!val->IsObject()) {
77         LOGW("param is not an object.");
78         return sheetInfo;
79     }
80 
81     auto obj = JSRef<JSObject>::Cast(val);
82     auto titleVal = obj->GetProperty("title");
83     std::string title;
84     if (JSActionSheet::ParseJsString(titleVal, title)) {
85         sheetInfo.title = title;
86     }
87 
88     auto iconVal = obj->GetProperty("icon");
89     std::string icon;
90     if (JSActionSheet::ParseJsMedia(iconVal, icon)) {
91         sheetInfo.icon = icon;
92     }
93 
94     auto actionValue = obj->GetProperty("action");
95     if (actionValue->IsFunction()) {
96         auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
97         auto actionFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(actionValue));
98         auto eventFunc = [execContext, func = std::move(actionFunc), node = frameNode](const GestureEvent&) {
99             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execContext);
100             ACE_SCORING_EVENT("SheetInfo.action");
101             auto pipelineContext = PipelineContext::GetCurrentContextSafely();
102             CHECK_NULL_VOID(pipelineContext);
103             pipelineContext->UpdateCurrentActiveNode(node);
104             func->ExecuteJS();
105         };
106         ActionSheetModel::GetInstance()->SetAction(eventFunc, sheetInfo);
107     }
108     return sheetInfo;
109 }
110 
ParseTitleAndMessage(DialogProperties & properties,JSRef<JSObject> obj)111 void ParseTitleAndMessage(DialogProperties& properties, JSRef<JSObject> obj)
112 {
113     // Parse title.
114     auto titleValue = obj->GetProperty("title");
115     std::string title;
116     if (JSActionSheet::ParseJsString(titleValue, title)) {
117         properties.title = title;
118     }
119 
120     // Parse subtitle.
121     auto subtitleValue = obj->GetProperty("subtitle");
122     std::string subtitle;
123     if (JSActionSheet::ParseJsString(subtitleValue, subtitle)) {
124         properties.subtitle = subtitle;
125     }
126 
127     // Parses message.
128     auto messageValue = obj->GetProperty("message");
129     std::string message;
130     if (JSActionSheet::ParseJsString(messageValue, message)) {
131         properties.content = message;
132     }
133 }
134 
ParseConfirmButton(const JsiExecutionContext & execContext,DialogProperties & properties,JSRef<JSObject> obj)135 void ParseConfirmButton(const JsiExecutionContext& execContext, DialogProperties& properties, JSRef<JSObject> obj)
136 {
137     auto confirmVal = obj->GetProperty("confirm");
138     if (!confirmVal->IsObject()) {
139         return;
140     }
141     JSRef<JSObject> confirmObj = JSRef<JSObject>::Cast(confirmVal);
142     std::string buttonValue;
143     if (JSActionSheet::ParseJsString(confirmObj->GetProperty("value"), buttonValue)) {
144         ButtonInfo buttonInfo = { .text = buttonValue };
145         JSRef<JSVal> actionValue = confirmObj->GetProperty("action");
146         if (actionValue->IsFunction()) {
147             auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
148             auto actionFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(actionValue));
149             auto gestureEvent = [execContext, func = std::move(actionFunc), node = frameNode](GestureEvent&) {
150                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execContext);
151                 ACE_SCORING_EVENT("ActionSheet.confirm.action");
152                 auto pipelineContext = PipelineContext::GetCurrentContextSafely();
153                 CHECK_NULL_VOID(pipelineContext);
154                 pipelineContext->UpdateCurrentActiveNode(node);
155                 func->ExecuteJS();
156             };
157             actionFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(actionValue));
158             auto eventFunc = [execContext, func = std::move(actionFunc), node = frameNode]() {
159                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execContext);
160                 ACE_SCORING_EVENT("ActionSheet.confirm.action");
161                 auto pipelineContext = PipelineContext::GetCurrentContextSafely();
162                 CHECK_NULL_VOID(pipelineContext);
163                 pipelineContext->UpdateCurrentActiveNode(node);
164                 func->Execute();
165             };
166             ActionSheetModel::GetInstance()->SetConfirm(gestureEvent, eventFunc, buttonInfo, properties);
167         }
168         auto enabledValue = confirmObj->GetProperty("enabled");
169         if (enabledValue->IsBoolean()) {
170             buttonInfo.enabled = enabledValue->ToBoolean();
171         }
172         auto defaultFocusValue = confirmObj->GetProperty("defaultFocus");
173         if (defaultFocusValue->IsBoolean()) {
174             buttonInfo.defaultFocus = defaultFocusValue->ToBoolean();
175         }
176         auto style = confirmObj->GetProperty("style");
177         if (style->IsNumber()) {
178             SetParseStyle(buttonInfo, style->ToNumber<int32_t>());
179         }
180         if (!buttonInfo.defaultFocus) {
181             buttonInfo.isPrimary = true;
182         }
183         if (buttonInfo.IsValid()) {
184             properties.buttons.clear();
185             properties.buttons.emplace_back(buttonInfo);
186         }
187     }
188 }
189 
ParseShadow(DialogProperties & properties,JSRef<JSObject> obj)190 void ParseShadow(DialogProperties& properties, JSRef<JSObject> obj)
191 {
192     // Parse shadow.
193     auto shadowValue = obj->GetProperty("shadow");
194     Shadow shadow;
195     if ((shadowValue->IsObject() || shadowValue->IsNumber()) && JSActionSheet::ParseShadowProps(shadowValue, shadow)) {
196         properties.shadow = shadow;
197     }
198 }
199 
ParseBorderWidthAndColor(DialogProperties & properties,JSRef<JSObject> obj)200 void ParseBorderWidthAndColor(DialogProperties& properties, JSRef<JSObject> obj)
201 {
202     auto borderWidthValue = obj->GetProperty("borderWidth");
203     NG::BorderWidthProperty borderWidth;
204     if (JSActionSheet::ParseBorderWidthProps(borderWidthValue, borderWidth)) {
205         properties.borderWidth = borderWidth;
206         auto colorValue = obj->GetProperty("borderColor");
207         NG::BorderColorProperty borderColor;
208         if (JSActionSheet::ParseBorderColorProps(colorValue, borderColor)) {
209             properties.borderColor = borderColor;
210         } else {
211             borderColor.SetColor(Color::BLACK);
212             properties.borderColor = borderColor;
213         }
214     }
215 }
216 
ParseRadius(DialogProperties & properties,JSRef<JSObject> obj)217 void ParseRadius(DialogProperties& properties, JSRef<JSObject> obj)
218 {
219     auto cornerRadiusValue = obj->GetProperty("cornerRadius");
220     NG::BorderRadiusProperty radius;
221     if (JSActionSheet::ParseBorderRadius(cornerRadiusValue, radius)) {
222         properties.borderRadius = radius;
223     }
224 }
225 
UpdateDialogAlignment(DialogAlignment & alignment)226 void UpdateDialogAlignment(DialogAlignment& alignment)
227 {
228     bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
229     if (alignment == DialogAlignment::TOP_START) {
230         if (isRtl) {
231             alignment = DialogAlignment::TOP_END;
232         }
233     } else if (alignment == DialogAlignment::TOP_END) {
234         if (isRtl) {
235             alignment = DialogAlignment::TOP_START;
236         }
237     } else if (alignment == DialogAlignment::CENTER_START) {
238         if (isRtl) {
239             alignment = DialogAlignment::CENTER_END;
240         }
241     } else if (alignment == DialogAlignment::CENTER_END) {
242         if (isRtl) {
243             alignment = DialogAlignment::CENTER_START;
244         }
245     } else if (alignment == DialogAlignment::BOTTOM_START) {
246         if (isRtl) {
247             alignment = DialogAlignment::BOTTOM_END;
248         }
249     } else if (alignment == DialogAlignment::BOTTOM_END) {
250         if (isRtl) {
251             alignment = DialogAlignment::BOTTOM_START;
252         }
253     }
254 }
255 
ParseDialogAlignment(DialogProperties & properties,JSRef<JSObject> obj)256 void ParseDialogAlignment(DialogProperties& properties, JSRef<JSObject> obj)
257 {
258     // Parse alignment
259     auto alignmentValue = obj->GetProperty("alignment");
260     if (alignmentValue->IsNumber()) {
261         auto alignment = alignmentValue->ToNumber<int32_t>();
262         if (alignment >= 0 && alignment <= static_cast<int32_t>(DIALOG_ALIGNMENT.size())) {
263             properties.alignment = DIALOG_ALIGNMENT[alignment];
264             UpdateDialogAlignment(properties.alignment);
265         }
266         if (alignment == static_cast<int32_t>(DialogAlignment::TOP) ||
267             alignment == static_cast<int32_t>(DialogAlignment::TOP_START) ||
268             alignment == static_cast<int32_t>(DialogAlignment::TOP_END)) {
269             properties.offset = ACTION_SHEET_OFFSET_DEFAULT_TOP;
270         }
271     }
272 }
273 
ParseOffset(DialogProperties & properties,JSRef<JSObject> obj)274 void ParseOffset(DialogProperties& properties, JSRef<JSObject> obj)
275 {
276     // Parse offset
277     auto offsetValue = obj->GetProperty("offset");
278     if (offsetValue->IsObject()) {
279         auto offsetObj = JSRef<JSObject>::Cast(offsetValue);
280         CalcDimension dx;
281         auto dxValue = offsetObj->GetProperty("dx");
282         JSActionSheet::ParseJsDimensionVp(dxValue, dx);
283         CalcDimension dy;
284         auto dyValue = offsetObj->GetProperty("dy");
285         JSActionSheet::ParseJsDimensionVp(dyValue, dy);
286         properties.offset = DimensionOffset(dx, dy);
287         bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
288         Dimension offsetX = isRtl ? properties.offset.GetX() * (-1) : properties.offset.GetX();
289         properties.offset.SetX(offsetX);
290     }
291 }
292 
ParseMaskRect(DialogProperties & properties,JSRef<JSObject> obj)293 void ParseMaskRect(DialogProperties& properties, JSRef<JSObject> obj)
294 {
295     // Parse maskRect.
296     auto maskRectValue = obj->GetProperty("maskRect");
297     DimensionRect maskRect;
298     if (JSViewAbstract::ParseJsDimensionRect(maskRectValue, maskRect)) {
299         properties.maskRect = maskRect;
300         bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
301         auto offset = maskRect.GetOffset();
302         Dimension offsetX = isRtl ? offset.GetX() * (-1) : offset.GetX();
303         offset.SetX(offsetX);
304         properties.maskRect->SetOffset(offset);
305     }
306 }
307 
ParseDialogLevelMode(DialogProperties & properties,JSRef<JSObject> obj)308 void ParseDialogLevelMode(DialogProperties& properties, JSRef<JSObject> obj)
309 {
310 #ifndef ARKUI_WAERABLE
311     auto levelMode = obj->GetProperty("levelMode");
312     auto levelUniqueId = obj->GetProperty("levelUniqueId");
313     auto immersiveMode = obj->GetProperty("immersiveMode");
314     bool showInMainWindow = true;
315     if (obj->GetProperty("showInSubWindow")->IsBoolean() && obj->GetProperty("showInSubWindow")->ToBoolean()) {
316         showInMainWindow = false;
317     }
318     if (levelMode->IsNumber() && showInMainWindow) {
319         auto mode = levelMode->ToNumber<int32_t>();
320         if (mode >= 0 && mode < static_cast<int32_t>(DIALOG_LEVEL_MODE.size())) {
321             properties.dialogLevelMode = DIALOG_LEVEL_MODE[mode];
322         }
323     }
324     if (levelUniqueId->IsNumber()) {
325         properties.dialogLevelUniqueId = levelUniqueId->ToNumber<int32_t>();
326     }
327     if (immersiveMode->IsNumber()) {
328         auto immersiveVal = immersiveMode->ToNumber<int32_t>();
329         if (immersiveVal >= 0 && immersiveVal < static_cast<int32_t>(DIALOG_IMMERSIVE_MODE.size())) {
330             properties.dialogImmersiveMode = DIALOG_IMMERSIVE_MODE[immersiveVal];
331         }
332     }
333 #endif
334 }
335 
Show(const JSCallbackInfo & args)336 void JSActionSheet::Show(const JSCallbackInfo& args)
337 {
338     auto scopedDelegate = EngineHelper::GetCurrentDelegateSafely();
339     if (!scopedDelegate) {
340         // this case usually means there is no foreground container, need to figure out the reason.
341         LOGE("scopedDelegate is null, please check");
342         return;
343     }
344     if (!args[0]->IsObject()) {
345         LOGE("args is not an object, can't show ActionSheet.");
346         return;
347     }
348 
349     DialogProperties properties {
350         .type = DialogType::ACTION_SHEET, .alignment = DialogAlignment::BOTTOM, .offset = ACTION_SHEET_OFFSET_DEFAULT
351     };
352     auto obj = JSRef<JSObject>::Cast(args[0]);
353     auto execContext = args.GetExecutionContext();
354     auto dialogNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
355 
356     ParseTitleAndMessage(properties, obj);
357     ParseConfirmButton(execContext, properties, obj);
358     ParseShadow(properties, obj);
359     ParseBorderWidthAndColor(properties, obj);
360     ParseRadius(properties, obj);
361     ParseDialogAlignment(properties, obj);
362     ParseOffset(properties, obj);
363     ParseMaskRect(properties, obj);
364     ParseDialogLevelMode(properties, obj);
365 
366     auto onLanguageChange = [execContext, obj, parseContent = ParseTitleAndMessage, parseButton = ParseConfirmButton,
367                                 parseShadow = ParseShadow, parseBorderProps = ParseBorderWidthAndColor,
368                                 parseRadius = ParseRadius, parseAlignment = ParseDialogAlignment,
369                                 parseOffset = ParseOffset,  parseMaskRect = ParseMaskRect,
370                                 parseDialogLevelMode = ParseDialogLevelMode,
371                                 node = dialogNode](DialogProperties& dialogProps) {
372         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execContext);
373         ACE_SCORING_EVENT("ActionSheet.property.onLanguageChange");
374         auto pipelineContext = PipelineContext::GetCurrentContextSafely();
375         CHECK_NULL_VOID(pipelineContext);
376         pipelineContext->UpdateCurrentActiveNode(node);
377         parseContent(dialogProps, obj);
378         parseButton(execContext, dialogProps, obj);
379         parseShadow(dialogProps, obj);
380         parseBorderProps(dialogProps, obj);
381         parseRadius(dialogProps, obj);
382         ParseDialogAlignment(dialogProps, obj);
383         parseOffset(dialogProps, obj);
384         parseMaskRect(dialogProps, obj);
385         parseDialogLevelMode(dialogProps, obj);
386         // Parse sheets
387         auto sheetsVal = obj->GetProperty("sheets");
388         if (sheetsVal->IsArray()) {
389             std::vector<ActionSheetInfo> sheetsInfo;
390             auto sheetsArr = JSRef<JSArray>::Cast(sheetsVal);
391             for (size_t index = 0; index < sheetsArr->Length(); ++index) {
392                 sheetsInfo.emplace_back(ParseSheetInfo(execContext, sheetsArr->GetValueAt(index)));
393             }
394             dialogProps.sheetsInfo = std::move(sheetsInfo);
395         }
396     };
397     properties.onLanguageChange = std::move(onLanguageChange);
398 
399     // Parse auto autoCancel.
400     auto autoCancelValue = obj->GetProperty("autoCancel");
401     if (autoCancelValue->IsBoolean()) {
402         properties.autoCancel = autoCancelValue->ToBoolean();
403     }
404 
405     // Parse cancel.
406     auto cancelValue = obj->GetProperty("cancel");
407     if (cancelValue->IsFunction()) {
408         auto cancelFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(cancelValue));
409         auto eventFunc = [execContext, func = std::move(cancelFunc), node = dialogNode]() {
410             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execContext);
411             ACE_SCORING_EVENT("ActionSheet.cancel");
412             auto pipelineContext = PipelineContext::GetCurrentContextSafely();
413             CHECK_NULL_VOID(pipelineContext);
414             pipelineContext->UpdateCurrentActiveNode(node);
415             func->Execute();
416         };
417         ActionSheetModel::GetInstance()->SetCancel(eventFunc, properties);
418     }
419 
420     std::function<void(const int32_t& info)> onWillDismissFunc = nullptr;
421     ParseDialogCallback(obj, onWillDismissFunc);
422     ActionSheetModel::GetInstance()->SetOnWillDismiss(std::move(onWillDismissFunc), properties);
423 
424     // Parse sheets
425     auto sheetsVal = obj->GetProperty("sheets");
426     if (sheetsVal->IsArray()) {
427         std::vector<ActionSheetInfo> sheetsInfo;
428         auto sheetsArr = JSRef<JSArray>::Cast(sheetsVal);
429         for (size_t index = 0; index < sheetsArr->Length(); ++index) {
430             sheetsInfo.emplace_back(ParseSheetInfo(execContext, sheetsArr->GetValueAt(index)));
431         }
432         properties.sheetsInfo = std::move(sheetsInfo);
433     }
434 
435     // Parses gridCount.
436     auto gridCountValue = obj->GetProperty("gridCount");
437     if (gridCountValue->IsNumber()) {
438         properties.gridCount = gridCountValue->ToNumber<int32_t>();
439     }
440 
441     // Parse showInSubWindowValue.
442     auto showInSubWindowValue = obj->GetProperty("showInSubWindow");
443     if (showInSubWindowValue->IsBoolean()) {
444 #if defined(PREVIEW)
445         LOGW("[Engine Log] Unable to use the SubWindow in the Previewer. Perform this operation on the "
446              "emulator or a real device instead.");
447 #else
448         properties.isShowInSubWindow = showInSubWindowValue->ToBoolean();
449 #endif
450     }
451 
452     // Parse isModalValue.
453     auto isModalValue = obj->GetProperty("isModal");
454     if (isModalValue->IsBoolean()) {
455         LOGI("Parse isModalValue");
456         properties.isModal = isModalValue->ToBoolean();
457     }
458 
459     auto backgroundColorValue = obj->GetProperty("backgroundColor");
460     Color backgroundColor;
461     if (JSViewAbstract::ParseJsColor(backgroundColorValue, backgroundColor)) {
462         properties.backgroundColor = backgroundColor;
463     }
464 
465     auto backgroundBlurStyle = obj->GetProperty("backgroundBlurStyle");
466     if (backgroundBlurStyle->IsNumber()) {
467         auto blurStyle = backgroundBlurStyle->ToNumber<int32_t>();
468         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
469             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
470             properties.backgroundBlurStyle = blurStyle;
471         }
472     }
473     // Parse transition.
474     properties.transitionEffect = ParseJsTransitionEffect(args);
475     JSViewAbstract::SetDialogProperties(obj, properties);
476     JSViewAbstract::SetDialogHoverModeProperties(obj, properties);
477     ActionSheetModel::GetInstance()->ShowActionSheet(properties);
478     args.SetReturnValue(args.This());
479 }
480 
JSBind(BindingTarget globalObj)481 void JSActionSheet::JSBind(BindingTarget globalObj)
482 {
483     JSClass<JSActionSheet>::Declare("ActionSheet");
484     JSClass<JSActionSheet>::StaticMethod("show", &JSActionSheet::Show);
485     JSClass<JSActionSheet>::InheritAndBind<JSViewAbstract>(globalObj);
486 }
487 } // namespace OHOS::Ace::Framework
488