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