• 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 "frameworks/bridge/declarative_frontend/jsview/js_view_functions.h"
17 
18 #include <memory>
19 
20 #include "base/log/ace_trace.h"
21 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
22 #include "core/components_ng/base/frame_node.h"
23 #include "core/components_ng/layout/layout_wrapper.h"
24 #include "core/pipeline/base/composed_element.h"
25 #include "frameworks/bridge/declarative_frontend/engine/js_execution_scope_defines.h"
26 #include "frameworks/bridge/declarative_frontend/jsview/js_view.h"
27 #include "frameworks/bridge/declarative_frontend/jsview/js_view_measure_layout.h"
28 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
29 
30 namespace OHOS::Ace::Framework {
31 
32 #ifdef USE_ARK_ENGINE
33 
34 namespace {
35 
GenConstraint(const std::optional<NG::LayoutConstraintF> & parentConstraint)36 JSRef<JSObject> GenConstraint(const std::optional<NG::LayoutConstraintF>& parentConstraint)
37 {
38     auto minSize = parentConstraint->minSize;
39     auto maxSize = parentConstraint->maxSize;
40     JSRef<JSObject> constraint = JSRef<JSObject>::New();
41     constraint->SetProperty<double>("minWidth", minSize.Width());
42     constraint->SetProperty<double>("minHeight", minSize.Height());
43     constraint->SetProperty<double>("maxWidth", maxSize.Width());
44     constraint->SetProperty<double>("maxHeight", maxSize.Height());
45     return constraint;
46 }
47 
GenPadding(const std::unique_ptr<NG::PaddingProperty> & paddingNative)48 JSRef<JSObject> GenPadding(const std::unique_ptr<NG::PaddingProperty>& paddingNative)
49 {
50     JSRef<JSObject> padding = JSRef<JSObject>::New();
51     padding->SetProperty("top", paddingNative->top->ToString());
52     padding->SetProperty("right", paddingNative->right->ToString());
53     padding->SetProperty("bottom", paddingNative->bottom->ToString());
54     padding->SetProperty("left", paddingNative->left->ToString());
55     return padding;
56 }
57 
GenEdgeWidths(const std::unique_ptr<NG::BorderWidthProperty> & edgeWidthsNative)58 JSRef<JSObject> GenEdgeWidths(const std::unique_ptr<NG::BorderWidthProperty>& edgeWidthsNative)
59 {
60     JSRef<JSObject> edgeWidths = JSRef<JSObject>::New();
61     edgeWidths->SetProperty("top", edgeWidthsNative->topDimen->ToString());
62     edgeWidths->SetProperty("right", edgeWidthsNative->rightDimen->ToString());
63     edgeWidths->SetProperty("bottom", edgeWidthsNative->bottomDimen->ToString());
64     edgeWidths->SetProperty("left", edgeWidthsNative->leftDimen->ToString());
65     return edgeWidths;
66 }
67 
GenBorderInfo(const RefPtr<NG::LayoutWrapper> & layoutWrapper)68 JSRef<JSObject> GenBorderInfo(const RefPtr<NG::LayoutWrapper>& layoutWrapper)
69 {
70     JSRef<JSObject> borderInfo = JSRef<JSObject>::New();
71     auto layoutProperty = layoutWrapper->GetLayoutProperty();
72     if (!layoutProperty) {
73         return borderInfo;
74     }
75 
76     const std::unique_ptr<NG::PaddingProperty> defaultPadding = std::make_unique<NG::PaddingProperty>();
77     const std::unique_ptr<NG::BorderWidthProperty>& defaultEdgeWidth = std::make_unique<NG::BorderWidthProperty>();
78     borderInfo->SetPropertyObject("borderWidth",
79         GenEdgeWidths(
80             layoutProperty->GetBorderWidthProperty() ? layoutProperty->GetBorderWidthProperty() : defaultEdgeWidth));
81 
82     borderInfo->SetPropertyObject("margin",
83         GenPadding(layoutProperty->GetMarginProperty() ? layoutProperty->GetMarginProperty() : defaultPadding));
84     borderInfo->SetPropertyObject("padding",
85         GenPadding(layoutProperty->GetPaddingProperty() ? layoutProperty->GetPaddingProperty() : defaultPadding));
86 
87     return borderInfo;
88 }
89 
GenPositionInfo(const RefPtr<NG::LayoutWrapper> & layoutWrapper)90 JSRef<JSObject> GenPositionInfo(const RefPtr<NG::LayoutWrapper>& layoutWrapper)
91 {
92     auto offset = layoutWrapper->GetGeometryNode()->GetFrameOffset();
93     JSRef<JSObject> position = JSRef<JSObject>::New();
94     position->SetProperty("x", offset.GetX());
95     position->SetProperty("y", offset.GetY());
96     return position;
97 }
98 
FillSubComponetProperty(JSRef<JSObject> & info,const RefPtr<NG::LayoutWrapper> & layoutWrapper,const size_t & index)99 void FillSubComponetProperty(JSRef<JSObject>& info, const RefPtr<NG::LayoutWrapper>& layoutWrapper, const size_t& index)
100 {
101     info->SetProperty<std::string>("name", layoutWrapper->GetHostNode()->GetTag());
102     info->SetProperty<std::string>("id", std::to_string(layoutWrapper->GetHostNode()->GetId()));
103     info->SetPropertyObject("constraint", GenConstraint(layoutWrapper->GetLayoutProperty()->GetLayoutConstraint()));
104     info->SetPropertyObject("borderInfo", GenBorderInfo(layoutWrapper));
105     info->SetPropertyObject("position", GenPositionInfo(layoutWrapper));
106 }
107 
GenLayoutChildArray(std::list<RefPtr<NG::LayoutWrapper>> children)108 JSRef<JSArray> GenLayoutChildArray(std::list<RefPtr<NG::LayoutWrapper>> children)
109 {
110     JSRef<JSArray> childInfo = JSRef<JSArray>::New();
111     JSRef<JSFunc> layoutFunc = JSRef<JSFunc>::New<FunctionCallback>(ViewMeasureLayout::JSLayout);
112     size_t index = 0;
113 
114     for (const auto& iter : children) {
115         JSRef<JSObject> info = JSRef<JSObject>::New();
116         FillSubComponetProperty(info, iter, index);
117         info->SetPropertyObject("layout", layoutFunc);
118         childInfo->SetValueAt(index++, info);
119     }
120 
121     return childInfo;
122 }
123 
GenMeasureChildArray(std::list<RefPtr<NG::LayoutWrapper>> children)124 JSRef<JSArray> GenMeasureChildArray(std::list<RefPtr<NG::LayoutWrapper>> children)
125 {
126     JSRef<JSArray> childInfo = JSRef<JSArray>::New();
127     JSRef<JSFunc> measureFunc = JSRef<JSFunc>::New<FunctionCallback>(ViewMeasureLayout::JSMeasure);
128     size_t index = 0;
129 
130     for (const auto& iter : children) {
131         JSRef<JSObject> info = JSRef<JSObject>::New();
132         FillSubComponetProperty(info, iter, index);
133         info->SetPropertyObject("measure", measureFunc);
134         childInfo->SetValueAt(index++, info);
135     }
136 
137     return childInfo;
138 }
139 
140 } // namespace
141 
ExecuteLayout(NG::LayoutWrapper * layoutWrapper)142 void ViewFunctions::ExecuteLayout(NG::LayoutWrapper* layoutWrapper)
143 {
144     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
145     ACE_SCOPED_TRACE("ViewFunctions::ExecuteLayout");
146     auto children = layoutWrapper->GetAllChildrenWithBuild();
147     auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
148     auto constraint = GenConstraint(parentConstraint);
149     auto childArray = GenLayoutChildArray(children);
150     JSRef<JSVal> params[2] = { childArray, constraint };
151 
152     ViewMeasureLayout::SetLayoutChildren(layoutWrapper->GetAllChildrenWithBuild());
153     ViewMeasureLayout::SetDefaultMeasureConstraint(parentConstraint.value());
154     jsLayoutFunc_.Lock()->Call(jsObject_.Lock(), 2, params);
155 }
156 
ExecuteMeasure(NG::LayoutWrapper * layoutWrapper)157 void ViewFunctions::ExecuteMeasure(NG::LayoutWrapper* layoutWrapper)
158 {
159     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
160     ACE_SCOPED_TRACE("ViewFunctions::ExecuteMeasure");
161     auto children = layoutWrapper->GetAllChildrenWithBuild();
162     auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
163     auto constraint = GenConstraint(parentConstraint);
164     auto childArray = GenMeasureChildArray(children);
165     JSRef<JSVal> params[2];
166 
167     params[0] = childArray;
168     params[1] = constraint;
169 
170     ViewMeasureLayout::SetMeasureChildren(children);
171     ViewMeasureLayout::SetDefaultMeasureConstraint(parentConstraint.value());
172     jsMeasureFunc_.Lock()->Call(jsObject_.Lock(), 2, params);
173 }
174 
ExecuteReload(bool deep)175 void ViewFunctions::ExecuteReload(bool deep)
176 {
177     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
178     ACE_SCOPED_TRACE("ViewFunctions::ExecuteReload");
179     auto func = jsReloadFunc_.Lock();
180     if (!func.IsEmpty()) {
181         JSRef<JSVal> params[1];
182         params[0] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(deep)));
183         func->Call(jsObject_.Lock(), 1, params);
184     } else {
185         LOGE("the reload func is null");
186     }
187 }
188 
ExecuteForceNodeRerender(int32_t elemId)189 void ViewFunctions::ExecuteForceNodeRerender(int32_t elemId)
190 {
191     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
192     ACE_SCOPED_TRACE("ViewFunctions::ExecuteForceNodeRerender");
193     auto func = jsForceRerenderNodeFunc_.Lock();
194     if (!func.IsEmpty()) {
195         JSRef<JSVal> params[1];
196         params[0] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(elemId)));
197         func->Call(jsObject_.Lock(), 1, params);
198     } else {
199         LOGE("the force node rerender func is null");
200     }
201 }
202 
203 #else
204 
205 void ViewFunctions::ExecuteLayout(NG::LayoutWrapper* layoutWrapper) {}
206 
207 void ViewFunctions::ExecuteMeasure(NG::LayoutWrapper* layoutWrapper) {}
208 
209 void ViewFunctions::ExecuteReload(bool deep) {}
210 
211 void ViewFunctions::ExecuteForceNodeRerender(int32_t elemId) {}
212 
213 #endif
214 
InitViewFunctions(const JSRef<JSObject> & jsObject,const JSRef<JSFunc> & jsRenderFunction,bool partialUpdate)215 void ViewFunctions::InitViewFunctions(
216     const JSRef<JSObject>& jsObject, const JSRef<JSFunc>& jsRenderFunction, bool partialUpdate)
217 {
218     jsObject_ = jsObject;
219 
220     if (partialUpdate) {
221         if (jsObject->GetProperty("initialRender")->IsFunction()) {
222             JSRef<JSVal> jsRenderFunc = jsObject->GetProperty("initialRenderView");
223             if (jsRenderFunc->IsFunction()) {
224                 jsRenderFunc_ = JSRef<JSFunc>::Cast(jsRenderFunc);
225             } else {
226                 LOGE("View lacks mandatory 'initialRenderView()' function, fatal internal error.");
227             }
228         } else {
229             LOGE("View lacks mandatory 'initialRender()' function, fatal internal error.");
230         }
231 
232         JSRef<JSVal> jsRerenderFunc = jsObject->GetProperty("rerender");
233         if (jsRerenderFunc->IsFunction()) {
234             jsRerenderFunc_ = JSRef<JSFunc>::Cast(jsRerenderFunc);
235         } else {
236             LOGE("View lacks mandatory 'rerender()' function, fatal internal error.");
237         }
238 
239         JSRef<JSVal> jsReloadFunc = jsObject->GetProperty("forceCompleteRerender");
240         if (jsReloadFunc->IsFunction()) {
241             jsReloadFunc_ = JSRef<JSFunc>::Cast(jsReloadFunc);
242         } else {
243             LOGE("View lacks mandatory 'forceCompleteRerender()' function, fatal internal error.");
244         }
245 
246         JSRef<JSVal> jsForceRerenderNodeFunc = jsObject->GetProperty("forceRerenderNode");
247         if (jsReloadFunc->IsFunction()) {
248             jsForceRerenderNodeFunc_ = JSRef<JSFunc>::Cast(jsForceRerenderNodeFunc);
249         } else {
250             LOGE("View lacks mandatory 'forceRerenderNode()' function, fatal internal error.");
251         }
252     }
253 
254     JSRef<JSVal> jsAppearFunc = jsObject->GetProperty("aboutToAppear");
255     if (jsAppearFunc->IsFunction()) {
256         jsAppearFunc_ = JSRef<JSFunc>::Cast(jsAppearFunc);
257     }
258 
259     JSRef<JSVal> jsDisappearFunc = jsObject->GetProperty("aboutToDisappear");
260     if (jsDisappearFunc->IsFunction()) {
261         jsDisappearFunc_ = JSRef<JSFunc>::Cast(jsDisappearFunc);
262     } else {
263         LOGD("aboutToDisappear is not a function");
264     }
265 
266     JSRef<JSVal> jsLayoutFunc = jsObject->GetProperty("onLayout");
267     if (jsLayoutFunc->IsFunction()) {
268         jsLayoutFunc_ = JSRef<JSFunc>::Cast(jsLayoutFunc);
269     }
270 
271     JSRef<JSVal> jsMeasureFunc = jsObject->GetProperty("onMeasure");
272     if (jsMeasureFunc->IsFunction()) {
273         jsMeasureFunc_ = JSRef<JSFunc>::Cast(jsMeasureFunc);
274     }
275 
276     JSRef<JSVal> jsAboutToBeDeletedFunc = jsObject->GetProperty("aboutToBeDeleted");
277     if (jsAboutToBeDeletedFunc->IsFunction()) {
278         jsAboutToBeDeletedFunc_ = JSRef<JSFunc>::Cast(jsAboutToBeDeletedFunc);
279     } else {
280         LOGD("aboutToBeDeleted is not a function");
281     }
282 
283     JSRef<JSVal> jsAboutToRenderFunc = jsObject->GetProperty("aboutToRender");
284     if (jsAboutToRenderFunc->IsFunction()) {
285         jsAboutToRenderFunc_ = JSRef<JSFunc>::Cast(jsAboutToRenderFunc);
286     } else {
287         LOGD("aboutToRender is not a function");
288     }
289 
290     JSRef<JSVal> jsRenderDoneFunc = jsObject->GetProperty("onRenderDone");
291     if (jsRenderDoneFunc->IsFunction()) {
292         jsRenderDoneFunc_ = JSRef<JSFunc>::Cast(jsRenderDoneFunc);
293     } else {
294         LOGD("onRenderDone is not a function");
295     }
296 
297     JSRef<JSVal> jsAboutToBuildFunc = jsObject->GetProperty("aboutToBuild");
298     if (jsAboutToBuildFunc->IsFunction()) {
299         jsAboutToBuildFunc_ = JSRef<JSFunc>::Cast(jsAboutToBuildFunc);
300     } else {
301         LOGD("aboutToBuild is not a function");
302     }
303 
304     JSRef<JSVal> jsBuildDoneFunc = jsObject->GetProperty("onBuildDone");
305     if (jsBuildDoneFunc->IsFunction()) {
306         jsBuildDoneFunc_ = JSRef<JSFunc>::Cast(jsBuildDoneFunc);
307     } else {
308         LOGD("onBuildDone is not a function");
309     }
310 
311     JSRef<JSVal> jsTransitionFunc = jsObject->GetProperty("pageTransition");
312     if (jsTransitionFunc->IsFunction()) {
313         jsTransitionFunc_ = JSRef<JSFunc>::Cast(jsTransitionFunc);
314     } else {
315         LOGD("transition is not a function");
316     }
317 
318     JSRef<JSVal> jsOnHideFunc = jsObject->GetProperty("onPageHide");
319     if (jsOnHideFunc->IsFunction()) {
320         jsOnHideFunc_ = JSRef<JSFunc>::Cast(jsOnHideFunc);
321     } else {
322         LOGD("onHide is not a function");
323     }
324 
325     JSRef<JSVal> jsOnShowFunc = jsObject->GetProperty("onPageShow");
326     if (jsOnShowFunc->IsFunction()) {
327         jsOnShowFunc_ = JSRef<JSFunc>::Cast(jsOnShowFunc);
328     } else {
329         LOGD("onShow is not a function");
330     }
331 
332     JSRef<JSVal> jsBackPressFunc = jsObject->GetProperty("onBackPress");
333     if (jsBackPressFunc->IsFunction()) {
334         jsBackPressFunc_ = JSRef<JSFunc>::Cast(jsBackPressFunc);
335     } else {
336         LOGD("onBackPress is not a function");
337     }
338 
339     JSRef<JSVal> jsSetInitiallyProvidedValueFunc = jsObject->GetProperty("setInitiallyProvidedValue");
340     if (jsSetInitiallyProvidedValueFunc->IsFunction()) {
341         jsSetInitiallyProvidedValueFunc_ = JSRef<JSFunc>::Cast(jsSetInitiallyProvidedValueFunc);
342     }
343 
344     if (!partialUpdate) {
345         JSRef<JSVal> jsUpdateWithValueParamsFunc = jsObject->GetProperty("updateWithValueParams");
346         if (jsUpdateWithValueParamsFunc->IsFunction()) {
347             LOGD("updateWithValueParams is a function");
348             jsUpdateWithValueParamsFunc_ = JSRef<JSFunc>::Cast(jsUpdateWithValueParamsFunc);
349         } else {
350             LOGD("updateWithValueParams is not a function");
351         }
352 
353 #ifdef UICAST_COMPONENT_SUPPORTED
354         JSRef<JSVal> jsCreateChildViewFunc = jsObject->GetProperty("createChildView");
355         if (jsCreateChildViewFunc->IsFunction()) {
356             LOGI("UICast createChildView is a function");
357             jsCreateChildViewFunc_ = JSRef<JSFunc>::Cast(jsCreateChildViewFunc);
358         } else {
359             LOGI("UICast createChildView is not a function");
360         }
361 
362         JSRef<JSVal> jsRouterHandleFunc = jsObject->GetProperty("routerHandle");
363         if (jsRouterHandleFunc->IsFunction()) {
364             LOGI("UICast routerHandle is a function");
365             jsRouterHandleFunc_ = JSRef<JSFunc>::Cast(jsRouterHandleFunc);
366         } else {
367             LOGI("UICast routerHandle is not a function");
368         }
369 
370         JSRef<JSVal> jsReplayOnEventFunc = jsObject->GetProperty("replayOnEvent");
371         if (jsReplayOnEventFunc->IsFunction()) {
372             LOGI("UICast replayOnEvent is a function");
373             jsReplayOnEventFunc_ = JSRef<JSFunc>::Cast(jsReplayOnEventFunc);
374         } else {
375             LOGI("UICast replayOnEvent is not a function");
376         }
377 #endif
378 
379         jsRenderFunc_ = jsRenderFunction;
380     }
381 }
382 
ViewFunctions(const JSRef<JSObject> & jsObject,const JSRef<JSFunc> & jsRenderFunction)383 ViewFunctions::ViewFunctions(const JSRef<JSObject>& jsObject, const JSRef<JSFunc>& jsRenderFunction)
384 {
385     ACE_DCHECK(jsObject);
386     InitViewFunctions(jsObject, jsRenderFunction, false);
387 }
388 
ExecuteRender()389 void ViewFunctions::ExecuteRender()
390 {
391     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
392     if (jsRenderFunc_.IsEmpty()) {
393         LOGE("no render function in View!");
394         return;
395     }
396 
397     auto func = jsRenderFunc_.Lock();
398     JSRef<JSVal> jsThis = jsObject_.Lock();
399     jsRenderResult_ = func->Call(jsThis);
400 }
401 
ExecuteAppear()402 void ViewFunctions::ExecuteAppear()
403 {
404     ExecuteFunction(jsAppearFunc_, "aboutToAppear");
405 }
406 
ExecuteDisappear()407 void ViewFunctions::ExecuteDisappear()
408 {
409     ExecuteFunction(jsDisappearFunc_, "aboutToDisappear");
410 }
411 
HasLayout() const412 bool ViewFunctions::HasLayout() const
413 {
414     return !jsLayoutFunc_.IsEmpty();
415 }
416 
HasMeasure() const417 bool ViewFunctions::HasMeasure() const
418 {
419     return !jsMeasureFunc_.IsEmpty();
420 }
421 
ExecuteAboutToBeDeleted()422 void ViewFunctions::ExecuteAboutToBeDeleted()
423 {
424     ExecuteFunction(jsAboutToBeDeletedFunc_, "aboutToDisappear");
425 }
426 
ExecuteAboutToRender()427 void ViewFunctions::ExecuteAboutToRender()
428 {
429     // for developer callback.
430     ExecuteFunction(jsAboutToBuildFunc_, "aboutToBuild");
431     // for state manager mark rendering progress.
432     ExecuteFunction(jsAboutToRenderFunc_, "aboutToRender");
433 }
434 
ExecuteOnRenderDone()435 void ViewFunctions::ExecuteOnRenderDone()
436 {
437     // for state manager reset rendering progress.
438     ExecuteFunction(jsRenderDoneFunc_, "onRenderDone");
439     // for developer callback.
440     ExecuteFunction(jsBuildDoneFunc_, "onBuildDone");
441 }
442 
ExecuteTransition()443 void ViewFunctions::ExecuteTransition()
444 {
445     ExecuteFunction(jsTransitionFunc_, "pageTransition");
446 }
447 
HasPageTransition() const448 bool ViewFunctions::HasPageTransition() const
449 {
450     return !jsTransitionFunc_.IsEmpty();
451 }
452 
ExecuteShow()453 void ViewFunctions::ExecuteShow()
454 {
455     ExecuteFunction(jsOnShowFunc_, "onPageShow");
456 }
457 
ExecuteHide()458 void ViewFunctions::ExecuteHide()
459 {
460     ExecuteFunction(jsOnHideFunc_, "onPageHide");
461 }
462 
ExecuteInitiallyProvidedValue(const std::string & jsonData)463 void ViewFunctions::ExecuteInitiallyProvidedValue(const std::string& jsonData)
464 {
465     ExecuteFunctionWithParams(jsSetInitiallyProvidedValueFunc_, "setInitiallyProvidedValue", jsonData);
466 }
467 
468 // Method not needed for Partial Update code path
ExecuteUpdateWithValueParams(const std::string & jsonData)469 void ViewFunctions::ExecuteUpdateWithValueParams(const std::string& jsonData)
470 {
471     ExecuteFunctionWithParams(jsUpdateWithValueParamsFunc_, "updateWithValueParams", jsonData);
472 }
473 
474 #ifdef UICAST_COMPONENT_SUPPORTED
ExecuteCreateChildView(const std::string & jsonData)475 void ViewFunctions::ExecuteCreateChildView(const std::string& jsonData)
476 {
477     ExecuteFunctionWithParams(jsCreateChildViewFunc_, "createChildView", jsonData);
478 }
479 
ExecuteRouterHandle(const std::string & jsonData)480 void ViewFunctions::ExecuteRouterHandle(const std::string& jsonData)
481 {
482     ExecuteFunctionWithParams(jsRouterHandleFunc_, "routerHandle", jsonData);
483 }
484 
ExecuteReplayOnEvent(const std::string & jsonData)485 void ViewFunctions::ExecuteReplayOnEvent(const std::string& jsonData)
486 {
487     ExecuteFunctionWithParams(jsReplayOnEventFunc_, "replayOnEvent", jsonData);
488 }
489 #endif
490 
ExecuteOnBackPress()491 bool ViewFunctions::ExecuteOnBackPress()
492 {
493     auto ret = ExecuteFunctionWithReturn(jsBackPressFunc_, "onBackPress");
494     if (!ret->IsEmpty() && ret->IsBoolean()) {
495         return ret->ToBoolean();
496     }
497     return false;
498 }
499 
ExecuteFunction(JSWeak<JSFunc> & func,const char * debugInfo)500 void ViewFunctions::ExecuteFunction(JSWeak<JSFunc>& func, const char* debugInfo)
501 {
502     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
503     if (func.IsEmpty()) {
504         LOGD("View doesn't have %{public}s() method!", debugInfo);
505         return;
506     }
507     ACE_SCOPED_TRACE("%s", debugInfo);
508     JSRef<JSVal> jsObject = jsObject_.Lock();
509     func.Lock()->Call(jsObject);
510 }
511 
ExecuteFunctionWithReturn(JSWeak<JSFunc> & func,const char * debugInfo)512 JSRef<JSVal> ViewFunctions::ExecuteFunctionWithReturn(JSWeak<JSFunc>& func, const char* debugInfo)
513 {
514     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_, JSRef<JSVal>::Make())
515     if (func.IsEmpty()) {
516         LOGD("View doesn't have %{public}s() method!", debugInfo);
517         return JSRef<JSVal>::Make();
518     }
519     ACE_SCOPED_TRACE("%s", debugInfo);
520     JSRef<JSVal> jsObject = jsObject_.Lock();
521     JSRef<JSVal> result = func.Lock()->Call(jsObject);
522     if (result.IsEmpty()) {
523         LOGE("Error calling %{public}s", debugInfo);
524     }
525     return result;
526 }
527 
ExecuteFunctionWithParams(JSWeak<JSFunc> & func,const char * debugInfo,const std::string & jsonData)528 void ViewFunctions::ExecuteFunctionWithParams(JSWeak<JSFunc>& func, const char* debugInfo, const std::string& jsonData)
529 {
530     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
531     if (func.IsEmpty()) {
532         LOGD("View doesn't have %{public}s() method!", debugInfo);
533         return;
534     }
535 
536     JSRef<JSObject> obj = JSRef<JSObject>::New();
537     JSRef<JSVal> param = obj->ToJsonObject(jsonData.c_str());
538 
539     JSRef<JSVal> jsObject = jsObject_.Lock();
540     JSRef<JSVal> result = func.Lock()->Call(jsObject, 1, &param);
541     if (result.IsEmpty()) {
542         LOGE("Error calling %{public}s", debugInfo);
543     }
544 }
545 
546 // Baseline version of Destroy
Destroy(JSView * parentCustomView)547 void ViewFunctions::Destroy(JSView* parentCustomView)
548 {
549     LOGD("Destroy");
550     // Might be called from parent view, before any result has been produced??
551     if (jsRenderResult_.IsEmpty()) {
552         LOGD("ViewFunctions::Destroy() -> no previous render result to delete");
553         return;
554     }
555 
556     auto renderRes = jsRenderResult_.Lock();
557     if (renderRes.IsEmpty() || !renderRes->IsObject()) {
558         LOGD("ViewFunctions::Destroy() -> result not an object");
559         return;
560     }
561 
562     JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
563     if (!obj.IsEmpty()) {
564         // jsRenderResult_ maybe an js exception, not a JSView
565         JSView* view = obj->Unwrap<JSView>();
566         if (view != nullptr) {
567             view->Destroy(parentCustomView);
568         }
569     }
570     jsRenderResult_.Reset();
571     LOGD("ViewFunctions::Destroy() end");
572 }
573 
574 // PartialUpdate version of Destroy
Destroy()575 void ViewFunctions::Destroy()
576 {
577     LOGD("Destroy");
578 
579     // Might be called from parent view, before any result has been produced??
580     if (jsRenderResult_.IsEmpty()) {
581         LOGD("ViewFunctions::Destroy() -> no previous render result to delete");
582         return;
583     }
584 
585     auto renderRes = jsRenderResult_.Lock();
586     if (renderRes.IsEmpty() || !renderRes->IsObject()) {
587         LOGD("ViewFunctions::Destroy() -> result not an object");
588         return;
589     }
590 
591     // merging: when would a render function return a JSView ?
592     JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
593     if (!obj.IsEmpty()) {
594         // jsRenderResult_ maybe an js exception, not a JSView
595         JSView* view = obj->Unwrap<JSView>();
596         if (view != nullptr) {
597             LOGE("NOTE NOTE NOTE render returned a JSView object that's dangling!");
598         }
599     }
600     jsObject_.Reset();
601     jsRenderResult_.Reset();
602 
603     LOGD("ViewFunctions::Destroy() end");
604 }
605 
606 // Partial update method
ExecuteRerender()607 void ViewFunctions::ExecuteRerender()
608 {
609     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
610     if (jsRerenderFunc_.IsEmpty()) {
611         LOGE("no rerender function in View!");
612         return;
613     }
614 
615     auto func = jsRerenderFunc_.Lock();
616     JSRef<JSVal> jsThis = jsObject_.Lock();
617     jsRenderResult_ = func->Call(jsThis);
618 }
619 
620 // Partial update method
ViewFunctions(const JSRef<JSObject> & jsObject)621 ViewFunctions::ViewFunctions(const JSRef<JSObject>& jsObject)
622 {
623     InitViewFunctions(jsObject, JSRef<JSFunc>(), true);
624 }
625 
626 } // namespace OHOS::Ace::Framework
627