1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "bridge/declarative_frontend/jsview/js_view_functions.h"
17
18 #include <memory>
19 #include <string>
20
21 #include "base/geometry/calc_dimension.h"
22 #include "base/geometry/dimension.h"
23 #include "base/log/ace_performance_check.h"
24 #include "base/log/ace_trace.h"
25 #include "base/utils/utils.h"
26 #include "bridge/declarative_frontend/engine/js_execution_scope_defines.h"
27 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
28 #include "bridge/declarative_frontend/jsview/js_view.h"
29 #include "bridge/declarative_frontend/jsview/js_view_measure_layout.h"
30 #include "bridge/declarative_frontend/view_stack_processor.h"
31 #include "core/components_ng/base/frame_node.h"
32 #include "core/components_ng/layout/layout_property.h"
33 #include "core/components_ng/layout/layout_wrapper.h"
34 #include "core/components_ng/pattern/custom/custom_measure_layout_param.h"
35 #include "core/pipeline/base/composed_element.h"
36
37 namespace OHOS::Ace::Framework {
38 const std::string EMPTY_STATUS_DATA = "empty_status_data";
39
40 #ifdef USE_ARK_ENGINE
41
ExecuteLayout(NG::LayoutWrapper * layoutWrapper)42 void ViewFunctions::ExecuteLayout(NG::LayoutWrapper* layoutWrapper)
43 {
44 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
45 ACE_SCOPED_TRACE("ViewFunctions::ExecuteLayout");
46 auto jsParam = JSMeasureLayoutParam::GetInstance(layoutWrapper);
47 auto constraint = jsParam->GetConstraint();
48 auto childArray = jsParam->GetChildArray();
49 JSRef<JSVal> params[2] = { childArray, constraint };
50 jsLayoutFunc_.Lock()->Call(jsObject_.Lock(), 2, params);
51 }
52
ExecuteMeasure(NG::LayoutWrapper * layoutWrapper)53 void ViewFunctions::ExecuteMeasure(NG::LayoutWrapper* layoutWrapper)
54 {
55 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
56 ACE_SCOPED_TRACE("ViewFunctions::ExecuteMeasure");
57 auto jsParam = JSMeasureLayoutParam::GetInstance(layoutWrapper);
58 auto constraint = jsParam->GetConstraint();
59 auto childArray = jsParam->GetChildArray();
60 JSRef<JSVal> params[2] = { childArray, constraint };
61 jsMeasureFunc_.Lock()->Call(jsObject_.Lock(), 2, params);
62 }
63
ExecutePlaceChildren(NG::LayoutWrapper * layoutWrapper)64 void ViewFunctions::ExecutePlaceChildren(NG::LayoutWrapper* layoutWrapper)
65 {
66 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
67 ACE_SCOPED_TRACE("ViewFunctions::ExecutePlaceChildren");
68 auto jsParam = JSMeasureLayoutParamNG::GetInstance(layoutWrapper);
69
70 auto selfLayoutInfo = jsParam->GetSelfLayoutInfo();
71 auto childArray = jsParam->GetChildArray();
72 auto constraint = jsParam->GetConstraint();
73
74 JSRef<JSVal> params[3] = { selfLayoutInfo, childArray, constraint };
75 jsPlaceChildrenFunc_.Lock()->Call(jsObject_.Lock(), 3, params); /* 3:params number */
76 }
77
InitJsParam(NG::LayoutWrapper * layoutWrapper)78 void ViewFunctions::InitJsParam(NG::LayoutWrapper* layoutWrapper)
79 {
80 JSMeasureLayoutParamNG::GetInstance(layoutWrapper);
81 }
82
ExecuteMeasureSize(NG::LayoutWrapper * layoutWrapper)83 void ViewFunctions::ExecuteMeasureSize(NG::LayoutWrapper* layoutWrapper)
84 {
85 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
86 ACE_SCOPED_TRACE("ViewFunctions::ExecuteMeasureSize");
87 auto jsParam = JSMeasureLayoutParamNG::GetInstance(layoutWrapper);
88
89 auto selfLayoutInfo = jsParam->GetSelfLayoutInfo();
90 auto childArray = jsParam->GetChildArray();
91 auto constraint = jsParam->GetConstraint();
92
93 JSRef<JSVal> params[3] = { selfLayoutInfo, childArray, constraint };
94 JSRef<JSObject> result = jsMeasureSizeFunc_.Lock()->Call(jsObject_.Lock(), 3, params); /* 3:params number */
95
96 CalcDimension measureWidth;
97 CalcDimension measureHeight;
98 if (!JSViewAbstract::ParseJsDimensionVp(result->GetProperty("width"), measureWidth)) {
99 measureWidth = { -1.0f };
100 }
101 if (!JSViewAbstract::ParseJsDimensionVp(result->GetProperty("height"), measureHeight)) {
102 measureWidth = { -1.0f };
103 }
104 NG::SizeF frameSize = { measureWidth.ConvertToPx(), measureHeight.ConvertToPx() };
105 layoutWrapper->GetGeometryNode()->SetFrameSize(frameSize);
106 }
107
ExecuteReload(bool deep)108 void ViewFunctions::ExecuteReload(bool deep)
109 {
110 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
111 ACE_SCOPED_TRACE("ViewFunctions::ExecuteReload");
112 auto func = jsReloadFunc_.Lock();
113 if (!func.IsEmpty()) {
114 JSRef<JSVal> params[1];
115 params[0] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(deep)));
116 func->Call(jsObject_.Lock(), 1, params);
117 } else {
118 LOGE("the reload func is null");
119 }
120 }
121
ExecuteForceNodeRerender(int32_t elemId)122 void ViewFunctions::ExecuteForceNodeRerender(int32_t elemId)
123 {
124 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
125 ACE_SCOPED_TRACE("ViewFunctions::ExecuteForceNodeRerender");
126 auto func = jsForceRerenderNodeFunc_.Lock();
127 if (!func.IsEmpty()) {
128 JSRef<JSVal> params[1];
129 params[0] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(elemId)));
130 func->Call(jsObject_.Lock(), 1, params);
131 } else {
132 LOGE("the force node rerender func is null");
133 }
134 }
135
ExecuteRecycle(const std::string & viewName)136 void ViewFunctions::ExecuteRecycle(const std::string& viewName)
137 {
138 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
139 ACE_SCOPED_TRACE("ViewFunctions::ExecuteRecycle");
140 auto func = jsRecycleFunc_.Lock();
141 if (!func->IsEmpty()) {
142 auto recycleNodeName = JSRef<JSVal>::Make(ToJSValue(viewName));
143 func->Call(jsObject_.Lock(), 1, &recycleNodeName);
144 } else {
145 LOGE("the recycle func is null");
146 }
147 }
148
ExecuteSetActive(bool active)149 void ViewFunctions::ExecuteSetActive(bool active)
150 {
151 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
152 auto func = jsSetActive_.Lock();
153 if (!func->IsEmpty()) {
154 auto isActive = JSRef<JSVal>::Make(ToJSValue(active));
155 func->Call(jsObject_.Lock(), 1, &isActive);
156 } else {
157 LOGE("the set active func is null");
158 }
159 }
160
ExecuteOnDumpInfo(const std::vector<std::string> & params)161 void ViewFunctions::ExecuteOnDumpInfo(const std::vector<std::string>& params)
162 {
163 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
164 auto func = jsOnDumpInfo_.Lock();
165 if (!func->IsEmpty()) {
166 JSRef<JSArray> arr = JSRef<JSArray>::New();
167 for (size_t i = 0; i < params.size(); ++i) {
168 arr->SetValueAt(i, JSRef<JSVal>::Make(ToJSValue(params.at(i))));
169 }
170 JSRef<JSVal> argv = arr;
171 func->Call(jsObject_.Lock(), 1, &argv);
172 } else {
173 LOGE("the on dump info func is null");
174 }
175 }
176
177 #else
178
ExecuteLayout(NG::LayoutWrapper * layoutWrapper)179 void ViewFunctions::ExecuteLayout(NG::LayoutWrapper* layoutWrapper) {}
180
ExecuteMeasure(NG::LayoutWrapper * layoutWrapper)181 void ViewFunctions::ExecuteMeasure(NG::LayoutWrapper* layoutWrapper) {}
182
ExecutePlaceChildren(NG::LayoutWrapper * layoutWrapper)183 void ViewFunctions::ExecutePlaceChildren(NG::LayoutWrapper* layoutWrapper) {}
184
ExecuteMeasureSize(NG::LayoutWrapper * layoutWrapper)185 void ViewFunctions::ExecuteMeasureSize(NG::LayoutWrapper* layoutWrapper) {}
186
ExecuteReload(bool deep)187 void ViewFunctions::ExecuteReload(bool deep) {}
188
ExecuteForceNodeRerender(int32_t elemId)189 void ViewFunctions::ExecuteForceNodeRerender(int32_t elemId) {}
190
191 #endif
192
InitViewFunctions(const JSRef<JSObject> & jsObject,const JSRef<JSFunc> & jsRenderFunction,bool partialUpdate)193 void ViewFunctions::InitViewFunctions(
194 const JSRef<JSObject>& jsObject, const JSRef<JSFunc>& jsRenderFunction, bool partialUpdate)
195 {
196 jsObject_ = jsObject;
197
198 if (partialUpdate) {
199 if (jsObject->GetProperty("initialRender")->IsFunction()) {
200 JSRef<JSVal> jsRenderFunc = jsObject->GetProperty("initialRenderView");
201 if (jsRenderFunc->IsFunction()) {
202 jsRenderFunc_ = JSRef<JSFunc>::Cast(jsRenderFunc);
203 } else {
204 LOGE("View lacks mandatory 'initialRenderView()' function, fatal internal error.");
205 }
206 } else {
207 LOGE("View lacks mandatory 'initialRender()' function, fatal internal error.");
208 }
209
210 JSRef<JSVal> jsRerenderFunc = jsObject->GetProperty("rerender");
211 if (jsRerenderFunc->IsFunction()) {
212 jsRerenderFunc_ = JSRef<JSFunc>::Cast(jsRerenderFunc);
213 } else {
214 LOGE("View lacks mandatory 'rerender()' function, fatal internal error.");
215 }
216
217 JSRef<JSVal> jsReloadFunc = jsObject->GetProperty("forceCompleteRerender");
218 if (jsReloadFunc->IsFunction()) {
219 jsReloadFunc_ = JSRef<JSFunc>::Cast(jsReloadFunc);
220 } else {
221 LOGE("View lacks mandatory 'forceCompleteRerender()' function, fatal internal error.");
222 }
223
224 JSRef<JSVal> jsForceRerenderNodeFunc = jsObject->GetProperty("forceRerenderNode");
225 if (jsForceRerenderNodeFunc->IsFunction()) {
226 jsForceRerenderNodeFunc_ = JSRef<JSFunc>::Cast(jsForceRerenderNodeFunc);
227 } else {
228 LOGE("View lacks mandatory 'forceRerenderNode()' function, fatal internal error.");
229 }
230
231 JSRef<JSVal> jsRecycleFunc = jsObject->GetProperty("recycleSelf");
232 if (jsRecycleFunc->IsFunction()) {
233 jsRecycleFunc_ = JSRef<JSFunc>::Cast(jsRecycleFunc);
234 }
235
236 JSRef<JSVal> jsAboutToRecycleFunc = jsObject->GetProperty("aboutToRecycleInternal");
237 if (jsAboutToRecycleFunc->IsFunction()) {
238 jsAboutToRecycleFunc_ = JSRef<JSFunc>::Cast(jsAboutToRecycleFunc);
239 }
240
241 JSRef<JSVal> jsSetActive = jsObject->GetProperty("setActiveInternal");
242 if (jsSetActive->IsFunction()) {
243 jsSetActive_ = JSRef<JSFunc>::Cast(jsSetActive);
244 }
245
246 JSRef<JSVal> jsOnDumpInfo = jsObject->GetProperty("onDumpInfo");
247 if (jsOnDumpInfo->IsFunction()) {
248 jsOnDumpInfo_ = JSRef<JSFunc>::Cast(jsOnDumpInfo);
249 }
250 }
251
252 JSRef<JSVal> jsAppearFunc = jsObject->GetProperty("aboutToAppear");
253 if (jsAppearFunc->IsFunction()) {
254 jsAppearFunc_ = JSRef<JSFunc>::Cast(jsAppearFunc);
255 }
256
257 JSRef<JSVal> jsDisappearFunc = jsObject->GetProperty("aboutToDisappear");
258 if (jsDisappearFunc->IsFunction()) {
259 jsDisappearFunc_ = JSRef<JSFunc>::Cast(jsDisappearFunc);
260 }
261
262 JSRef<JSVal> jsLayoutFunc = jsObject->GetProperty("onLayout");
263 if (jsLayoutFunc->IsFunction()) {
264 jsLayoutFunc_ = JSRef<JSFunc>::Cast(jsLayoutFunc);
265 }
266
267 JSRef<JSVal> jsMeasureFunc = jsObject->GetProperty("onMeasure");
268 if (jsMeasureFunc->IsFunction()) {
269 jsMeasureFunc_ = JSRef<JSFunc>::Cast(jsMeasureFunc);
270 }
271
272 JSRef<JSVal> jsPlaceChildrenFunc = jsObject->GetProperty("onPlaceChildren");
273 if (jsPlaceChildrenFunc->IsFunction()) {
274 jsPlaceChildrenFunc_ = JSRef<JSFunc>::Cast(jsPlaceChildrenFunc);
275 }
276
277 JSRef<JSVal> jsMeasureSizeFunc = jsObject->GetProperty("onMeasureSize");
278 if (jsMeasureSizeFunc->IsFunction()) {
279 jsMeasureSizeFunc_ = JSRef<JSFunc>::Cast(jsMeasureSizeFunc);
280 }
281
282 JSRef<JSVal> jsAboutToBeDeletedFunc = jsObject->GetProperty("aboutToBeDeleted");
283 if (jsAboutToBeDeletedFunc->IsFunction()) {
284 jsAboutToBeDeletedFunc_ = JSRef<JSFunc>::Cast(jsAboutToBeDeletedFunc);
285 }
286
287 JSRef<JSVal> jsAboutToRenderFunc = jsObject->GetProperty("aboutToRender");
288 if (jsAboutToRenderFunc->IsFunction()) {
289 jsAboutToRenderFunc_ = JSRef<JSFunc>::Cast(jsAboutToRenderFunc);
290 }
291
292 JSRef<JSVal> jsRenderDoneFunc = jsObject->GetProperty("onRenderDone");
293 if (jsRenderDoneFunc->IsFunction()) {
294 jsRenderDoneFunc_ = JSRef<JSFunc>::Cast(jsRenderDoneFunc);
295 }
296
297 JSRef<JSVal> jsAboutToBuildFunc = jsObject->GetProperty("aboutToBuild");
298 if (jsAboutToBuildFunc->IsFunction()) {
299 jsAboutToBuildFunc_ = JSRef<JSFunc>::Cast(jsAboutToBuildFunc);
300 }
301
302 JSRef<JSVal> jsBuildDoneFunc = jsObject->GetProperty("onBuildDone");
303 if (jsBuildDoneFunc->IsFunction()) {
304 jsBuildDoneFunc_ = JSRef<JSFunc>::Cast(jsBuildDoneFunc);
305 }
306
307 JSRef<JSVal> jsTransitionFunc = jsObject->GetProperty("pageTransition");
308 if (jsTransitionFunc->IsFunction()) {
309 jsTransitionFunc_ = JSRef<JSFunc>::Cast(jsTransitionFunc);
310 }
311
312 JSRef<JSVal> jsOnHideFunc = jsObject->GetProperty("onPageHide");
313 if (jsOnHideFunc->IsFunction()) {
314 jsOnHideFunc_ = JSRef<JSFunc>::Cast(jsOnHideFunc);
315 }
316
317 JSRef<JSVal> jsOnShowFunc = jsObject->GetProperty("onPageShow");
318 if (jsOnShowFunc->IsFunction()) {
319 jsOnShowFunc_ = JSRef<JSFunc>::Cast(jsOnShowFunc);
320 }
321
322 JSRef<JSVal> jsBackPressFunc = jsObject->GetProperty("onBackPress");
323 if (jsBackPressFunc->IsFunction()) {
324 jsBackPressFunc_ = JSRef<JSFunc>::Cast(jsBackPressFunc);
325 }
326
327 JSRef<JSVal> jsSetInitiallyProvidedValueFunc = jsObject->GetProperty("setInitiallyProvidedValue");
328 if (jsSetInitiallyProvidedValueFunc->IsFunction()) {
329 jsSetInitiallyProvidedValueFunc_ = JSRef<JSFunc>::Cast(jsSetInitiallyProvidedValueFunc);
330 }
331
332 if (!partialUpdate) {
333 JSRef<JSVal> jsUpdateWithValueParamsFunc = jsObject->GetProperty("updateWithValueParams");
334 if (jsUpdateWithValueParamsFunc->IsFunction()) {
335 jsUpdateWithValueParamsFunc_ = JSRef<JSFunc>::Cast(jsUpdateWithValueParamsFunc);
336 }
337 jsRenderFunc_ = jsRenderFunction;
338 }
339
340 JSRef<JSVal> jsOnFormRecycleFunc = jsObject->GetProperty("onFormRecycle");
341 if (jsOnFormRecycleFunc->IsFunction()) {
342 jsOnFormRecycleFunc_ = JSRef<JSFunc>::Cast(jsOnFormRecycleFunc);
343 }
344
345 JSRef<JSVal> jsOnFormRecoverFunc = jsObject->GetProperty("onFormRecover");
346 if (jsOnFormRecoverFunc->IsFunction()) {
347 jsOnFormRecoverFunc_ = JSRef<JSFunc>::Cast(jsOnFormRecoverFunc);
348 }
349 }
350
ViewFunctions(const JSRef<JSObject> & jsObject,const JSRef<JSFunc> & jsRenderFunction)351 ViewFunctions::ViewFunctions(const JSRef<JSObject>& jsObject, const JSRef<JSFunc>& jsRenderFunction)
352 {
353 ACE_DCHECK(jsObject);
354 InitViewFunctions(jsObject, jsRenderFunction, false);
355 }
356
ExecuteRender()357 void ViewFunctions::ExecuteRender()
358 {
359 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
360 if (jsRenderFunc_.IsEmpty()) {
361 LOGE("no render function in View!");
362 return;
363 }
364
365 auto func = jsRenderFunc_.Lock();
366 JSRef<JSVal> jsThis = jsObject_.Lock();
367 if (!jsThis->IsUndefined()) {
368 jsRenderResult_ = func->Call(jsThis);
369 } else {
370 LOGE("jsView Object is undefined and will not execute render function");
371 }
372 }
373
ExecuteAppear()374 void ViewFunctions::ExecuteAppear()
375 {
376 ExecuteFunction(jsAppearFunc_, "aboutToAppear");
377 }
378
ExecuteDisappear()379 void ViewFunctions::ExecuteDisappear()
380 {
381 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
382 if (jsDisappearFunc_.IsEmpty()) {
383 return;
384 }
385 ACE_SCOPED_TRACE("%s", "aboutToDisappear");
386 JSRef<JSVal> jsObject = jsObject_.Lock();
387 std::string functionName("aboutToDisappear");
388 AceScopedPerformanceCheck scoped(functionName);
389 if (!jsObject->IsUndefined()) {
390 jsDisappearFunc_.Lock()->Call(jsObject);
391 } else {
392 LOGE("jsView Object is undefined and will not execute aboutToDisappear function");
393 }
394 }
395
ExecuteAboutToRecycle()396 void ViewFunctions::ExecuteAboutToRecycle()
397 {
398 ExecuteFunction(jsAboutToRecycleFunc_, "aboutToRecycleInternal");
399 }
400
HasLayout() const401 bool ViewFunctions::HasLayout() const
402 {
403 return !jsLayoutFunc_.IsEmpty();
404 }
405
HasMeasure() const406 bool ViewFunctions::HasMeasure() const
407 {
408 return !jsMeasureFunc_.IsEmpty();
409 }
410
HasPlaceChildren() const411 bool ViewFunctions::HasPlaceChildren() const
412 {
413 return !jsPlaceChildrenFunc_.IsEmpty();
414 }
415
HasMeasureSize() const416 bool ViewFunctions::HasMeasureSize() const
417 {
418 return !jsMeasureSizeFunc_.IsEmpty();
419 }
420
ExecuteAboutToBeDeleted()421 void ViewFunctions::ExecuteAboutToBeDeleted()
422 {
423 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
424 if (jsAboutToBeDeletedFunc_.IsEmpty()) {
425 return;
426 }
427 ACE_SCOPED_TRACE("%s", "aboutToBeDeleted");
428 JSRef<JSVal> jsObject = jsObject_.Lock();
429 std::string functionName("aboutToBeDeleted");
430 AceScopedPerformanceCheck scoped(functionName);
431 if (!jsObject->IsUndefined()) {
432 jsAboutToBeDeletedFunc_.Lock()->Call(jsObject);
433 } else {
434 LOGE("jsView Object is undefined and will not execute aboutToBeDeleted function");
435 }
436 }
437
ExecuteAboutToRender()438 void ViewFunctions::ExecuteAboutToRender()
439 {
440 // for developer callback.
441 ExecuteFunction(jsAboutToBuildFunc_, "aboutToBuild");
442 // for state manager mark rendering progress.
443 ExecuteFunction(jsAboutToRenderFunc_, "aboutToRender");
444 }
445
ExecuteOnRenderDone()446 void ViewFunctions::ExecuteOnRenderDone()
447 {
448 // for state manager reset rendering progress.
449 ExecuteFunction(jsRenderDoneFunc_, "onRenderDone");
450 // for developer callback.
451 ExecuteFunction(jsBuildDoneFunc_, "onBuildDone");
452 }
453
ExecuteTransition()454 void ViewFunctions::ExecuteTransition()
455 {
456 ExecuteFunction(jsTransitionFunc_, "pageTransition");
457 }
458
HasPageTransition() const459 bool ViewFunctions::HasPageTransition() const
460 {
461 return !jsTransitionFunc_.IsEmpty();
462 }
463
ExecuteShow()464 void ViewFunctions::ExecuteShow()
465 {
466 ExecuteFunction(jsOnShowFunc_, "onPageShow");
467 }
468
ExecuteHide()469 void ViewFunctions::ExecuteHide()
470 {
471 ExecuteFunction(jsOnHideFunc_, "onPageHide");
472 }
473
ExecuteInitiallyProvidedValue(const std::string & jsonData)474 void ViewFunctions::ExecuteInitiallyProvidedValue(const std::string& jsonData)
475 {
476 ExecuteFunctionWithParams(jsSetInitiallyProvidedValueFunc_, "setInitiallyProvidedValue", jsonData);
477 }
478
479 // Method not needed for Partial Update code path
ExecuteUpdateWithValueParams(const std::string & jsonData)480 void ViewFunctions::ExecuteUpdateWithValueParams(const std::string& jsonData)
481 {
482 ExecuteFunctionWithParams(jsUpdateWithValueParamsFunc_, "updateWithValueParams", jsonData);
483 }
484
ExecuteOnBackPress()485 bool ViewFunctions::ExecuteOnBackPress()
486 {
487 auto ret = ExecuteFunctionWithReturn(jsBackPressFunc_, "onBackPress");
488 if (!ret->IsEmpty() && ret->IsBoolean()) {
489 return ret->ToBoolean();
490 }
491 return false;
492 }
493
ExecuteFunction(JSWeak<JSFunc> & func,const char * debugInfo)494 void ViewFunctions::ExecuteFunction(JSWeak<JSFunc>& func, const char* debugInfo)
495 {
496 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
497 if (func.IsEmpty()) {
498 return;
499 }
500 ACE_SCOPED_TRACE("%s", debugInfo);
501 JSRef<JSVal> jsObject = jsObject_.Lock();
502 if (!jsObject->IsUndefined()) {
503 std::string functionName(debugInfo);
504 AceScopedPerformanceCheck scoped(functionName);
505 func.Lock()->Call(jsObject);
506 } else {
507 LOGE("jsObject is undefined. Internal error while trying to exec %{public}s", debugInfo);
508 }
509 }
510
ExecuteFunctionWithReturn(JSWeak<JSFunc> & func,const char * debugInfo)511 JSRef<JSVal> ViewFunctions::ExecuteFunctionWithReturn(JSWeak<JSFunc>& func, const char* debugInfo)
512 {
513 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_, JSRef<JSVal>::Make())
514 if (func.IsEmpty()) {
515 return JSRef<JSVal>::Make();
516 }
517 ACE_SCOPED_TRACE("%s", debugInfo);
518 JSRef<JSVal> jsObject = jsObject_.Lock();
519 std::string functionName(debugInfo);
520 AceScopedPerformanceCheck scoped(functionName);
521 JSRef<JSVal> result = func.Lock()->Call(jsObject);
522 if (result.IsEmpty()) {
523 LOGE("Error calling %{public}s", debugInfo);
524 }
525 return result;
526 }
527
ExecuteFunctionWithParams(JSWeak<JSFunc> & func,const char * debugInfo,const std::string & jsonData)528 void ViewFunctions::ExecuteFunctionWithParams(JSWeak<JSFunc>& func, const char* debugInfo, const std::string& jsonData)
529 {
530 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
531 if (func.IsEmpty()) {
532 return;
533 }
534
535 JSRef<JSObject> obj = JSRef<JSObject>::New();
536 JSRef<JSVal> param = obj->ToJsonObject(jsonData.c_str());
537
538 JSRef<JSVal> jsObject = jsObject_.Lock();
539 JSRef<JSVal> result = func.Lock()->Call(jsObject, 1, ¶m);
540 if (result.IsEmpty()) {
541 LOGE("Error calling %{public}s", debugInfo);
542 }
543 }
544
545 // Baseline version of Destroy
Destroy(JSView * parentCustomView)546 void ViewFunctions::Destroy(JSView* parentCustomView)
547 {
548 // Might be called from parent view, before any result has been produced??
549 if (jsRenderResult_.IsEmpty()) {
550 return;
551 }
552
553 auto renderRes = jsRenderResult_.Lock();
554 if (renderRes.IsEmpty() || !renderRes->IsObject()) {
555 return;
556 }
557
558 JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
559 if (!obj.IsEmpty()) {
560 // jsRenderResult_ maybe an js exception, not a JSView
561 JSView* view = obj->Unwrap<JSView>();
562 if (view != nullptr) {
563 view->Destroy(parentCustomView);
564 }
565 }
566 jsRenderResult_.Reset();
567 }
568
569 // PartialUpdate version of Destroy
Destroy()570 void ViewFunctions::Destroy()
571 {
572 // Might be called from parent view, before any result has been produced??
573 if (jsRenderResult_.IsEmpty()) {
574 return;
575 }
576
577 auto renderRes = jsRenderResult_.Lock();
578 if (renderRes.IsEmpty() || !renderRes->IsObject()) {
579 return;
580 }
581
582 // merging: when would a render function return a JSView ?
583 JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
584 if (!obj.IsEmpty()) {
585 // jsRenderResult_ maybe an js exception, not a JSView
586 JSView* view = obj->Unwrap<JSView>();
587 if (view != nullptr) {
588 LOGE("NOTE NOTE NOTE render returned a JSView object that's dangling!");
589 }
590 }
591 jsObject_.Reset();
592 jsRenderResult_.Reset();
593 }
594
595 // Partial update method
ExecuteRerender()596 void ViewFunctions::ExecuteRerender()
597 {
598 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
599 if (jsRerenderFunc_.IsEmpty()) {
600 LOGE("no rerender function in View!");
601 return;
602 }
603
604 auto func = jsRerenderFunc_.Lock();
605 JSRef<JSVal> jsThis = jsObject_.Lock();
606 if (!jsThis->IsUndefined()) {
607 jsRenderResult_ = func->Call(jsThis);
608 } else {
609 LOGE("jsView Object is undefined and will not execute rerender function");
610 }
611 }
612
613 // Partial update method
ViewFunctions(const JSRef<JSObject> & jsObject)614 ViewFunctions::ViewFunctions(const JSRef<JSObject>& jsObject)
615 {
616 InitViewFunctions(jsObject, JSRef<JSFunc>(), true);
617 }
618
ExecuteOnFormRecycle()619 std::string ViewFunctions::ExecuteOnFormRecycle()
620 {
621 auto ret = ExecuteFunctionWithReturn(jsOnFormRecycleFunc_, "OnFormRecycle");
622 if (!ret->IsEmpty() && ret->IsString()) {
623 std::string statusData = ret->ToString();
624 return statusData.empty() ? EMPTY_STATUS_DATA : statusData;
625 }
626 LOGE("ExecuteOnFormRecycle failed");
627 return "";
628 }
629
ExecuteOnFormRecover(const std::string & statusData)630 void ViewFunctions::ExecuteOnFormRecover(const std::string& statusData)
631 {
632 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
633 if (jsOnFormRecoverFunc_.IsEmpty()) {
634 LOGE("jsOnFormRecoverFunc_ is null");
635 return;
636 }
637
638 std::string data;
639 if (statusData != EMPTY_STATUS_DATA) {
640 data = statusData;
641 }
642 auto jsData = JSRef<JSVal>::Make(ToJSValue(data));
643 auto func = jsOnFormRecoverFunc_.Lock();
644 func->Call(jsObject_.Lock(), 1, &jsData);
645 }
646 } // namespace OHOS::Ace::Framework
647