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