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