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