• 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 const std::string JS_STRINGIFIED_UNDEFINED = "undefined";
40 
41 #ifdef USE_ARK_ENGINE
42 
ExecuteLayout(NG::LayoutWrapper * layoutWrapper)43 void ViewFunctions::ExecuteLayout(NG::LayoutWrapper* layoutWrapper)
44 {
45     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
46     ACE_SCOPED_TRACE("ViewFunctions::ExecuteLayout");
47     auto jsParam = JSMeasureLayoutParam::GetInstance(layoutWrapper);
48     auto constraint = jsParam->GetConstraint();
49     auto childArray = jsParam->GetChildArray();
50     JSRef<JSVal> params[2] = { childArray, constraint };
51     jsLayoutFunc_.Lock()->Call(jsObject_.Lock(), 2, params);
52 }
53 
ExecuteMeasure(NG::LayoutWrapper * layoutWrapper)54 void ViewFunctions::ExecuteMeasure(NG::LayoutWrapper* layoutWrapper)
55 {
56     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
57     ACE_SCOPED_TRACE("ViewFunctions::ExecuteMeasure");
58     auto jsParam = JSMeasureLayoutParam::GetInstance(layoutWrapper);
59     auto constraint = jsParam->GetConstraint();
60     auto childArray = jsParam->GetChildArray();
61     JSRef<JSVal> params[2] = { childArray, constraint };
62     jsMeasureFunc_.Lock()->Call(jsObject_.Lock(), 2, params);
63 }
64 
ExecutePlaceChildren(NG::LayoutWrapper * layoutWrapper)65 void ViewFunctions::ExecutePlaceChildren(NG::LayoutWrapper* layoutWrapper)
66 {
67     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
68     ACE_SCOPED_TRACE("ViewFunctions::ExecutePlaceChildren");
69     auto jsParam = JSMeasureLayoutParamNG::GetInstance(layoutWrapper);
70 
71     auto selfLayoutInfo = jsParam->GetSelfLayoutInfo();
72     auto childArray = jsParam->GetChildArray();
73     auto constraint = jsParam->GetPlaceChildrenConstraint();
74 
75     JSRef<JSVal> params[3] = { selfLayoutInfo, childArray, constraint };
76     jsPlaceChildrenFunc_.Lock()->Call(jsObject_.Lock(), 3, params); /* 3:params number */
77 }
78 
InitJsParam(NG::LayoutWrapper * layoutWrapper)79 void ViewFunctions::InitJsParam(NG::LayoutWrapper* layoutWrapper)
80 {
81     JSMeasureLayoutParamNG::GetInstance(layoutWrapper);
82 }
83 
ExecuteMeasureSize(NG::LayoutWrapper * layoutWrapper)84 void ViewFunctions::ExecuteMeasureSize(NG::LayoutWrapper* layoutWrapper)
85 {
86     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
87     ACE_SCOPED_TRACE("ViewFunctions::ExecuteMeasureSize");
88     auto jsParam = JSMeasureLayoutParamNG::GetInstance(layoutWrapper);
89     if (!jsParam) {
90         layoutWrapper->GetGeometryNode()->SetFrameSize({ -1.0f, -1.0f });
91         TAG_LOGW(AceLogTag::ACE_LAYOUT, "GetInstance return val in onMeasureSize API is null");
92         return;
93     }
94 
95     auto selfLayoutInfo = jsParam->GetSelfLayoutInfo();
96     auto childArray = jsParam->GetChildArray();
97     auto constraint = jsParam->GetConstraint();
98 
99     JSRef<JSVal> params[3] = { selfLayoutInfo, childArray, constraint };
100     JSRef<JSObject> result = jsMeasureSizeFunc_.Lock()->Call(jsObject_.Lock(), 3, params); /* 3:params number */
101     if (result->IsUndefined()) {
102         layoutWrapper->GetGeometryNode()->SetFrameSize({ -1.0f, -1.0f });
103         TAG_LOGW(AceLogTag::ACE_LAYOUT, "app return val of onMeasureSize API is empty or undefined");
104         return;
105     }
106 
107     CalcDimension measureWidth;
108     CalcDimension measureHeight;
109     if (!JSViewAbstract::ParseJsDimensionVp(result->GetProperty("width"), measureWidth)) {
110         measureWidth = { -1.0f };
111     }
112     if (!JSViewAbstract::ParseJsDimensionVp(result->GetProperty("height"), measureHeight)) {
113         measureWidth = { -1.0f };
114     }
115     NG::SizeF frameSize = { static_cast<float>(measureWidth.ConvertToPx()),
116         static_cast<float>(measureHeight.ConvertToPx()) };
117     layoutWrapper->GetGeometryNode()->SetFrameSize(frameSize);
118 }
119 
ExecuteReload(bool deep)120 void ViewFunctions::ExecuteReload(bool deep)
121 {
122     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
123     ACE_SCOPED_TRACE("ViewFunctions::ExecuteReload");
124     auto func = jsReloadFunc_.Lock();
125     if (!func.IsEmpty()) {
126         JSRef<JSVal> params[1];
127         params[0] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(deep)));
128         func->Call(jsObject_.Lock(), 1, params);
129     } else {
130         LOGE("the reload func is null");
131     }
132 }
133 
ExecuteForceNodeRerender(int32_t elemId)134 void ViewFunctions::ExecuteForceNodeRerender(int32_t elemId)
135 {
136     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
137     ACE_SCOPED_TRACE("ViewFunctions::ExecuteForceNodeRerender");
138     auto func = jsForceRerenderNodeFunc_.Lock();
139     if (!func.IsEmpty()) {
140         JSRef<JSVal> params[1];
141         params[0] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(elemId)));
142         func->Call(jsObject_.Lock(), 1, params);
143     } else {
144         LOGE("the force node rerender func is null");
145     }
146 }
147 
ExecuteHasNodeUpdateFunc(int32_t elmtId)148 bool ViewFunctions::ExecuteHasNodeUpdateFunc(int32_t elmtId)
149 {
150     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_, false)
151     auto func = jsHasNodeUpdateFunc_.Lock();
152     if (func->IsEmpty()) {
153         LOGE("the hasNodeUpdateFunc is null");
154         return false;
155     }
156     JSRef<JSVal> params[1];
157     params[0] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(elmtId)));
158     auto result = func->Call(jsObject_.Lock(), 1, params);
159     return result->IsBoolean() && result->ToBoolean();
160 }
161 
162 // recycleSelf
ExecuteRecycle(const std::string & viewName)163 void ViewFunctions::ExecuteRecycle(const std::string& viewName)
164 {
165     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
166     ACE_SCOPED_TRACE("ViewFunctions::ExecuteRecycle");
167     auto func = jsRecycleFunc_.Lock();
168     if (!func->IsEmpty()) {
169         auto recycleNodeName = JSRef<JSVal>::Make(ToJSValue(viewName));
170         func->Call(jsObject_.Lock(), 1, &recycleNodeName);
171     } else {
172         LOGE("the recycle func is null");
173     }
174 }
175 
ExecuteSetActive(bool active,bool isReuse)176 void ViewFunctions::ExecuteSetActive(bool active, bool isReuse)
177 {
178     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
179     auto func = jsSetActive_.Lock();
180     if (!func->IsEmpty()) {
181         JSFastNativeScope scope(func->GetEcmaVM());
182         JSRef<JSVal> params[2]; // 2: the count of parameter
183         params[0] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(active)));
184         params[1] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(isReuse)));
185         func->Call(jsObject_.Lock(), 2, params); // 2: the count of parameter
186     } else {
187         LOGE("the set active func is null");
188     }
189 }
190 
ExecutePrebuildComponent()191 void ViewFunctions::ExecutePrebuildComponent()
192 {
193     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
194     auto func = jsPrebuildComponent_.Lock();
195     if (!func->IsEmpty()) {
196         func->Call(jsObject_.Lock());
197     } else {
198         LOGE("the prebuild component func is null");
199     }
200 }
201 
ExecuteSetPrebuildPhase(PrebuildPhase prebuildPhase)202 bool ViewFunctions::ExecuteSetPrebuildPhase(PrebuildPhase prebuildPhase)
203 {
204     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_, false)
205     auto func = jsSetPrebuildPhase_.Lock();
206     if (!func->IsEmpty()) {
207         auto jsPrebuildPhase = JSRef<JSVal>::Make(ToJSValue(static_cast<int32_t>(prebuildPhase)));
208         func->Call(jsObject_.Lock(), 1, &jsPrebuildPhase);
209         return true;
210     } else {
211         LOGE("the set prebuild phase func is null");
212     }
213     return false;
214 }
215 
ExecuteIsEnablePrebuildInMultiFrame()216 bool ViewFunctions::ExecuteIsEnablePrebuildInMultiFrame()
217 {
218     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_, false)
219     auto func = jsIsEnablePrebuildInMultiFrame_.Lock();
220     if (!func->IsEmpty()) {
221         auto result = func->Call(jsObject_.Lock());
222         if (result->IsBoolean()) {
223             return result->ToBoolean();
224         }
225     } else {
226         LOGE("the is enable prebuild in multi frame func is null");
227     }
228     return false;
229 }
230 
ExecuteOnDumpInfo(const std::vector<std::string> & params)231 void ViewFunctions::ExecuteOnDumpInfo(const std::vector<std::string>& params)
232 {
233     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
234     auto func = jsOnDumpInfo_.Lock();
235     if (!func->IsEmpty()) {
236         JSRef<JSArray> arr = JSRef<JSArray>::New();
237         for (size_t i = 0; i < params.size(); ++i) {
238             arr->SetValueAt(i, JSRef<JSVal>::Make(ToJSValue(params.at(i))));
239         }
240         JSRef<JSVal> argv = arr;
241         func->Call(jsObject_.Lock(), 1, &argv);
242     } else {
243         LOGE("the on dump info func is null");
244     }
245 }
246 
ExecuteOnDumpInfo()247 std::string ViewFunctions::ExecuteOnDumpInfo()
248 {
249     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_, "")
250     std::string res;
251     auto func = jsOnDumpInspector_.Lock();
252     if (!func->IsEmpty()) {
253         auto result = func->Call(jsObject_.Lock());
254         if (result->IsString()) {
255             res = result->ToString();
256         }
257     } else {
258         LOGE("the onDumpInspector func is null");
259     }
260     return res;
261 }
262 
ExecuteClearAllRecycle()263 void ViewFunctions::ExecuteClearAllRecycle()
264 {
265     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
266     auto func = jsClearAllRecycle_.Lock();
267     if (!func->IsEmpty()) {
268         auto result = func->Call(jsObject_.Lock());
269     } else {
270         LOGE("the clearAllRecycle func is null");
271     }
272 }
273 
274 #else
275 
ExecuteLayout(NG::LayoutWrapper * layoutWrapper)276 void ViewFunctions::ExecuteLayout(NG::LayoutWrapper* layoutWrapper) {}
277 
ExecuteMeasure(NG::LayoutWrapper * layoutWrapper)278 void ViewFunctions::ExecuteMeasure(NG::LayoutWrapper* layoutWrapper) {}
279 
ExecutePlaceChildren(NG::LayoutWrapper * layoutWrapper)280 void ViewFunctions::ExecutePlaceChildren(NG::LayoutWrapper* layoutWrapper) {}
281 
ExecuteMeasureSize(NG::LayoutWrapper * layoutWrapper)282 void ViewFunctions::ExecuteMeasureSize(NG::LayoutWrapper* layoutWrapper) {}
283 
ExecuteReload(bool deep)284 void ViewFunctions::ExecuteReload(bool deep) {}
285 
ExecuteForceNodeRerender(int32_t elemId)286 void ViewFunctions::ExecuteForceNodeRerender(int32_t elemId) {}
287 
288 #endif
289 
InitViewFunctions(const JSRef<JSObject> & jsObject,const JSRef<JSFunc> & jsRenderFunction,bool partialUpdate)290 void ViewFunctions::InitViewFunctions(
291     const JSRef<JSObject>& jsObject, const JSRef<JSFunc>& jsRenderFunction, bool partialUpdate)
292 {
293     jsObject_ = jsObject;
294 
295     if (partialUpdate) {
296         if (jsObject->GetProperty("initialRender")->IsFunction()) {
297             JSRef<JSVal> jsRenderFunc = jsObject->GetProperty("initialRenderView");
298             if (jsRenderFunc->IsFunction()) {
299                 jsRenderFunc_ = JSRef<JSFunc>::Cast(jsRenderFunc);
300             } else {
301                 LOGE("View lacks mandatory 'initialRenderView()' function, fatal internal error.");
302             }
303         } else {
304             LOGE("View lacks mandatory 'initialRender()' function, fatal internal error.");
305         }
306 
307         JSRef<JSVal> jsRerenderFunc = jsObject->GetProperty("rerender");
308         if (jsRerenderFunc->IsFunction()) {
309             jsRerenderFunc_ = JSRef<JSFunc>::Cast(jsRerenderFunc);
310         } else {
311             LOGE("View lacks mandatory 'rerender()' function, fatal internal error.");
312         }
313 
314         JSRef<JSVal> jsReloadFunc = jsObject->GetProperty("forceCompleteRerender");
315         if (jsReloadFunc->IsFunction()) {
316             jsReloadFunc_ = JSRef<JSFunc>::Cast(jsReloadFunc);
317         } else {
318             LOGE("View lacks mandatory 'forceCompleteRerender()' function, fatal internal error.");
319         }
320 
321         JSRef<JSVal> jsForceRerenderNodeFunc = jsObject->GetProperty("forceRerenderNode");
322         if (jsForceRerenderNodeFunc->IsFunction()) {
323             jsForceRerenderNodeFunc_ = JSRef<JSFunc>::Cast(jsForceRerenderNodeFunc);
324         } else {
325             LOGE("View lacks mandatory 'forceRerenderNode()' function, fatal internal error.");
326         }
327 
328         JSRef<JSVal> jsHasNodeUpdateFunc = jsObject->GetProperty("hasNodeUpdateFunc");
329         if (jsHasNodeUpdateFunc->IsFunction()) {
330             jsHasNodeUpdateFunc_ = JSRef<JSFunc>::Cast(jsHasNodeUpdateFunc);
331         }
332 
333         JSRef<JSVal> jsRecycleFunc = jsObject->GetProperty("recycleSelf");
334         if (jsRecycleFunc->IsFunction()) {
335             jsRecycleFunc_ = JSRef<JSFunc>::Cast(jsRecycleFunc);
336         }
337 
338         JSRef<JSVal> jsAboutToRecycleFunc = jsObject->GetProperty("aboutToRecycleInternal");
339         if (jsAboutToRecycleFunc->IsFunction()) {
340             jsAboutToRecycleFunc_ = JSRef<JSFunc>::Cast(jsAboutToRecycleFunc);
341         }
342 
343         JSRef<JSVal> jsAboutToReuseFunc = jsObject->GetProperty("aboutToReuseInternal");
344         if (jsAboutToReuseFunc->IsFunction()) {
345             jsAboutToReuseFunc_ = JSRef<JSFunc>::Cast(jsAboutToReuseFunc);
346         }
347 
348         JSRef<JSVal> jsSetActive = jsObject->GetProperty("setActiveInternal");
349         if (jsSetActive->IsFunction()) {
350             jsSetActive_ = JSRef<JSFunc>::Cast(jsSetActive);
351         }
352 
353         JSRef<JSVal> jsOnDumpInfo = jsObject->GetProperty("onDumpInfo");
354         if (jsOnDumpInfo->IsFunction()) {
355             jsOnDumpInfo_ = JSRef<JSFunc>::Cast(jsOnDumpInfo);
356         }
357 
358         JSRef<JSVal> jsOnDumpInspector = jsObject->GetProperty("onDumpInspector");
359         if (jsOnDumpInspector->IsFunction()) {
360             jsOnDumpInspector_ = JSRef<JSFunc>::Cast(jsOnDumpInspector);
361         }
362 
363         JSRef<JSVal> jsClearAllRecycle = jsObject->GetProperty("__ClearAllRecyle__PUV2ViewBase__Internal");
364         if (jsClearAllRecycle->IsFunction()) {
365             jsClearAllRecycle_ = JSRef<JSFunc>::Cast(jsClearAllRecycle);
366         }
367 
368         JSRef<JSVal> jsPrebuildComponent = jsObject->GetProperty("prebuildComponent");
369         if (jsPrebuildComponent->IsFunction()) {
370             jsPrebuildComponent_ = JSRef<JSFunc>::Cast(jsPrebuildComponent);
371         }
372 
373         JSRef<JSVal> jsIsEnablePrebuildInMultiFrame = jsObject->GetProperty("isEnablePrebuildInMultiFrame");
374         if (jsIsEnablePrebuildInMultiFrame->IsFunction()) {
375             jsIsEnablePrebuildInMultiFrame_ = JSRef<JSFunc>::Cast(jsIsEnablePrebuildInMultiFrame);
376         }
377 
378         JSRef<JSVal> jsSetPrebuildPhase = jsObject->GetProperty("setPrebuildPhase");
379         if (jsSetPrebuildPhase->IsFunction()) {
380             jsSetPrebuildPhase_ = JSRef<JSFunc>::Cast(jsSetPrebuildPhase);
381         }
382     }
383 
384     JSRef<JSVal> jsAppearFunc = jsObject->GetProperty("aboutToAppear");
385     if (jsAppearFunc->IsFunction()) {
386         jsAppearFunc_ = JSRef<JSFunc>::Cast(jsAppearFunc);
387     }
388 
389     JSRef<JSVal> jsDisappearFunc = jsObject->GetProperty("aboutToDisappear");
390     if (jsDisappearFunc->IsFunction()) {
391         jsDisappearFunc_ = JSRef<JSFunc>::Cast(jsDisappearFunc);
392     }
393 
394     JSRef<JSVal> jsDidBuildFunc = jsObject->GetProperty("onDidBuild");
395     if (jsDidBuildFunc->IsFunction()) {
396         jsDidBuildFunc_ = JSRef<JSFunc>::Cast(jsDidBuildFunc);
397     }
398 
399     JSRef<JSVal> jsLayoutFunc = jsObject->GetProperty("onLayout");
400     if (jsLayoutFunc->IsFunction()) {
401         jsLayoutFunc_ = JSRef<JSFunc>::Cast(jsLayoutFunc);
402     }
403 
404     JSRef<JSVal> jsMeasureFunc = jsObject->GetProperty("onMeasure");
405     if (jsMeasureFunc->IsFunction()) {
406         jsMeasureFunc_ = JSRef<JSFunc>::Cast(jsMeasureFunc);
407     }
408 
409     JSRef<JSVal> jsPlaceChildrenFunc = jsObject->GetProperty("onPlaceChildren");
410     if (jsPlaceChildrenFunc->IsFunction()) {
411         jsPlaceChildrenFunc_ = JSRef<JSFunc>::Cast(jsPlaceChildrenFunc);
412     }
413 
414     JSRef<JSVal> jsMeasureSizeFunc = jsObject->GetProperty("onMeasureSize");
415     if (jsMeasureSizeFunc->IsFunction()) {
416         jsMeasureSizeFunc_ = JSRef<JSFunc>::Cast(jsMeasureSizeFunc);
417     }
418 
419     JSRef<JSVal> jsAboutToBeDeletedFunc = jsObject->GetProperty("aboutToBeDeleted");
420     if (jsAboutToBeDeletedFunc->IsFunction()) {
421         jsAboutToBeDeletedFunc_ = JSRef<JSFunc>::Cast(jsAboutToBeDeletedFunc);
422     } else {
423         jsAboutToBeDeletedFunc = jsObject->GetProperty("aboutToBeDeletedInternal");
424         if (jsAboutToBeDeletedFunc->IsFunction()) {
425             jsAboutToBeDeletedFunc_ = JSRef<JSFunc>::Cast(jsAboutToBeDeletedFunc);
426         }
427     }
428 
429     JSRef<JSVal> jsAboutToRenderFunc = jsObject->GetProperty("aboutToRender");
430     if (jsAboutToRenderFunc->IsFunction()) {
431         jsAboutToRenderFunc_ = JSRef<JSFunc>::Cast(jsAboutToRenderFunc);
432     }
433 
434     JSRef<JSVal> jsRenderDoneFunc = jsObject->GetProperty("onRenderDone");
435     if (jsRenderDoneFunc->IsFunction()) {
436         jsRenderDoneFunc_ = JSRef<JSFunc>::Cast(jsRenderDoneFunc);
437     }
438 
439     JSRef<JSVal> jsAboutToBuildFunc = jsObject->GetProperty("aboutToBuild");
440     if (jsAboutToBuildFunc->IsFunction()) {
441         jsAboutToBuildFunc_ = JSRef<JSFunc>::Cast(jsAboutToBuildFunc);
442     }
443 
444     JSRef<JSVal> jsBuildDoneFunc = jsObject->GetProperty("onBuildDone");
445     if (jsBuildDoneFunc->IsFunction()) {
446         jsBuildDoneFunc_ = JSRef<JSFunc>::Cast(jsBuildDoneFunc);
447     }
448 
449     JSRef<JSVal> jsTransitionFunc = jsObject->GetProperty("pageTransition");
450     if (jsTransitionFunc->IsFunction()) {
451         jsTransitionFunc_ = JSRef<JSFunc>::Cast(jsTransitionFunc);
452     }
453 
454     JSRef<JSVal> jsOnHideFunc = jsObject->GetProperty("onPageHide");
455     if (jsOnHideFunc->IsFunction()) {
456         jsOnHideFunc_ = JSRef<JSFunc>::Cast(jsOnHideFunc);
457     }
458 
459     JSRef<JSVal> jsOnShowFunc = jsObject->GetProperty("onPageShow");
460     if (jsOnShowFunc->IsFunction()) {
461         jsOnShowFunc_ = JSRef<JSFunc>::Cast(jsOnShowFunc);
462     }
463 
464     JSRef<JSVal> jsBackPressFunc = jsObject->GetProperty("onBackPress");
465     if (jsBackPressFunc->IsFunction()) {
466         jsBackPressFunc_ = JSRef<JSFunc>::Cast(jsBackPressFunc);
467     }
468 
469     JSRef<JSVal> jsSetInitiallyProvidedValueFunc = jsObject->GetProperty("setInitiallyProvidedValue");
470     if (jsSetInitiallyProvidedValueFunc->IsFunction()) {
471         jsSetInitiallyProvidedValueFunc_ = JSRef<JSFunc>::Cast(jsSetInitiallyProvidedValueFunc);
472     }
473 
474     if (!partialUpdate) {
475         JSRef<JSVal> jsUpdateWithValueParamsFunc = jsObject->GetProperty("updateWithValueParams");
476         if (jsUpdateWithValueParamsFunc->IsFunction()) {
477             jsUpdateWithValueParamsFunc_ = JSRef<JSFunc>::Cast(jsUpdateWithValueParamsFunc);
478         }
479         jsRenderFunc_ = jsRenderFunction;
480     }
481 
482     JSRef<JSVal> jsOnFormRecycleFunc = jsObject->GetProperty("onFormRecycle");
483     if (jsOnFormRecycleFunc->IsFunction()) {
484         jsOnFormRecycleFunc_ = JSRef<JSFunc>::Cast(jsOnFormRecycleFunc);
485     }
486 
487     JSRef<JSVal> jsOnFormRecoverFunc = jsObject->GetProperty("onFormRecover");
488     if (jsOnFormRecoverFunc->IsFunction()) {
489         jsOnFormRecoverFunc_ = JSRef<JSFunc>::Cast(jsOnFormRecoverFunc);
490     }
491 
492     JSRef<JSVal> jsOnNewParam = jsObject->GetProperty("onNewParam");
493     if (jsOnNewParam->IsFunction()) {
494         jsOnNewParam_ = JSRef<JSFunc>::Cast(jsOnNewParam);
495     }
496 }
497 
ViewFunctions(const JSRef<JSObject> & jsObject,const JSRef<JSFunc> & jsRenderFunction)498 ViewFunctions::ViewFunctions(const JSRef<JSObject>& jsObject, const JSRef<JSFunc>& jsRenderFunction)
499 {
500     ACE_DCHECK(jsObject);
501     InitViewFunctions(jsObject, jsRenderFunction, false);
502 }
503 
ExecuteRender()504 void ViewFunctions::ExecuteRender()
505 {
506     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
507     if (jsRenderFunc_.IsEmpty()) {
508         LOGE("no render function in View!");
509         return;
510     }
511 
512     auto func = jsRenderFunc_.Lock();
513     JSRef<JSVal> jsThis = jsObject_.Lock();
514     if (!jsThis->IsUndefined()) {
515         jsRenderResult_ = func->Call(jsThis);
516     } else {
517         LOGE("jsView Object is undefined and will not execute render function");
518     }
519 }
520 
ExecuteAppear()521 void ViewFunctions::ExecuteAppear()
522 {
523     ExecuteFunction(jsAppearFunc_, "aboutToAppear");
524 }
525 
ExecuteDisappear()526 void ViewFunctions::ExecuteDisappear()
527 {
528     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
529     if (jsDisappearFunc_.IsEmpty()) {
530         return;
531     }
532     ACE_SCOPED_TRACE("%s", "aboutToDisappear");
533     JSRef<JSVal> jsObject = jsObject_.Lock();
534     std::string functionName("aboutToDisappear");
535     AceScopedPerformanceCheck scoped(functionName);
536     if (!jsObject->IsUndefined()) {
537         jsDisappearFunc_.Lock()->Call(jsObject);
538     } else {
539         LOGE("jsView Object is undefined and will not execute aboutToDisappear function");
540     }
541 }
542 
ExecuteDidBuild()543 void ViewFunctions::ExecuteDidBuild()
544 {
545     ExecuteFunction(jsDidBuildFunc_, "onDidBuild");
546 }
547 
ExecuteAboutToRecycle()548 void ViewFunctions::ExecuteAboutToRecycle()
549 {
550     ExecuteFunction(jsAboutToRecycleFunc_, "aboutToRecycleInternal");
551 }
552 
ExecuteAboutToReuse(void * params)553 void ViewFunctions::ExecuteAboutToReuse(void* params)
554 {
555     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
556     if (jsAboutToReuseFunc_.IsEmpty()) {
557         return;
558     }
559     ACE_SCOPED_TRACE("ExecuteAboutToReuse");
560     JSRef<JSVal> jsObject = jsObject_.Lock();
561     if (!jsObject->IsUndefined()) {
562         std::string functionName("ExecuteAboutToReuse");
563         AceScopedPerformanceCheck scoped(functionName);
564         auto reuseParams = JsiCallbackInfo(reinterpret_cast<panda::JsiRuntimeCallInfo*>(params));
565         JsiRef<JsiValue> params[1] = { reuseParams[0] };
566         if (reuseParams.Length() > 0) {
567             jsAboutToReuseFunc_.Lock()->Call(jsObject, 1, params);
568         } else {
569             jsAboutToReuseFunc_.Lock()->Call(jsObject);
570         }
571     } else {
572         LOGE("jsObject is undefined. Internal error while trying to exec ExecuteAboutToReuse");
573     }
574 }
575 
HasLayout() const576 bool ViewFunctions::HasLayout() const
577 {
578     return !jsLayoutFunc_.IsEmpty();
579 }
580 
HasMeasure() const581 bool ViewFunctions::HasMeasure() const
582 {
583     return !jsMeasureFunc_.IsEmpty();
584 }
585 
HasPlaceChildren() const586 bool ViewFunctions::HasPlaceChildren() const
587 {
588     return !jsPlaceChildrenFunc_.IsEmpty();
589 }
590 
HasMeasureSize() const591 bool ViewFunctions::HasMeasureSize() const
592 {
593     return !jsMeasureSizeFunc_.IsEmpty();
594 }
595 
ExecuteAboutToBeDeleted()596 void ViewFunctions::ExecuteAboutToBeDeleted()
597 {
598     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
599     if (jsAboutToBeDeletedFunc_.IsEmpty()) {
600         return;
601     }
602     ACE_SCOPED_TRACE("%s", "aboutToBeDeleted");
603     JSRef<JSVal> jsObject = jsObject_.Lock();
604     std::string functionName("aboutToBeDeleted");
605     AceScopedPerformanceCheck scoped(functionName);
606     if (!jsObject->IsUndefined()) {
607         jsAboutToBeDeletedFunc_.Lock()->Call(jsObject);
608     } else {
609         LOGE("jsView Object is undefined and will not execute aboutToBeDeleted function");
610     }
611 }
612 
ExecuteAboutToRender()613 void ViewFunctions::ExecuteAboutToRender()
614 {
615     // for developer callback.
616     ExecuteFunction(jsAboutToBuildFunc_, "aboutToBuild");
617     // for state manager mark rendering progress.
618     ExecuteFunction(jsAboutToRenderFunc_, "aboutToRender");
619 }
620 
ExecuteOnRenderDone()621 void ViewFunctions::ExecuteOnRenderDone()
622 {
623     // for state manager reset rendering progress.
624     ExecuteFunction(jsRenderDoneFunc_, "onRenderDone");
625     // for developer callback.
626     ExecuteFunction(jsBuildDoneFunc_, "onBuildDone");
627 }
628 
ExecuteTransition()629 void ViewFunctions::ExecuteTransition()
630 {
631     ExecuteFunction(jsTransitionFunc_, "pageTransition");
632 }
633 
HasPageTransition() const634 bool ViewFunctions::HasPageTransition() const
635 {
636     return !jsTransitionFunc_.IsEmpty();
637 }
638 
ExecuteShow()639 void ViewFunctions::ExecuteShow()
640 {
641     ExecuteFunction(jsOnShowFunc_, "onPageShow");
642 }
643 
ExecuteHide()644 void ViewFunctions::ExecuteHide()
645 {
646     ExecuteFunction(jsOnHideFunc_, "onPageHide");
647 }
648 
ExecuteInitiallyProvidedValue(const std::string & jsonData)649 void ViewFunctions::ExecuteInitiallyProvidedValue(const std::string& jsonData)
650 {
651     ExecuteFunctionWithParams(jsSetInitiallyProvidedValueFunc_, "setInitiallyProvidedValue", jsonData);
652 }
653 
654 // Method not needed for Partial Update code path
ExecuteUpdateWithValueParams(const std::string & jsonData)655 void ViewFunctions::ExecuteUpdateWithValueParams(const std::string& jsonData)
656 {
657     ExecuteFunctionWithParams(jsUpdateWithValueParamsFunc_, "updateWithValueParams", jsonData);
658 }
659 
ExecuteOnBackPress()660 bool ViewFunctions::ExecuteOnBackPress()
661 {
662     auto ret = ExecuteFunctionWithReturn(jsBackPressFunc_, "onBackPress");
663     if (!ret->IsEmpty() && ret->IsBoolean()) {
664         return ret->ToBoolean();
665     }
666     return false;
667 }
668 
ExecuteFunction(JSWeak<JSFunc> & func,const char * debugInfo)669 void ViewFunctions::ExecuteFunction(JSWeak<JSFunc>& func, const char* debugInfo)
670 {
671     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
672     if (func.IsEmpty()) {
673         return;
674     }
675     ACE_SCOPED_TRACE("%s", debugInfo);
676     JSRef<JSVal> jsObject = jsObject_.Lock();
677     if (!jsObject->IsUndefined()) {
678         std::string functionName(debugInfo);
679         AceScopedPerformanceCheck scoped(functionName);
680         func.Lock()->Call(jsObject);
681     } else {
682         LOGE("jsObject is undefined. Internal error while trying to exec %{public}s", debugInfo);
683     }
684 }
685 
ExecuteFunctionWithReturn(JSWeak<JSFunc> & func,const char * debugInfo)686 JSRef<JSVal> ViewFunctions::ExecuteFunctionWithReturn(JSWeak<JSFunc>& func, const char* debugInfo)
687 {
688     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_, JSRef<JSVal>::Make())
689     if (func.IsEmpty()) {
690         return JSRef<JSVal>::Make();
691     }
692     ACE_SCOPED_TRACE("%s", debugInfo);
693     JSRef<JSVal> jsObject = jsObject_.Lock();
694     std::string functionName(debugInfo);
695     AceScopedPerformanceCheck scoped(functionName);
696     JSRef<JSVal> result = func.Lock()->Call(jsObject);
697     if (result.IsEmpty()) {
698         LOGE("Error calling %{public}s", debugInfo);
699     }
700     return result;
701 }
702 
ExecuteFunctionWithParams(JSWeak<JSFunc> & func,const char * debugInfo,const std::string & jsonData)703 void ViewFunctions::ExecuteFunctionWithParams(JSWeak<JSFunc>& func, const char* debugInfo, const std::string& jsonData)
704 {
705     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
706     if (func.IsEmpty()) {
707         return;
708     }
709 
710     JSRef<JSObject> obj = JSRef<JSObject>::New();
711     JSRef<JSVal> param = obj->ToJsonObject(jsonData.c_str());
712 
713     JSRef<JSVal> jsObject = jsObject_.Lock();
714     JSRef<JSVal> result = func.Lock()->Call(jsObject, 1, &param);
715     if (result.IsEmpty()) {
716         LOGE("Error calling %{public}s", debugInfo);
717     }
718 }
719 
720 // Baseline version of Destroy
Destroy(JSView * parentCustomView)721 void ViewFunctions::Destroy(JSView* parentCustomView)
722 {
723     // Might be called from parent view, before any result has been produced??
724     if (jsRenderResult_.IsEmpty()) {
725         return;
726     }
727 
728     auto renderRes = jsRenderResult_.Lock();
729     if (renderRes.IsEmpty() || !renderRes->IsObject()) {
730         return;
731     }
732 
733     JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
734     if (!obj.IsEmpty()) {
735         // jsRenderResult_ maybe an js exception, not a JSView
736         JSView* view = JSView::GetNativeView(obj);
737         if (view != nullptr) {
738             view->Destroy(parentCustomView);
739         }
740     }
741     jsRenderResult_.Reset();
742 }
743 
744 // PartialUpdate version of Destroy
Destroy()745 void ViewFunctions::Destroy()
746 {
747     // Might be called from parent view, before any result has been produced??
748     if (jsRenderResult_.IsEmpty()) {
749         return;
750     }
751 
752     auto renderRes = jsRenderResult_.Lock();
753     if (renderRes.IsEmpty() || !renderRes->IsObject()) {
754         return;
755     }
756 
757     // merging: when would a render function return a JSView ?
758     JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
759     if (!obj.IsEmpty()) {
760         // jsRenderResult_ maybe an js exception, not a JSView
761         JSView* view = JSView::GetNativeView(obj);
762         if (view != nullptr) {
763             LOGE("NOTE NOTE NOTE render returned a JSView object that's dangling!");
764         }
765     }
766     jsObject_.Reset();
767     jsRenderResult_.Reset();
768 }
769 
770 // Partial update method
ExecuteRerender()771 void ViewFunctions::ExecuteRerender()
772 {
773     int32_t id = -1;
774     if (SystemProperties::GetAcePerformanceMonitorEnabled()) {
775         id = Container::CurrentId();
776     }
777     COMPONENT_UPDATE_DURATION(id);
778     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
779     if (jsRerenderFunc_.IsEmpty()) {
780         LOGE("no rerender function in View!");
781         return;
782     }
783 
784     auto func = jsRerenderFunc_.Lock();
785     JSRef<JSVal> jsThis = jsObject_.Lock();
786     if (!jsThis->IsUndefined()) {
787         jsRenderResult_ = func->Call(jsThis);
788     } else {
789         LOGE("jsView Object is undefined and will not execute rerender function");
790     }
791 }
792 
793 // Partial update method
ViewFunctions(const JSRef<JSObject> & jsObject)794 ViewFunctions::ViewFunctions(const JSRef<JSObject>& jsObject)
795 {
796     InitViewFunctions(jsObject, JSRef<JSFunc>(), true);
797 }
798 
ExecuteOnFormRecycle()799 std::string ViewFunctions::ExecuteOnFormRecycle()
800 {
801     auto ret = ExecuteFunctionWithReturn(jsOnFormRecycleFunc_, "OnFormRecycle");
802     if (!ret->IsEmpty() && ret->IsString()) {
803         std::string statusData = ret->ToString();
804         return statusData.empty() ? EMPTY_STATUS_DATA : statusData;
805     }
806     TAG_LOGE(AceLogTag::ACE_FORM, "ExecuteOnFormRecycle failed");
807     return "";
808 }
809 
ExecuteOnFormRecover(const std::string & statusData)810 void ViewFunctions::ExecuteOnFormRecover(const std::string& statusData)
811 {
812     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
813     if (jsOnFormRecoverFunc_.IsEmpty()) {
814         TAG_LOGE(AceLogTag::ACE_FORM, "jsOnFormRecoverFunc_ is null");
815         return;
816     }
817 
818     std::string data;
819     if (statusData != EMPTY_STATUS_DATA) {
820         data = statusData;
821     }
822     auto jsData = JSRef<JSVal>::Make(ToJSValue(data));
823     auto func = jsOnFormRecoverFunc_.Lock();
824     func->Call(jsObject_.Lock(), 1, &jsData);
825 }
826 
ExecuteOnNewParam(const std::string & newParam)827 void ViewFunctions::ExecuteOnNewParam(const std::string& newParam)
828 {
829     JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
830     if (jsOnNewParam_.IsEmpty()) {
831         return;
832     }
833     auto argv = JSRef<JSVal>::Make();
834     if (!newParam.empty() && newParam != JS_STRINGIFIED_UNDEFINED) {
835         argv = JSRef<JSObject>::New()->ToJsonObject(newParam.c_str());
836     }
837     auto func = jsOnNewParam_.Lock();
838     func->Call(jsObject_.Lock(), 1, &argv);
839 }
840 } // namespace OHOS::Ace::Framework
841