• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "bridge/declarative_frontend/jsview/js_view_functions.h"
17 
18 #include <memory>
19 #include <string>
20 
21 #include "base/geometry/calc_dimension.h"
22 #include "base/geometry/dimension.h"
23 #include "base/log/ace_performance_check.h"
24 #include "base/log/ace_trace.h"
25 #include "bridge/declarative_frontend/engine/js_execution_scope_defines.h"
26 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
27 #include "bridge/declarative_frontend/jsview/js_view.h"
28 #include "bridge/declarative_frontend/jsview/js_view_measure_layout.h"
29 #include "bridge/declarative_frontend/view_stack_processor.h"
30 #include "core/components_ng/base/frame_node.h"
31 #include "core/components_ng/layout/layout_wrapper.h"
32 #include "core/pipeline/base/composed_element.h"
33 
34 namespace OHOS::Ace::Framework {
35 
36 #ifdef USE_ARK_ENGINE
37 
38 namespace {
39 
GenConstraint(const std::optional<NG::LayoutConstraintF> & parentConstraint)40 JSRef<JSObject> GenConstraint(const std::optional<NG::LayoutConstraintF>& parentConstraint)
41 {
42     auto minSize = parentConstraint->minSize;
43     auto maxSize = parentConstraint->maxSize;
44     JSRef<JSObject> constraint = JSRef<JSObject>::New();
45     constraint->SetProperty<double>("minWidth", minSize.Width());
46     constraint->SetProperty<double>("minHeight", minSize.Height());
47     constraint->SetProperty<double>("maxWidth", maxSize.Width());
48     constraint->SetProperty<double>("maxHeight", maxSize.Height());
49     return constraint;
50 }
51 
GenPadding(const std::unique_ptr<NG::PaddingProperty> & paddingNative)52 JSRef<JSObject> GenPadding(const std::unique_ptr<NG::PaddingProperty>& paddingNative)
53 {
54     JSRef<JSObject> padding = JSRef<JSObject>::New();
55     padding->SetProperty("top", paddingNative->top->ToString());
56     padding->SetProperty("right", paddingNative->right->ToString());
57     padding->SetProperty("bottom", paddingNative->bottom->ToString());
58     padding->SetProperty("left", paddingNative->left->ToString());
59     return padding;
60 }
61 
GenEdgeWidths(const std::unique_ptr<NG::BorderWidthProperty> & edgeWidthsNative)62 JSRef<JSObject> GenEdgeWidths(const std::unique_ptr<NG::BorderWidthProperty>& edgeWidthsNative)
63 {
64     JSRef<JSObject> edgeWidths = JSRef<JSObject>::New();
65     edgeWidths->SetProperty("top", edgeWidthsNative->topDimen->ToString());
66     edgeWidths->SetProperty("right", edgeWidthsNative->rightDimen->ToString());
67     edgeWidths->SetProperty("bottom", edgeWidthsNative->bottomDimen->ToString());
68     edgeWidths->SetProperty("left", edgeWidthsNative->leftDimen->ToString());
69     return edgeWidths;
70 }
71 
GenBorderInfo(const RefPtr<NG::LayoutWrapper> & layoutWrapper)72 JSRef<JSObject> GenBorderInfo(const RefPtr<NG::LayoutWrapper>& layoutWrapper)
73 {
74     JSRef<JSObject> borderInfo = JSRef<JSObject>::New();
75     auto layoutProperty = layoutWrapper->GetLayoutProperty();
76     if (!layoutProperty) {
77         return borderInfo;
78     }
79 
80     const std::unique_ptr<NG::PaddingProperty> defaultPadding = std::make_unique<NG::PaddingProperty>();
81     const std::unique_ptr<NG::BorderWidthProperty>& defaultEdgeWidth = std::make_unique<NG::BorderWidthProperty>();
82     borderInfo->SetPropertyObject("borderWidth",
83         GenEdgeWidths(
84             layoutProperty->GetBorderWidthProperty() ? layoutProperty->GetBorderWidthProperty() : defaultEdgeWidth));
85 
86     borderInfo->SetPropertyObject("margin",
87         GenPadding(layoutProperty->GetMarginProperty() ? layoutProperty->GetMarginProperty() : defaultPadding));
88     borderInfo->SetPropertyObject("padding",
89         GenPadding(layoutProperty->GetPaddingProperty() ? layoutProperty->GetPaddingProperty() : defaultPadding));
90 
91     return borderInfo;
92 }
93 
GenPositionInfo(const RefPtr<NG::LayoutWrapper> & layoutWrapper)94 JSRef<JSObject> GenPositionInfo(const RefPtr<NG::LayoutWrapper>& layoutWrapper)
95 {
96     auto offset = layoutWrapper->GetGeometryNode()->GetFrameOffset();
97     JSRef<JSObject> position = JSRef<JSObject>::New();
98     position->SetProperty("x", offset.GetX());
99     position->SetProperty("y", offset.GetY());
100     return position;
101 }
102 
GenSelfLayoutInfo(NG::LayoutWrapper * layoutWrapper)103 JSRef<JSObject> GenSelfLayoutInfo(NG::LayoutWrapper* layoutWrapper)
104 {
105     JSRef<JSObject> selfLayoutInfo = JSRef<JSObject>::New();
106     auto layoutProperty = layoutWrapper->GetLayoutProperty();
107     if (!layoutProperty) {
108         return selfLayoutInfo;
109     }
110 
111     const std::unique_ptr<NG::PaddingProperty> defaultPadding = std::make_unique<NG::PaddingProperty>();
112     const std::unique_ptr<NG::BorderWidthProperty>& defaultEdgeWidth = std::make_unique<NG::BorderWidthProperty>();
113     selfLayoutInfo->SetPropertyObject("borderWidth",
114         GenEdgeWidths(
115             layoutProperty->GetBorderWidthProperty() ? layoutProperty->GetBorderWidthProperty() : defaultEdgeWidth));
116     selfLayoutInfo->SetPropertyObject("margin",
117         GenPadding(layoutProperty->GetMarginProperty() ? layoutProperty->GetMarginProperty() : defaultPadding));
118     selfLayoutInfo->SetPropertyObject("padding",
119         GenPadding(layoutProperty->GetPaddingProperty() ? layoutProperty->GetPaddingProperty() : defaultPadding));
120     selfLayoutInfo->SetProperty(
121         "width", layoutProperty->GetCalcLayoutConstraint()
122                      ? layoutProperty->GetCalcLayoutConstraint()->selfIdealSize->Width()->GetDimension().ConvertToVp()
123                      : 0.0f);
124     selfLayoutInfo->SetProperty(
125         "height", layoutProperty->GetCalcLayoutConstraint()
126                       ? layoutProperty->GetCalcLayoutConstraint()->selfIdealSize->Height()->GetDimension().ConvertToVp()
127                       : 0.0f);
128 
129     return selfLayoutInfo;
130 }
131 
FillSubComponetProperty(JSRef<JSObject> & info,const RefPtr<NG::LayoutWrapper> & layoutWrapper,const size_t & index)132 void FillSubComponetProperty(JSRef<JSObject>& info, const RefPtr<NG::LayoutWrapper>& layoutWrapper, const size_t& index)
133 {
134     info->SetProperty<std::string>("name", layoutWrapper->GetHostNode()->GetTag());
135     info->SetProperty<std::string>("id", std::to_string(layoutWrapper->GetHostNode()->GetId()));
136     info->SetPropertyObject("constraint", GenConstraint(layoutWrapper->GetLayoutProperty()->GetLayoutConstraint()));
137     info->SetPropertyObject("borderInfo", GenBorderInfo(layoutWrapper));
138     info->SetPropertyObject("position", GenPositionInfo(layoutWrapper));
139 }
140 
FillPlaceSizeProperty(JSRef<JSObject> & info,const RefPtr<NG::LayoutWrapper> & layoutWrapper)141 void FillPlaceSizeProperty(JSRef<JSObject>& info, const RefPtr<NG::LayoutWrapper>& layoutWrapper)
142 {
143     auto frameRect = layoutWrapper->GetGeometryNode()->GetFrameRect();
144     JSRef<JSObject> size = JSRef<JSObject>::New();
145 
146     Dimension measureWidth(frameRect.GetSize().Width(), DimensionUnit::PX);
147     Dimension measureHeight(frameRect.GetSize().Height(), DimensionUnit::PX);
148     size->SetProperty("width", measureWidth.ConvertToVp());
149     size->SetProperty("height", measureHeight.ConvertToVp());
150     info->SetPropertyObject("measureResult", size);
151 }
152 
GenLayoutChildArray(std::list<RefPtr<NG::LayoutWrapper>> children)153 JSRef<JSArray> GenLayoutChildArray(std::list<RefPtr<NG::LayoutWrapper>> children)
154 {
155     JSRef<JSArray> childInfo = JSRef<JSArray>::New();
156     JSRef<JSFunc> layoutFunc = JSRef<JSFunc>::New<FunctionCallback>(ViewMeasureLayout::JSLayout);
157     size_t index = 0;
158 
159     for (const auto& iter : children) {
160         JSRef<JSObject> info = JSRef<JSObject>::New();
161         FillSubComponetProperty(info, iter, index);
162         info->SetPropertyObject("layout", layoutFunc);
163         childInfo->SetValueAt(index++, info);
164     }
165 
166     return childInfo;
167 }
168 
GenPlaceChildrenArray(std::list<RefPtr<NG::LayoutWrapper>> children)169 JSRef<JSArray> GenPlaceChildrenArray(std::list<RefPtr<NG::LayoutWrapper>> children)
170 {
171     JSRef<JSArray> childInfo = JSRef<JSArray>::New();
172     JSRef<JSFunc> layoutFunc = JSRef<JSFunc>::New<FunctionCallback>(ViewMeasureLayout::JSPlaceChildren);
173     size_t index = 0;
174 
175     for (const auto& iter : children) {
176         JSRef<JSObject> info = JSRef<JSObject>::New();
177         FillPlaceSizeProperty(info, iter);
178         info->SetPropertyObject("layout", layoutFunc);
179         childInfo->SetValueAt(index++, info);
180     }
181 
182     return childInfo;
183 }
184 
GenMeasureChildArray(std::list<RefPtr<NG::LayoutWrapper>> children,bool isMeasureSize)185 JSRef<JSArray> GenMeasureChildArray(std::list<RefPtr<NG::LayoutWrapper>> children, bool isMeasureSize)
186 {
187     JSRef<JSArray> childInfo = JSRef<JSArray>::New();
188     JSRef<JSFunc> measureFunc = JSRef<JSFunc>::New<FunctionCallback>(ViewMeasureLayout::JSMeasure);
189     size_t index = 0;
190 
191     for (const auto& iter : children) {
192         JSRef<JSObject> info = JSRef<JSObject>::New();
193         if (!isMeasureSize) {
194             FillSubComponetProperty(info, iter, index);
195         }
196         info->SetPropertyObject("measure", measureFunc);
197         childInfo->SetValueAt(index++, info);
198     }
199 
200     return childInfo;
201 }
202 
203 } // namespace
204 
ExecuteLayout(NG::LayoutWrapper * layoutWrapper)205 void ViewFunctions::ExecuteLayout(NG::LayoutWrapper* layoutWrapper)
206 {
207     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
208     ACE_SCOPED_TRACE("ViewFunctions::ExecuteLayout");
209     auto children = layoutWrapper->GetAllChildrenWithBuild();
210     auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
211     auto constraint = GenConstraint(parentConstraint);
212     auto childArray = GenLayoutChildArray(children);
213     JSRef<JSVal> params[2] = { childArray, constraint };
214 
215     ViewMeasureLayout::SetLayoutChildren(layoutWrapper->GetAllChildrenWithBuild());
216     ViewMeasureLayout::SetDefaultMeasureConstraint(parentConstraint.value());
217     jsLayoutFunc_.Lock()->Call(jsObject_.Lock(), 2, params);
218 
219     for (const auto& child : children) {
220         if (child->GetLayoutProperty()->GetPositionProperty()) {
221             child->Layout();
222         }
223     }
224 }
225 
ExecuteMeasure(NG::LayoutWrapper * layoutWrapper)226 void ViewFunctions::ExecuteMeasure(NG::LayoutWrapper* layoutWrapper)
227 {
228     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
229     ACE_SCOPED_TRACE("ViewFunctions::ExecuteMeasure");
230     auto children = layoutWrapper->GetAllChildrenWithBuild();
231     auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
232     auto constraint = GenConstraint(parentConstraint);
233     auto childArray = GenMeasureChildArray(children, false);
234     JSRef<JSVal> params[2];
235 
236     params[0] = childArray;
237     params[1] = constraint;
238 
239     ViewMeasureLayout::SetMeasureChildren(children);
240     ViewMeasureLayout::SetDefaultMeasureConstraint(parentConstraint.value());
241     jsMeasureFunc_.Lock()->Call(jsObject_.Lock(), 2, params);
242 
243     for (const auto& child : children) {
244         if (child->GetGeometryNode()->GetFrameRect().IsEmpty()) {
245             child->Measure(parentConstraint.value());
246         }
247     }
248 }
249 
ExecutePlaceChildren(NG::LayoutWrapper * layoutWrapper)250 void ViewFunctions::ExecutePlaceChildren(NG::LayoutWrapper* layoutWrapper)
251 {
252     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
253     ACE_SCOPED_TRACE("ViewFunctions::ExecutePlaceChildren");
254     auto children = layoutWrapper->GetAllChildrenWithBuild();
255     auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
256 
257     auto selfLayoutInfo = GenSelfLayoutInfo(layoutWrapper);
258     auto childArray = GenPlaceChildrenArray(children);
259     auto constraint = GenConstraint(parentConstraint);
260 
261     JSRef<JSVal> params[3] = { selfLayoutInfo, childArray, constraint };
262 
263     ViewMeasureLayout::SetLayoutChildren(layoutWrapper->GetAllChildrenWithBuild());
264     ViewMeasureLayout::SetDefaultMeasureConstraint(parentConstraint.value());
265     jsPlaceChildrenFunc_.Lock()->Call(jsObject_.Lock(), 3, params);
266 
267     for (const auto& child : children) {
268         if (child->GetLayoutProperty()->GetPositionProperty()) {
269             child->Layout();
270         }
271     }
272 }
273 
ExecuteMeasureSize(NG::LayoutWrapper * layoutWrapper)274 void ViewFunctions::ExecuteMeasureSize(NG::LayoutWrapper* layoutWrapper)
275 {
276     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
277     ACE_SCOPED_TRACE("ViewFunctions::ExecutePlaceChildren");
278     auto children = layoutWrapper->GetAllChildrenWithBuild();
279     auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
280 
281     auto selfLayoutInfo = GenSelfLayoutInfo(layoutWrapper);
282     auto childArray = GenMeasureChildArray(children, true);
283     auto constraint = GenConstraint(parentConstraint);
284 
285     JSRef<JSVal> params[3];
286 
287     params[0] = selfLayoutInfo;
288     params[1] = childArray;
289     params[2] = constraint;
290 
291     ViewMeasureLayout::SetMeasureChildren(children);
292     ViewMeasureLayout::SetDefaultMeasureConstraint(parentConstraint.value());
293     JSRef<JSObject> result = jsMeasureSizeFunc_.Lock()->Call(jsObject_.Lock(), 3, params);
294 
295     for (const auto& child : children) {
296         if (child->GetGeometryNode()->GetFrameRect().IsEmpty()) {
297             child->Measure(parentConstraint.value());
298         }
299     }
300 
301     CalcDimension measureWidth;
302     CalcDimension measureHeight;
303     if (!JSViewAbstract::ParseJsDimensionVp(result->GetProperty("width"), measureWidth)) {
304         measureWidth = { -1.0f };
305     }
306     if (!JSViewAbstract::ParseJsDimensionVp(result->GetProperty("height"), measureHeight)) {
307         measureWidth = { -1.0f };
308     }
309     NG::SizeF frameSize = { measureWidth.ConvertToPx(), measureHeight.ConvertToPx() };
310     layoutWrapper->GetGeometryNode()->SetFrameSize(frameSize);
311     NG::CalcSize idealSize = { NG::CalcLength(measureWidth.ConvertToPx()),
312         NG::CalcLength(measureHeight.ConvertToPx()) };
313     layoutWrapper->GetLayoutProperty()->UpdateUserDefinedIdealSize(idealSize);
314 }
315 
ExecuteReload(bool deep)316 void ViewFunctions::ExecuteReload(bool deep)
317 {
318     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
319     ACE_SCOPED_TRACE("ViewFunctions::ExecuteReload");
320     auto func = jsReloadFunc_.Lock();
321     if (!func.IsEmpty()) {
322         JSRef<JSVal> params[1];
323         params[0] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(deep)));
324         func->Call(jsObject_.Lock(), 1, params);
325     } else {
326         LOGE("the reload func is null");
327     }
328 }
329 
ExecuteForceNodeRerender(int32_t elemId)330 void ViewFunctions::ExecuteForceNodeRerender(int32_t elemId)
331 {
332     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
333     ACE_SCOPED_TRACE("ViewFunctions::ExecuteForceNodeRerender");
334     auto func = jsForceRerenderNodeFunc_.Lock();
335     if (!func.IsEmpty()) {
336         JSRef<JSVal> params[1];
337         params[0] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(elemId)));
338         func->Call(jsObject_.Lock(), 1, params);
339     } else {
340         LOGE("the force node rerender func is null");
341     }
342 }
343 
ExecuteRecycle(const std::string & viewName)344 void ViewFunctions::ExecuteRecycle(const std::string& viewName)
345 {
346     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
347     ACE_SCOPED_TRACE("ViewFunctions::ExecuteRecycle");
348     auto func = jsRecycleFunc_.Lock();
349     if (!func->IsEmpty()) {
350         auto recycleNodeName = JSRef<JSVal>::Make(ToJSValue(viewName));
351         func->Call(jsObject_.Lock(), 1, &recycleNodeName);
352     } else {
353         LOGE("the recycle func is null");
354     }
355 }
356 
ExecuteSetActive(bool active)357 void ViewFunctions::ExecuteSetActive(bool active)
358 {
359     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
360     auto func = jsSetActive_.Lock();
361     if (!func->IsEmpty()) {
362         auto isActive = JSRef<JSVal>::Make(ToJSValue(active));
363         func->Call(jsObject_.Lock(), 1, &isActive);
364     } else {
365         LOGE("the set active func is null");
366     }
367 }
368 
369 #else
370 
371 void ViewFunctions::ExecuteLayout(NG::LayoutWrapper* layoutWrapper) {}
372 
373 void ViewFunctions::ExecuteMeasure(NG::LayoutWrapper* layoutWrapper) {}
374 
375 void ViewFunctions::ExecutePlaceChildren(NG::LayoutWrapper* layoutWrapper) {}
376 
377 void ViewFunctions::ExecuteMeasureSize(NG::LayoutWrapper* layoutWrapper) {}
378 
379 void ViewFunctions::ExecuteReload(bool deep) {}
380 
381 void ViewFunctions::ExecuteForceNodeRerender(int32_t elemId) {}
382 
383 #endif
384 
InitViewFunctions(const JSRef<JSObject> & jsObject,const JSRef<JSFunc> & jsRenderFunction,bool partialUpdate)385 void ViewFunctions::InitViewFunctions(
386     const JSRef<JSObject>& jsObject, const JSRef<JSFunc>& jsRenderFunction, bool partialUpdate)
387 {
388     jsObject_ = jsObject;
389 
390     if (partialUpdate) {
391         if (jsObject->GetProperty("initialRender")->IsFunction()) {
392             JSRef<JSVal> jsRenderFunc = jsObject->GetProperty("initialRenderView");
393             if (jsRenderFunc->IsFunction()) {
394                 jsRenderFunc_ = JSRef<JSFunc>::Cast(jsRenderFunc);
395             } else {
396                 LOGE("View lacks mandatory 'initialRenderView()' function, fatal internal error.");
397             }
398         } else {
399             LOGE("View lacks mandatory 'initialRender()' function, fatal internal error.");
400         }
401 
402         JSRef<JSVal> jsRerenderFunc = jsObject->GetProperty("rerender");
403         if (jsRerenderFunc->IsFunction()) {
404             jsRerenderFunc_ = JSRef<JSFunc>::Cast(jsRerenderFunc);
405         } else {
406             LOGE("View lacks mandatory 'rerender()' function, fatal internal error.");
407         }
408 
409         JSRef<JSVal> jsReloadFunc = jsObject->GetProperty("forceCompleteRerender");
410         if (jsReloadFunc->IsFunction()) {
411             jsReloadFunc_ = JSRef<JSFunc>::Cast(jsReloadFunc);
412         } else {
413             LOGE("View lacks mandatory 'forceCompleteRerender()' function, fatal internal error.");
414         }
415 
416         JSRef<JSVal> jsForceRerenderNodeFunc = jsObject->GetProperty("forceRerenderNode");
417         if (jsForceRerenderNodeFunc->IsFunction()) {
418             jsForceRerenderNodeFunc_ = JSRef<JSFunc>::Cast(jsForceRerenderNodeFunc);
419         } else {
420             LOGE("View lacks mandatory 'forceRerenderNode()' function, fatal internal error.");
421         }
422 
423         JSRef<JSVal> jsRecycleFunc = jsObject->GetProperty("recycleSelf");
424         if (jsRecycleFunc->IsFunction()) {
425             jsRecycleFunc_ = JSRef<JSFunc>::Cast(jsRecycleFunc);
426         } else {
427             LOGD("View is not a recycle node");
428         }
429 
430         JSRef<JSVal> jsAboutToRecycleFunc = jsObject->GetProperty("aboutToRecycle");
431         if (jsAboutToRecycleFunc->IsFunction()) {
432             jsAboutToRecycleFunc_ = JSRef<JSFunc>::Cast(jsAboutToRecycleFunc);
433         }
434 
435         JSRef<JSVal> jsSetActive = jsObject->GetProperty("setActiveInternal");
436         if (jsSetActive->IsFunction()) {
437             jsSetActive_ = JSRef<JSFunc>::Cast(jsSetActive);
438         } else {
439             LOGD("View don't have the ability to prevent inactive update");
440         }
441     }
442 
443     JSRef<JSVal> jsAppearFunc = jsObject->GetProperty("aboutToAppear");
444     if (jsAppearFunc->IsFunction()) {
445         jsAppearFunc_ = JSRef<JSFunc>::Cast(jsAppearFunc);
446     }
447 
448     JSRef<JSVal> jsDisappearFunc = jsObject->GetProperty("aboutToDisappear");
449     if (jsDisappearFunc->IsFunction()) {
450         jsDisappearFunc_ = JSRef<JSFunc>::Cast(jsDisappearFunc);
451     } else {
452         LOGD("aboutToDisappear is not a function");
453     }
454 
455     JSRef<JSVal> jsLayoutFunc = jsObject->GetProperty("onLayout");
456     if (jsLayoutFunc->IsFunction()) {
457         jsLayoutFunc_ = JSRef<JSFunc>::Cast(jsLayoutFunc);
458     }
459 
460     JSRef<JSVal> jsMeasureFunc = jsObject->GetProperty("onMeasure");
461     if (jsMeasureFunc->IsFunction()) {
462         jsMeasureFunc_ = JSRef<JSFunc>::Cast(jsMeasureFunc);
463     }
464 
465     JSRef<JSVal> jsPlaceChildrenFunc = jsObject->GetProperty("onPlaceChildren");
466     if (jsPlaceChildrenFunc->IsFunction()) {
467         jsPlaceChildrenFunc_ = JSRef<JSFunc>::Cast(jsPlaceChildrenFunc);
468     }
469 
470     JSRef<JSVal> jsMeasureSizeFunc = jsObject->GetProperty("onMeasureSize");
471     if (jsMeasureSizeFunc->IsFunction()) {
472         jsMeasureSizeFunc_ = JSRef<JSFunc>::Cast(jsMeasureSizeFunc);
473     }
474 
475     JSRef<JSVal> jsAboutToBeDeletedFunc = jsObject->GetProperty("aboutToBeDeleted");
476     if (jsAboutToBeDeletedFunc->IsFunction()) {
477         jsAboutToBeDeletedFunc_ = JSRef<JSFunc>::Cast(jsAboutToBeDeletedFunc);
478     } else {
479         LOGD("aboutToBeDeleted is not a function");
480     }
481 
482     JSRef<JSVal> jsAboutToRenderFunc = jsObject->GetProperty("aboutToRender");
483     if (jsAboutToRenderFunc->IsFunction()) {
484         jsAboutToRenderFunc_ = JSRef<JSFunc>::Cast(jsAboutToRenderFunc);
485     } else {
486         LOGD("aboutToRender is not a function");
487     }
488 
489     JSRef<JSVal> jsRenderDoneFunc = jsObject->GetProperty("onRenderDone");
490     if (jsRenderDoneFunc->IsFunction()) {
491         jsRenderDoneFunc_ = JSRef<JSFunc>::Cast(jsRenderDoneFunc);
492     } else {
493         LOGD("onRenderDone is not a function");
494     }
495 
496     JSRef<JSVal> jsAboutToBuildFunc = jsObject->GetProperty("aboutToBuild");
497     if (jsAboutToBuildFunc->IsFunction()) {
498         jsAboutToBuildFunc_ = JSRef<JSFunc>::Cast(jsAboutToBuildFunc);
499     } else {
500         LOGD("aboutToBuild is not a function");
501     }
502 
503     JSRef<JSVal> jsBuildDoneFunc = jsObject->GetProperty("onBuildDone");
504     if (jsBuildDoneFunc->IsFunction()) {
505         jsBuildDoneFunc_ = JSRef<JSFunc>::Cast(jsBuildDoneFunc);
506     } else {
507         LOGD("onBuildDone is not a function");
508     }
509 
510     JSRef<JSVal> jsTransitionFunc = jsObject->GetProperty("pageTransition");
511     if (jsTransitionFunc->IsFunction()) {
512         jsTransitionFunc_ = JSRef<JSFunc>::Cast(jsTransitionFunc);
513     } else {
514         LOGD("transition is not a function");
515     }
516 
517     JSRef<JSVal> jsOnHideFunc = jsObject->GetProperty("onPageHide");
518     if (jsOnHideFunc->IsFunction()) {
519         jsOnHideFunc_ = JSRef<JSFunc>::Cast(jsOnHideFunc);
520     } else {
521         LOGD("onHide is not a function");
522     }
523 
524     JSRef<JSVal> jsOnShowFunc = jsObject->GetProperty("onPageShow");
525     if (jsOnShowFunc->IsFunction()) {
526         jsOnShowFunc_ = JSRef<JSFunc>::Cast(jsOnShowFunc);
527     } else {
528         LOGD("onShow is not a function");
529     }
530 
531     JSRef<JSVal> jsBackPressFunc = jsObject->GetProperty("onBackPress");
532     if (jsBackPressFunc->IsFunction()) {
533         jsBackPressFunc_ = JSRef<JSFunc>::Cast(jsBackPressFunc);
534     } else {
535         LOGD("onBackPress is not a function");
536     }
537 
538     JSRef<JSVal> jsSetInitiallyProvidedValueFunc = jsObject->GetProperty("setInitiallyProvidedValue");
539     if (jsSetInitiallyProvidedValueFunc->IsFunction()) {
540         jsSetInitiallyProvidedValueFunc_ = JSRef<JSFunc>::Cast(jsSetInitiallyProvidedValueFunc);
541     }
542 
543     if (!partialUpdate) {
544         JSRef<JSVal> jsUpdateWithValueParamsFunc = jsObject->GetProperty("updateWithValueParams");
545         if (jsUpdateWithValueParamsFunc->IsFunction()) {
546             LOGD("updateWithValueParams is a function");
547             jsUpdateWithValueParamsFunc_ = JSRef<JSFunc>::Cast(jsUpdateWithValueParamsFunc);
548         } else {
549             LOGD("updateWithValueParams is not a function");
550         }
551         jsRenderFunc_ = jsRenderFunction;
552     }
553 }
554 
ViewFunctions(const JSRef<JSObject> & jsObject,const JSRef<JSFunc> & jsRenderFunction)555 ViewFunctions::ViewFunctions(const JSRef<JSObject>& jsObject, const JSRef<JSFunc>& jsRenderFunction)
556 {
557     ACE_DCHECK(jsObject);
558     InitViewFunctions(jsObject, jsRenderFunction, false);
559 }
560 
ExecuteRender()561 void ViewFunctions::ExecuteRender()
562 {
563     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
564     if (jsRenderFunc_.IsEmpty()) {
565         LOGE("no render function in View!");
566         return;
567     }
568 
569     auto func = jsRenderFunc_.Lock();
570     JSRef<JSVal> jsThis = jsObject_.Lock();
571     if (!jsThis->IsUndefined()) {
572         jsRenderResult_ = func->Call(jsThis);
573     } else {
574         LOGE("jsView Object is undefined and will not execute render function");
575     }
576 }
577 
ExecuteAppear()578 void ViewFunctions::ExecuteAppear()
579 {
580     ExecuteFunction(jsAppearFunc_, "aboutToAppear");
581 }
582 
ExecuteDisappear()583 void ViewFunctions::ExecuteDisappear()
584 {
585     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
586     if (jsDisappearFunc_.IsEmpty()) {
587         LOGD("View doesn't have %{public}s() method!", "aboutToDisappear");
588         return;
589     }
590     ACE_SCOPED_TRACE("%s", "aboutToDisappear");
591     JSRef<JSVal> jsObject = jsObject_.Lock();
592     std::string functionName("aboutToDisappear");
593     AceScopedPerformanceCheck scoped(functionName);
594     if (!jsObject->IsUndefined()) {
595         jsDisappearFunc_.Lock()->Call(jsObject);
596     } else {
597         LOGE("jsView Object is undefined and will not execute aboutToDisappear function");
598     }
599 }
600 
ExecuteAboutToRecycle()601 void ViewFunctions::ExecuteAboutToRecycle()
602 {
603     ExecuteFunction(jsAboutToRecycleFunc_, "aboutToRecycle");
604 }
605 
HasLayout() const606 bool ViewFunctions::HasLayout() const
607 {
608     return !jsLayoutFunc_.IsEmpty();
609 }
610 
HasMeasure() const611 bool ViewFunctions::HasMeasure() const
612 {
613     return !jsMeasureFunc_.IsEmpty();
614 }
615 
HasPlaceChildren() const616 bool ViewFunctions::HasPlaceChildren() const
617 {
618     return !jsPlaceChildrenFunc_.IsEmpty();
619 }
620 
HasMeasureSize() const621 bool ViewFunctions::HasMeasureSize() const
622 {
623     return !jsMeasureSizeFunc_.IsEmpty();
624 }
625 
ExecuteAboutToBeDeleted()626 void ViewFunctions::ExecuteAboutToBeDeleted()
627 {
628     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
629     if (jsAboutToBeDeletedFunc_.IsEmpty()) {
630         LOGD("View doesn't have %{public}s() method!", "aboutToBeDeleted");
631         return;
632     }
633     ACE_SCOPED_TRACE("%s", "aboutToBeDeleted");
634     JSRef<JSVal> jsObject = jsObject_.Lock();
635     std::string functionName("aboutToBeDeleted");
636     AceScopedPerformanceCheck scoped(functionName);
637     if (!jsObject->IsUndefined()) {
638         jsAboutToBeDeletedFunc_.Lock()->Call(jsObject);
639     } else {
640         LOGE("jsView Object is undefined and will not execute aboutToBeDeleted function");
641     }
642 }
643 
ExecuteAboutToRender()644 void ViewFunctions::ExecuteAboutToRender()
645 {
646     // for developer callback.
647     ExecuteFunction(jsAboutToBuildFunc_, "aboutToBuild");
648     // for state manager mark rendering progress.
649     ExecuteFunction(jsAboutToRenderFunc_, "aboutToRender");
650 }
651 
ExecuteOnRenderDone()652 void ViewFunctions::ExecuteOnRenderDone()
653 {
654     // for state manager reset rendering progress.
655     ExecuteFunction(jsRenderDoneFunc_, "onRenderDone");
656     // for developer callback.
657     ExecuteFunction(jsBuildDoneFunc_, "onBuildDone");
658 }
659 
ExecuteTransition()660 void ViewFunctions::ExecuteTransition()
661 {
662     ExecuteFunction(jsTransitionFunc_, "pageTransition");
663 }
664 
HasPageTransition() const665 bool ViewFunctions::HasPageTransition() const
666 {
667     return !jsTransitionFunc_.IsEmpty();
668 }
669 
ExecuteShow()670 void ViewFunctions::ExecuteShow()
671 {
672     ExecuteFunction(jsOnShowFunc_, "onPageShow");
673 }
674 
ExecuteHide()675 void ViewFunctions::ExecuteHide()
676 {
677     ExecuteFunction(jsOnHideFunc_, "onPageHide");
678 }
679 
ExecuteInitiallyProvidedValue(const std::string & jsonData)680 void ViewFunctions::ExecuteInitiallyProvidedValue(const std::string& jsonData)
681 {
682     ExecuteFunctionWithParams(jsSetInitiallyProvidedValueFunc_, "setInitiallyProvidedValue", jsonData);
683 }
684 
685 // Method not needed for Partial Update code path
ExecuteUpdateWithValueParams(const std::string & jsonData)686 void ViewFunctions::ExecuteUpdateWithValueParams(const std::string& jsonData)
687 {
688     ExecuteFunctionWithParams(jsUpdateWithValueParamsFunc_, "updateWithValueParams", jsonData);
689 }
690 
ExecuteOnBackPress()691 bool ViewFunctions::ExecuteOnBackPress()
692 {
693     auto ret = ExecuteFunctionWithReturn(jsBackPressFunc_, "onBackPress");
694     if (!ret->IsEmpty() && ret->IsBoolean()) {
695         return ret->ToBoolean();
696     }
697     return false;
698 }
699 
ExecuteFunction(JSWeak<JSFunc> & func,const char * debugInfo)700 void ViewFunctions::ExecuteFunction(JSWeak<JSFunc>& func, const char* debugInfo)
701 {
702     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
703     if (func.IsEmpty()) {
704         LOGD("View doesn't have %{public}s() method!", debugInfo);
705         return;
706     }
707     ACE_SCOPED_TRACE("%s", debugInfo);
708     JSRef<JSVal> jsObject = jsObject_.Lock();
709     if (!jsObject->IsUndefined()) {
710         std::string functionName(debugInfo);
711         AceScopedPerformanceCheck scoped(functionName);
712         func.Lock()->Call(jsObject);
713     } else {
714         LOGE("jsObject is undefined. Internal error while trying to exec %{public}s", debugInfo);
715     }
716 }
717 
ExecuteFunctionWithReturn(JSWeak<JSFunc> & func,const char * debugInfo)718 JSRef<JSVal> ViewFunctions::ExecuteFunctionWithReturn(JSWeak<JSFunc>& func, const char* debugInfo)
719 {
720     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_, JSRef<JSVal>::Make())
721     if (func.IsEmpty()) {
722         LOGD("View doesn't have %{public}s() method!", debugInfo);
723         return JSRef<JSVal>::Make();
724     }
725     ACE_SCOPED_TRACE("%s", debugInfo);
726     JSRef<JSVal> jsObject = jsObject_.Lock();
727     std::string functionName(debugInfo);
728     AceScopedPerformanceCheck scoped(functionName);
729     JSRef<JSVal> result = func.Lock()->Call(jsObject);
730     if (result.IsEmpty()) {
731         LOGE("Error calling %{public}s", debugInfo);
732     }
733     return result;
734 }
735 
ExecuteFunctionWithParams(JSWeak<JSFunc> & func,const char * debugInfo,const std::string & jsonData)736 void ViewFunctions::ExecuteFunctionWithParams(JSWeak<JSFunc>& func, const char* debugInfo, const std::string& jsonData)
737 {
738     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
739     if (func.IsEmpty()) {
740         LOGD("View doesn't have %{public}s() method!", debugInfo);
741         return;
742     }
743 
744     JSRef<JSObject> obj = JSRef<JSObject>::New();
745     JSRef<JSVal> param = obj->ToJsonObject(jsonData.c_str());
746 
747     JSRef<JSVal> jsObject = jsObject_.Lock();
748     JSRef<JSVal> result = func.Lock()->Call(jsObject, 1, &param);
749     if (result.IsEmpty()) {
750         LOGE("Error calling %{public}s", debugInfo);
751     }
752 }
753 
754 // Baseline version of Destroy
Destroy(JSView * parentCustomView)755 void ViewFunctions::Destroy(JSView* parentCustomView)
756 {
757     LOGD("Destroy");
758     // Might be called from parent view, before any result has been produced??
759     if (jsRenderResult_.IsEmpty()) {
760         LOGD("ViewFunctions::Destroy() -> no previous render result to delete");
761         return;
762     }
763 
764     auto renderRes = jsRenderResult_.Lock();
765     if (renderRes.IsEmpty() || !renderRes->IsObject()) {
766         LOGD("ViewFunctions::Destroy() -> result not an object");
767         return;
768     }
769 
770     JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
771     if (!obj.IsEmpty()) {
772         // jsRenderResult_ maybe an js exception, not a JSView
773         JSView* view = obj->Unwrap<JSView>();
774         if (view != nullptr) {
775             view->Destroy(parentCustomView);
776         }
777     }
778     jsRenderResult_.Reset();
779     LOGD("ViewFunctions::Destroy() end");
780 }
781 
782 // PartialUpdate version of Destroy
Destroy()783 void ViewFunctions::Destroy()
784 {
785     LOGD("Destroy");
786 
787     // Might be called from parent view, before any result has been produced??
788     if (jsRenderResult_.IsEmpty()) {
789         LOGD("ViewFunctions::Destroy() -> no previous render result to delete");
790         return;
791     }
792 
793     auto renderRes = jsRenderResult_.Lock();
794     if (renderRes.IsEmpty() || !renderRes->IsObject()) {
795         LOGD("ViewFunctions::Destroy() -> result not an object");
796         return;
797     }
798 
799     // merging: when would a render function return a JSView ?
800     JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
801     if (!obj.IsEmpty()) {
802         // jsRenderResult_ maybe an js exception, not a JSView
803         JSView* view = obj->Unwrap<JSView>();
804         if (view != nullptr) {
805             LOGE("NOTE NOTE NOTE render returned a JSView object that's dangling!");
806         }
807     }
808     jsObject_.Reset();
809     jsRenderResult_.Reset();
810 
811     LOGD("ViewFunctions::Destroy() end");
812 }
813 
814 // Partial update method
ExecuteRerender()815 void ViewFunctions::ExecuteRerender()
816 {
817     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
818     if (jsRerenderFunc_.IsEmpty()) {
819         LOGE("no rerender function in View!");
820         return;
821     }
822 
823     auto func = jsRerenderFunc_.Lock();
824     JSRef<JSVal> jsThis = jsObject_.Lock();
825     if (!jsThis->IsUndefined()) {
826         jsRenderResult_ = func->Call(jsThis);
827     } else {
828         LOGE("jsView Object is undefined and will not execute rerender function");
829     }
830 }
831 
832 // Partial update method
ViewFunctions(const JSRef<JSObject> & jsObject)833 ViewFunctions::ViewFunctions(const JSRef<JSObject>& jsObject)
834 {
835     InitViewFunctions(jsObject, JSRef<JSFunc>(), true);
836 }
837 
838 } // namespace OHOS::Ace::Framework
839