• 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 "base/utils/utils.h"
26 #include "bridge/declarative_frontend/engine/js_execution_scope_defines.h"
27 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
28 #include "bridge/declarative_frontend/jsview/js_view.h"
29 #include "bridge/declarative_frontend/jsview/js_view_measure_layout.h"
30 #include "bridge/declarative_frontend/view_stack_processor.h"
31 #include "core/components_ng/base/frame_node.h"
32 #include "core/components_ng/layout/layout_property.h"
33 #include "core/components_ng/layout/layout_wrapper.h"
34 #include "core/components_ng/pattern/custom/custom_measure_layout_param.h"
35 #include "core/pipeline/base/composed_element.h"
36 
37 namespace OHOS::Ace::Framework {
38 const std::string EMPTY_STATUS_DATA = "empty_status_data";
39 
40 #ifdef USE_ARK_ENGINE
41 
ExecuteLayout(NG::LayoutWrapper * layoutWrapper)42 void ViewFunctions::ExecuteLayout(NG::LayoutWrapper* layoutWrapper)
43 {
44     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
45     ACE_SCOPED_TRACE("ViewFunctions::ExecuteLayout");
46     auto jsParam = JSMeasureLayoutParam::GetInstance(layoutWrapper);
47     auto constraint = jsParam->GetConstraint();
48     auto childArray = jsParam->GetChildArray();
49     JSRef<JSVal> params[2] = { childArray, constraint };
50     jsLayoutFunc_.Lock()->Call(jsObject_.Lock(), 2, params);
51 }
52 
ExecuteMeasure(NG::LayoutWrapper * layoutWrapper)53 void ViewFunctions::ExecuteMeasure(NG::LayoutWrapper* layoutWrapper)
54 {
55     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
56     ACE_SCOPED_TRACE("ViewFunctions::ExecuteMeasure");
57     auto jsParam = JSMeasureLayoutParam::GetInstance(layoutWrapper);
58     auto constraint = jsParam->GetConstraint();
59     auto childArray = jsParam->GetChildArray();
60     JSRef<JSVal> params[2] = { childArray, constraint };
61     jsMeasureFunc_.Lock()->Call(jsObject_.Lock(), 2, params);
62 }
63 
ExecutePlaceChildren(NG::LayoutWrapper * layoutWrapper)64 void ViewFunctions::ExecutePlaceChildren(NG::LayoutWrapper* layoutWrapper)
65 {
66     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
67     ACE_SCOPED_TRACE("ViewFunctions::ExecutePlaceChildren");
68     auto jsParam = JSMeasureLayoutParamNG::GetInstance(layoutWrapper);
69 
70     auto selfLayoutInfo = jsParam->GetSelfLayoutInfo();
71     auto childArray = jsParam->GetChildArray();
72     auto constraint = jsParam->GetConstraint();
73 
74     JSRef<JSVal> params[3] = { selfLayoutInfo, childArray, constraint };
75     jsPlaceChildrenFunc_.Lock()->Call(jsObject_.Lock(), 3, params); /* 3:params number */
76 }
77 
InitJsParam(NG::LayoutWrapper * layoutWrapper)78 void ViewFunctions::InitJsParam(NG::LayoutWrapper* layoutWrapper)
79 {
80     JSMeasureLayoutParamNG::GetInstance(layoutWrapper);
81 }
82 
ExecuteMeasureSize(NG::LayoutWrapper * layoutWrapper)83 void ViewFunctions::ExecuteMeasureSize(NG::LayoutWrapper* layoutWrapper)
84 {
85     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
86     ACE_SCOPED_TRACE("ViewFunctions::ExecuteMeasureSize");
87     auto jsParam = JSMeasureLayoutParamNG::GetInstance(layoutWrapper);
88 
89     auto selfLayoutInfo = jsParam->GetSelfLayoutInfo();
90     auto childArray = jsParam->GetChildArray();
91     auto constraint = jsParam->GetConstraint();
92 
93     JSRef<JSVal> params[3] = { selfLayoutInfo, childArray, constraint };
94     JSRef<JSObject> result = jsMeasureSizeFunc_.Lock()->Call(jsObject_.Lock(), 3, params); /* 3:params number */
95 
96     CalcDimension measureWidth;
97     CalcDimension measureHeight;
98     if (!JSViewAbstract::ParseJsDimensionVp(result->GetProperty("width"), measureWidth)) {
99         measureWidth = { -1.0f };
100     }
101     if (!JSViewAbstract::ParseJsDimensionVp(result->GetProperty("height"), measureHeight)) {
102         measureWidth = { -1.0f };
103     }
104     NG::SizeF frameSize = { measureWidth.ConvertToPx(), measureHeight.ConvertToPx() };
105     layoutWrapper->GetGeometryNode()->SetFrameSize(frameSize);
106 }
107 
ExecuteReload(bool deep)108 void ViewFunctions::ExecuteReload(bool deep)
109 {
110     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
111     ACE_SCOPED_TRACE("ViewFunctions::ExecuteReload");
112     auto func = jsReloadFunc_.Lock();
113     if (!func.IsEmpty()) {
114         JSRef<JSVal> params[1];
115         params[0] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(deep)));
116         func->Call(jsObject_.Lock(), 1, params);
117     } else {
118         LOGE("the reload func is null");
119     }
120 }
121 
ExecuteForceNodeRerender(int32_t elemId)122 void ViewFunctions::ExecuteForceNodeRerender(int32_t elemId)
123 {
124     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
125     ACE_SCOPED_TRACE("ViewFunctions::ExecuteForceNodeRerender");
126     auto func = jsForceRerenderNodeFunc_.Lock();
127     if (!func.IsEmpty()) {
128         JSRef<JSVal> params[1];
129         params[0] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(elemId)));
130         func->Call(jsObject_.Lock(), 1, params);
131     } else {
132         LOGE("the force node rerender func is null");
133     }
134 }
135 
ExecuteRecycle(const std::string & viewName)136 void ViewFunctions::ExecuteRecycle(const std::string& viewName)
137 {
138     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
139     ACE_SCOPED_TRACE("ViewFunctions::ExecuteRecycle");
140     auto func = jsRecycleFunc_.Lock();
141     if (!func->IsEmpty()) {
142         auto recycleNodeName = JSRef<JSVal>::Make(ToJSValue(viewName));
143         func->Call(jsObject_.Lock(), 1, &recycleNodeName);
144     } else {
145         LOGE("the recycle func is null");
146     }
147 }
148 
ExecuteSetActive(bool active)149 void ViewFunctions::ExecuteSetActive(bool active)
150 {
151     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
152     auto func = jsSetActive_.Lock();
153     if (!func->IsEmpty()) {
154         auto isActive = JSRef<JSVal>::Make(ToJSValue(active));
155         func->Call(jsObject_.Lock(), 1, &isActive);
156     } else {
157         LOGE("the set active func is null");
158     }
159 }
160 
ExecuteOnDumpInfo(const std::vector<std::string> & params)161 void ViewFunctions::ExecuteOnDumpInfo(const std::vector<std::string>& params)
162 {
163     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
164     auto func = jsOnDumpInfo_.Lock();
165     if (!func->IsEmpty()) {
166         JSRef<JSArray> arr = JSRef<JSArray>::New();
167         for (size_t i = 0; i < params.size(); ++i) {
168             arr->SetValueAt(i, JSRef<JSVal>::Make(ToJSValue(params.at(i))));
169         }
170         JSRef<JSVal> argv = arr;
171         func->Call(jsObject_.Lock(), 1, &argv);
172     } else {
173         LOGE("the on dump info func is null");
174     }
175 }
176 
177 #else
178 
ExecuteLayout(NG::LayoutWrapper * layoutWrapper)179 void ViewFunctions::ExecuteLayout(NG::LayoutWrapper* layoutWrapper) {}
180 
ExecuteMeasure(NG::LayoutWrapper * layoutWrapper)181 void ViewFunctions::ExecuteMeasure(NG::LayoutWrapper* layoutWrapper) {}
182 
ExecutePlaceChildren(NG::LayoutWrapper * layoutWrapper)183 void ViewFunctions::ExecutePlaceChildren(NG::LayoutWrapper* layoutWrapper) {}
184 
ExecuteMeasureSize(NG::LayoutWrapper * layoutWrapper)185 void ViewFunctions::ExecuteMeasureSize(NG::LayoutWrapper* layoutWrapper) {}
186 
ExecuteReload(bool deep)187 void ViewFunctions::ExecuteReload(bool deep) {}
188 
ExecuteForceNodeRerender(int32_t elemId)189 void ViewFunctions::ExecuteForceNodeRerender(int32_t elemId) {}
190 
191 #endif
192 
InitViewFunctions(const JSRef<JSObject> & jsObject,const JSRef<JSFunc> & jsRenderFunction,bool partialUpdate)193 void ViewFunctions::InitViewFunctions(
194     const JSRef<JSObject>& jsObject, const JSRef<JSFunc>& jsRenderFunction, bool partialUpdate)
195 {
196     jsObject_ = jsObject;
197 
198     if (partialUpdate) {
199         if (jsObject->GetProperty("initialRender")->IsFunction()) {
200             JSRef<JSVal> jsRenderFunc = jsObject->GetProperty("initialRenderView");
201             if (jsRenderFunc->IsFunction()) {
202                 jsRenderFunc_ = JSRef<JSFunc>::Cast(jsRenderFunc);
203             } else {
204                 LOGE("View lacks mandatory 'initialRenderView()' function, fatal internal error.");
205             }
206         } else {
207             LOGE("View lacks mandatory 'initialRender()' function, fatal internal error.");
208         }
209 
210         JSRef<JSVal> jsRerenderFunc = jsObject->GetProperty("rerender");
211         if (jsRerenderFunc->IsFunction()) {
212             jsRerenderFunc_ = JSRef<JSFunc>::Cast(jsRerenderFunc);
213         } else {
214             LOGE("View lacks mandatory 'rerender()' function, fatal internal error.");
215         }
216 
217         JSRef<JSVal> jsReloadFunc = jsObject->GetProperty("forceCompleteRerender");
218         if (jsReloadFunc->IsFunction()) {
219             jsReloadFunc_ = JSRef<JSFunc>::Cast(jsReloadFunc);
220         } else {
221             LOGE("View lacks mandatory 'forceCompleteRerender()' function, fatal internal error.");
222         }
223 
224         JSRef<JSVal> jsForceRerenderNodeFunc = jsObject->GetProperty("forceRerenderNode");
225         if (jsForceRerenderNodeFunc->IsFunction()) {
226             jsForceRerenderNodeFunc_ = JSRef<JSFunc>::Cast(jsForceRerenderNodeFunc);
227         } else {
228             LOGE("View lacks mandatory 'forceRerenderNode()' function, fatal internal error.");
229         }
230 
231         JSRef<JSVal> jsRecycleFunc = jsObject->GetProperty("recycleSelf");
232         if (jsRecycleFunc->IsFunction()) {
233             jsRecycleFunc_ = JSRef<JSFunc>::Cast(jsRecycleFunc);
234         }
235 
236         JSRef<JSVal> jsAboutToRecycleFunc = jsObject->GetProperty("aboutToRecycleInternal");
237         if (jsAboutToRecycleFunc->IsFunction()) {
238             jsAboutToRecycleFunc_ = JSRef<JSFunc>::Cast(jsAboutToRecycleFunc);
239         }
240 
241         JSRef<JSVal> jsSetActive = jsObject->GetProperty("setActiveInternal");
242         if (jsSetActive->IsFunction()) {
243             jsSetActive_ = JSRef<JSFunc>::Cast(jsSetActive);
244         }
245 
246         JSRef<JSVal> jsOnDumpInfo = jsObject->GetProperty("onDumpInfo");
247         if (jsOnDumpInfo->IsFunction()) {
248             jsOnDumpInfo_ = JSRef<JSFunc>::Cast(jsOnDumpInfo);
249         }
250     }
251 
252     JSRef<JSVal> jsAppearFunc = jsObject->GetProperty("aboutToAppear");
253     if (jsAppearFunc->IsFunction()) {
254         jsAppearFunc_ = JSRef<JSFunc>::Cast(jsAppearFunc);
255     }
256 
257     JSRef<JSVal> jsDisappearFunc = jsObject->GetProperty("aboutToDisappear");
258     if (jsDisappearFunc->IsFunction()) {
259         jsDisappearFunc_ = JSRef<JSFunc>::Cast(jsDisappearFunc);
260     }
261 
262     JSRef<JSVal> jsLayoutFunc = jsObject->GetProperty("onLayout");
263     if (jsLayoutFunc->IsFunction()) {
264         jsLayoutFunc_ = JSRef<JSFunc>::Cast(jsLayoutFunc);
265     }
266 
267     JSRef<JSVal> jsMeasureFunc = jsObject->GetProperty("onMeasure");
268     if (jsMeasureFunc->IsFunction()) {
269         jsMeasureFunc_ = JSRef<JSFunc>::Cast(jsMeasureFunc);
270     }
271 
272     JSRef<JSVal> jsPlaceChildrenFunc = jsObject->GetProperty("onPlaceChildren");
273     if (jsPlaceChildrenFunc->IsFunction()) {
274         jsPlaceChildrenFunc_ = JSRef<JSFunc>::Cast(jsPlaceChildrenFunc);
275     }
276 
277     JSRef<JSVal> jsMeasureSizeFunc = jsObject->GetProperty("onMeasureSize");
278     if (jsMeasureSizeFunc->IsFunction()) {
279         jsMeasureSizeFunc_ = JSRef<JSFunc>::Cast(jsMeasureSizeFunc);
280     }
281 
282     JSRef<JSVal> jsAboutToBeDeletedFunc = jsObject->GetProperty("aboutToBeDeleted");
283     if (jsAboutToBeDeletedFunc->IsFunction()) {
284         jsAboutToBeDeletedFunc_ = JSRef<JSFunc>::Cast(jsAboutToBeDeletedFunc);
285     }
286 
287     JSRef<JSVal> jsAboutToRenderFunc = jsObject->GetProperty("aboutToRender");
288     if (jsAboutToRenderFunc->IsFunction()) {
289         jsAboutToRenderFunc_ = JSRef<JSFunc>::Cast(jsAboutToRenderFunc);
290     }
291 
292     JSRef<JSVal> jsRenderDoneFunc = jsObject->GetProperty("onRenderDone");
293     if (jsRenderDoneFunc->IsFunction()) {
294         jsRenderDoneFunc_ = JSRef<JSFunc>::Cast(jsRenderDoneFunc);
295     }
296 
297     JSRef<JSVal> jsAboutToBuildFunc = jsObject->GetProperty("aboutToBuild");
298     if (jsAboutToBuildFunc->IsFunction()) {
299         jsAboutToBuildFunc_ = JSRef<JSFunc>::Cast(jsAboutToBuildFunc);
300     }
301 
302     JSRef<JSVal> jsBuildDoneFunc = jsObject->GetProperty("onBuildDone");
303     if (jsBuildDoneFunc->IsFunction()) {
304         jsBuildDoneFunc_ = JSRef<JSFunc>::Cast(jsBuildDoneFunc);
305     }
306 
307     JSRef<JSVal> jsTransitionFunc = jsObject->GetProperty("pageTransition");
308     if (jsTransitionFunc->IsFunction()) {
309         jsTransitionFunc_ = JSRef<JSFunc>::Cast(jsTransitionFunc);
310     }
311 
312     JSRef<JSVal> jsOnHideFunc = jsObject->GetProperty("onPageHide");
313     if (jsOnHideFunc->IsFunction()) {
314         jsOnHideFunc_ = JSRef<JSFunc>::Cast(jsOnHideFunc);
315     }
316 
317     JSRef<JSVal> jsOnShowFunc = jsObject->GetProperty("onPageShow");
318     if (jsOnShowFunc->IsFunction()) {
319         jsOnShowFunc_ = JSRef<JSFunc>::Cast(jsOnShowFunc);
320     }
321 
322     JSRef<JSVal> jsBackPressFunc = jsObject->GetProperty("onBackPress");
323     if (jsBackPressFunc->IsFunction()) {
324         jsBackPressFunc_ = JSRef<JSFunc>::Cast(jsBackPressFunc);
325     }
326 
327     JSRef<JSVal> jsSetInitiallyProvidedValueFunc = jsObject->GetProperty("setInitiallyProvidedValue");
328     if (jsSetInitiallyProvidedValueFunc->IsFunction()) {
329         jsSetInitiallyProvidedValueFunc_ = JSRef<JSFunc>::Cast(jsSetInitiallyProvidedValueFunc);
330     }
331 
332     if (!partialUpdate) {
333         JSRef<JSVal> jsUpdateWithValueParamsFunc = jsObject->GetProperty("updateWithValueParams");
334         if (jsUpdateWithValueParamsFunc->IsFunction()) {
335             jsUpdateWithValueParamsFunc_ = JSRef<JSFunc>::Cast(jsUpdateWithValueParamsFunc);
336         }
337         jsRenderFunc_ = jsRenderFunction;
338     }
339 
340     JSRef<JSVal> jsOnFormRecycleFunc = jsObject->GetProperty("onFormRecycle");
341     if (jsOnFormRecycleFunc->IsFunction()) {
342         jsOnFormRecycleFunc_ = JSRef<JSFunc>::Cast(jsOnFormRecycleFunc);
343     }
344 
345     JSRef<JSVal> jsOnFormRecoverFunc = jsObject->GetProperty("onFormRecover");
346     if (jsOnFormRecoverFunc->IsFunction()) {
347         jsOnFormRecoverFunc_ = JSRef<JSFunc>::Cast(jsOnFormRecoverFunc);
348     }
349 }
350 
ViewFunctions(const JSRef<JSObject> & jsObject,const JSRef<JSFunc> & jsRenderFunction)351 ViewFunctions::ViewFunctions(const JSRef<JSObject>& jsObject, const JSRef<JSFunc>& jsRenderFunction)
352 {
353     ACE_DCHECK(jsObject);
354     InitViewFunctions(jsObject, jsRenderFunction, false);
355 }
356 
ExecuteRender()357 void ViewFunctions::ExecuteRender()
358 {
359     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
360     if (jsRenderFunc_.IsEmpty()) {
361         LOGE("no render function in View!");
362         return;
363     }
364 
365     auto func = jsRenderFunc_.Lock();
366     JSRef<JSVal> jsThis = jsObject_.Lock();
367     if (!jsThis->IsUndefined()) {
368         jsRenderResult_ = func->Call(jsThis);
369     } else {
370         LOGE("jsView Object is undefined and will not execute render function");
371     }
372 }
373 
ExecuteAppear()374 void ViewFunctions::ExecuteAppear()
375 {
376     ExecuteFunction(jsAppearFunc_, "aboutToAppear");
377 }
378 
ExecuteDisappear()379 void ViewFunctions::ExecuteDisappear()
380 {
381     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
382     if (jsDisappearFunc_.IsEmpty()) {
383         return;
384     }
385     ACE_SCOPED_TRACE("%s", "aboutToDisappear");
386     JSRef<JSVal> jsObject = jsObject_.Lock();
387     std::string functionName("aboutToDisappear");
388     AceScopedPerformanceCheck scoped(functionName);
389     if (!jsObject->IsUndefined()) {
390         jsDisappearFunc_.Lock()->Call(jsObject);
391     } else {
392         LOGE("jsView Object is undefined and will not execute aboutToDisappear function");
393     }
394 }
395 
ExecuteAboutToRecycle()396 void ViewFunctions::ExecuteAboutToRecycle()
397 {
398     ExecuteFunction(jsAboutToRecycleFunc_, "aboutToRecycleInternal");
399 }
400 
HasLayout() const401 bool ViewFunctions::HasLayout() const
402 {
403     return !jsLayoutFunc_.IsEmpty();
404 }
405 
HasMeasure() const406 bool ViewFunctions::HasMeasure() const
407 {
408     return !jsMeasureFunc_.IsEmpty();
409 }
410 
HasPlaceChildren() const411 bool ViewFunctions::HasPlaceChildren() const
412 {
413     return !jsPlaceChildrenFunc_.IsEmpty();
414 }
415 
HasMeasureSize() const416 bool ViewFunctions::HasMeasureSize() const
417 {
418     return !jsMeasureSizeFunc_.IsEmpty();
419 }
420 
ExecuteAboutToBeDeleted()421 void ViewFunctions::ExecuteAboutToBeDeleted()
422 {
423     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
424     if (jsAboutToBeDeletedFunc_.IsEmpty()) {
425         return;
426     }
427     ACE_SCOPED_TRACE("%s", "aboutToBeDeleted");
428     JSRef<JSVal> jsObject = jsObject_.Lock();
429     std::string functionName("aboutToBeDeleted");
430     AceScopedPerformanceCheck scoped(functionName);
431     if (!jsObject->IsUndefined()) {
432         jsAboutToBeDeletedFunc_.Lock()->Call(jsObject);
433     } else {
434         LOGE("jsView Object is undefined and will not execute aboutToBeDeleted function");
435     }
436 }
437 
ExecuteAboutToRender()438 void ViewFunctions::ExecuteAboutToRender()
439 {
440     // for developer callback.
441     ExecuteFunction(jsAboutToBuildFunc_, "aboutToBuild");
442     // for state manager mark rendering progress.
443     ExecuteFunction(jsAboutToRenderFunc_, "aboutToRender");
444 }
445 
ExecuteOnRenderDone()446 void ViewFunctions::ExecuteOnRenderDone()
447 {
448     // for state manager reset rendering progress.
449     ExecuteFunction(jsRenderDoneFunc_, "onRenderDone");
450     // for developer callback.
451     ExecuteFunction(jsBuildDoneFunc_, "onBuildDone");
452 }
453 
ExecuteTransition()454 void ViewFunctions::ExecuteTransition()
455 {
456     ExecuteFunction(jsTransitionFunc_, "pageTransition");
457 }
458 
HasPageTransition() const459 bool ViewFunctions::HasPageTransition() const
460 {
461     return !jsTransitionFunc_.IsEmpty();
462 }
463 
ExecuteShow()464 void ViewFunctions::ExecuteShow()
465 {
466     ExecuteFunction(jsOnShowFunc_, "onPageShow");
467 }
468 
ExecuteHide()469 void ViewFunctions::ExecuteHide()
470 {
471     ExecuteFunction(jsOnHideFunc_, "onPageHide");
472 }
473 
ExecuteInitiallyProvidedValue(const std::string & jsonData)474 void ViewFunctions::ExecuteInitiallyProvidedValue(const std::string& jsonData)
475 {
476     ExecuteFunctionWithParams(jsSetInitiallyProvidedValueFunc_, "setInitiallyProvidedValue", jsonData);
477 }
478 
479 // Method not needed for Partial Update code path
ExecuteUpdateWithValueParams(const std::string & jsonData)480 void ViewFunctions::ExecuteUpdateWithValueParams(const std::string& jsonData)
481 {
482     ExecuteFunctionWithParams(jsUpdateWithValueParamsFunc_, "updateWithValueParams", jsonData);
483 }
484 
ExecuteOnBackPress()485 bool ViewFunctions::ExecuteOnBackPress()
486 {
487     auto ret = ExecuteFunctionWithReturn(jsBackPressFunc_, "onBackPress");
488     if (!ret->IsEmpty() && ret->IsBoolean()) {
489         return ret->ToBoolean();
490     }
491     return false;
492 }
493 
ExecuteFunction(JSWeak<JSFunc> & func,const char * debugInfo)494 void ViewFunctions::ExecuteFunction(JSWeak<JSFunc>& func, const char* debugInfo)
495 {
496     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
497     if (func.IsEmpty()) {
498         return;
499     }
500     ACE_SCOPED_TRACE("%s", debugInfo);
501     JSRef<JSVal> jsObject = jsObject_.Lock();
502     if (!jsObject->IsUndefined()) {
503         std::string functionName(debugInfo);
504         AceScopedPerformanceCheck scoped(functionName);
505         func.Lock()->Call(jsObject);
506     } else {
507         LOGE("jsObject is undefined. Internal error while trying to exec %{public}s", debugInfo);
508     }
509 }
510 
ExecuteFunctionWithReturn(JSWeak<JSFunc> & func,const char * debugInfo)511 JSRef<JSVal> ViewFunctions::ExecuteFunctionWithReturn(JSWeak<JSFunc>& func, const char* debugInfo)
512 {
513     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_, JSRef<JSVal>::Make())
514     if (func.IsEmpty()) {
515         return JSRef<JSVal>::Make();
516     }
517     ACE_SCOPED_TRACE("%s", debugInfo);
518     JSRef<JSVal> jsObject = jsObject_.Lock();
519     std::string functionName(debugInfo);
520     AceScopedPerformanceCheck scoped(functionName);
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         return;
533     }
534 
535     JSRef<JSObject> obj = JSRef<JSObject>::New();
536     JSRef<JSVal> param = obj->ToJsonObject(jsonData.c_str());
537 
538     JSRef<JSVal> jsObject = jsObject_.Lock();
539     JSRef<JSVal> result = func.Lock()->Call(jsObject, 1, &param);
540     if (result.IsEmpty()) {
541         LOGE("Error calling %{public}s", debugInfo);
542     }
543 }
544 
545 // Baseline version of Destroy
Destroy(JSView * parentCustomView)546 void ViewFunctions::Destroy(JSView* parentCustomView)
547 {
548     // Might be called from parent view, before any result has been produced??
549     if (jsRenderResult_.IsEmpty()) {
550         return;
551     }
552 
553     auto renderRes = jsRenderResult_.Lock();
554     if (renderRes.IsEmpty() || !renderRes->IsObject()) {
555         return;
556     }
557 
558     JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
559     if (!obj.IsEmpty()) {
560         // jsRenderResult_ maybe an js exception, not a JSView
561         JSView* view = obj->Unwrap<JSView>();
562         if (view != nullptr) {
563             view->Destroy(parentCustomView);
564         }
565     }
566     jsRenderResult_.Reset();
567 }
568 
569 // PartialUpdate version of Destroy
Destroy()570 void ViewFunctions::Destroy()
571 {
572     // Might be called from parent view, before any result has been produced??
573     if (jsRenderResult_.IsEmpty()) {
574         return;
575     }
576 
577     auto renderRes = jsRenderResult_.Lock();
578     if (renderRes.IsEmpty() || !renderRes->IsObject()) {
579         return;
580     }
581 
582     // merging: when would a render function return a JSView ?
583     JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
584     if (!obj.IsEmpty()) {
585         // jsRenderResult_ maybe an js exception, not a JSView
586         JSView* view = obj->Unwrap<JSView>();
587         if (view != nullptr) {
588             LOGE("NOTE NOTE NOTE render returned a JSView object that's dangling!");
589         }
590     }
591     jsObject_.Reset();
592     jsRenderResult_.Reset();
593 }
594 
595 // Partial update method
ExecuteRerender()596 void ViewFunctions::ExecuteRerender()
597 {
598     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
599     if (jsRerenderFunc_.IsEmpty()) {
600         LOGE("no rerender function in View!");
601         return;
602     }
603 
604     auto func = jsRerenderFunc_.Lock();
605     JSRef<JSVal> jsThis = jsObject_.Lock();
606     if (!jsThis->IsUndefined()) {
607         jsRenderResult_ = func->Call(jsThis);
608     } else {
609         LOGE("jsView Object is undefined and will not execute rerender function");
610     }
611 }
612 
613 // Partial update method
ViewFunctions(const JSRef<JSObject> & jsObject)614 ViewFunctions::ViewFunctions(const JSRef<JSObject>& jsObject)
615 {
616     InitViewFunctions(jsObject, JSRef<JSFunc>(), true);
617 }
618 
ExecuteOnFormRecycle()619 std::string ViewFunctions::ExecuteOnFormRecycle()
620 {
621     auto ret = ExecuteFunctionWithReturn(jsOnFormRecycleFunc_, "OnFormRecycle");
622     if (!ret->IsEmpty() && ret->IsString()) {
623         std::string statusData = ret->ToString();
624         return statusData.empty() ? EMPTY_STATUS_DATA : statusData;
625     }
626     LOGE("ExecuteOnFormRecycle failed");
627     return "";
628 }
629 
ExecuteOnFormRecover(const std::string & statusData)630 void ViewFunctions::ExecuteOnFormRecover(const std::string& statusData)
631 {
632     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
633     if (jsOnFormRecoverFunc_.IsEmpty()) {
634         LOGE("jsOnFormRecoverFunc_ is null");
635         return;
636     }
637 
638     std::string data;
639     if (statusData != EMPTY_STATUS_DATA) {
640         data = statusData;
641     }
642     auto jsData = JSRef<JSVal>::Make(ToJSValue(data));
643     auto func = jsOnFormRecoverFunc_.Lock();
644     func->Call(jsObject_.Lock(), 1, &jsData);
645 }
646 } // namespace OHOS::Ace::Framework
647