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, ¶m);
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