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