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 "frameworks/bridge/declarative_frontend/jsview/js_view_functions.h"
17
18 #include <memory>
19
20 #include "base/log/ace_trace.h"
21 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
22 #include "core/components_ng/base/frame_node.h"
23 #include "core/components_ng/layout/layout_wrapper.h"
24 #include "core/pipeline/base/composed_element.h"
25 #include "frameworks/bridge/declarative_frontend/engine/js_execution_scope_defines.h"
26 #include "frameworks/bridge/declarative_frontend/jsview/js_view.h"
27 #include "frameworks/bridge/declarative_frontend/jsview/js_view_measure_layout.h"
28 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
29
30 namespace OHOS::Ace::Framework {
31
32 #ifdef USE_ARK_ENGINE
33
34 namespace {
35
GenConstraint(const std::optional<NG::LayoutConstraintF> & parentConstraint)36 JSRef<JSObject> GenConstraint(const std::optional<NG::LayoutConstraintF>& parentConstraint)
37 {
38 auto minSize = parentConstraint->minSize;
39 auto maxSize = parentConstraint->maxSize;
40 JSRef<JSObject> constraint = JSRef<JSObject>::New();
41 constraint->SetProperty<double>("minWidth", minSize.Width());
42 constraint->SetProperty<double>("minHeight", minSize.Height());
43 constraint->SetProperty<double>("maxWidth", maxSize.Width());
44 constraint->SetProperty<double>("maxHeight", maxSize.Height());
45 return constraint;
46 }
47
GenPadding(const std::unique_ptr<NG::PaddingProperty> & paddingNative)48 JSRef<JSObject> GenPadding(const std::unique_ptr<NG::PaddingProperty>& paddingNative)
49 {
50 JSRef<JSObject> padding = JSRef<JSObject>::New();
51 padding->SetProperty("top", paddingNative->top->ToString());
52 padding->SetProperty("right", paddingNative->right->ToString());
53 padding->SetProperty("bottom", paddingNative->bottom->ToString());
54 padding->SetProperty("left", paddingNative->left->ToString());
55 return padding;
56 }
57
GenEdgeWidths(const std::unique_ptr<NG::BorderWidthProperty> & edgeWidthsNative)58 JSRef<JSObject> GenEdgeWidths(const std::unique_ptr<NG::BorderWidthProperty>& edgeWidthsNative)
59 {
60 JSRef<JSObject> edgeWidths = JSRef<JSObject>::New();
61 edgeWidths->SetProperty("top", edgeWidthsNative->topDimen->ToString());
62 edgeWidths->SetProperty("right", edgeWidthsNative->rightDimen->ToString());
63 edgeWidths->SetProperty("bottom", edgeWidthsNative->bottomDimen->ToString());
64 edgeWidths->SetProperty("left", edgeWidthsNative->leftDimen->ToString());
65 return edgeWidths;
66 }
67
GenBorderInfo(const RefPtr<NG::LayoutWrapper> & layoutWrapper)68 JSRef<JSObject> GenBorderInfo(const RefPtr<NG::LayoutWrapper>& layoutWrapper)
69 {
70 JSRef<JSObject> borderInfo = JSRef<JSObject>::New();
71 auto layoutProperty = layoutWrapper->GetLayoutProperty();
72 if (!layoutProperty) {
73 return borderInfo;
74 }
75
76 const std::unique_ptr<NG::PaddingProperty> defaultPadding = std::make_unique<NG::PaddingProperty>();
77 const std::unique_ptr<NG::BorderWidthProperty>& defaultEdgeWidth = std::make_unique<NG::BorderWidthProperty>();
78 borderInfo->SetPropertyObject("borderWidth",
79 GenEdgeWidths(
80 layoutProperty->GetBorderWidthProperty() ? layoutProperty->GetBorderWidthProperty() : defaultEdgeWidth));
81
82 borderInfo->SetPropertyObject("margin",
83 GenPadding(layoutProperty->GetMarginProperty() ? layoutProperty->GetMarginProperty() : defaultPadding));
84 borderInfo->SetPropertyObject("padding",
85 GenPadding(layoutProperty->GetPaddingProperty() ? layoutProperty->GetPaddingProperty() : defaultPadding));
86
87 return borderInfo;
88 }
89
GenPositionInfo(const RefPtr<NG::LayoutWrapper> & layoutWrapper)90 JSRef<JSObject> GenPositionInfo(const RefPtr<NG::LayoutWrapper>& layoutWrapper)
91 {
92 auto offset = layoutWrapper->GetGeometryNode()->GetFrameOffset();
93 JSRef<JSObject> position = JSRef<JSObject>::New();
94 position->SetProperty("x", offset.GetX());
95 position->SetProperty("y", offset.GetY());
96 return position;
97 }
98
FillSubComponetProperty(JSRef<JSObject> & info,const RefPtr<NG::LayoutWrapper> & layoutWrapper,const size_t & index)99 void FillSubComponetProperty(JSRef<JSObject>& info, const RefPtr<NG::LayoutWrapper>& layoutWrapper, const size_t& index)
100 {
101 info->SetProperty<std::string>("name", layoutWrapper->GetHostNode()->GetTag());
102 info->SetProperty<std::string>("id", std::to_string(layoutWrapper->GetHostNode()->GetId()));
103 info->SetPropertyObject("constraint", GenConstraint(layoutWrapper->GetLayoutProperty()->GetLayoutConstraint()));
104 info->SetPropertyObject("borderInfo", GenBorderInfo(layoutWrapper));
105 info->SetPropertyObject("position", GenPositionInfo(layoutWrapper));
106 }
107
GenLayoutChildArray(std::list<RefPtr<NG::LayoutWrapper>> children)108 JSRef<JSArray> GenLayoutChildArray(std::list<RefPtr<NG::LayoutWrapper>> children)
109 {
110 JSRef<JSArray> childInfo = JSRef<JSArray>::New();
111 JSRef<JSFunc> layoutFunc = JSRef<JSFunc>::New<FunctionCallback>(ViewMeasureLayout::JSLayout);
112 size_t index = 0;
113
114 for (const auto& iter : children) {
115 JSRef<JSObject> info = JSRef<JSObject>::New();
116 FillSubComponetProperty(info, iter, index);
117 info->SetPropertyObject("layout", layoutFunc);
118 childInfo->SetValueAt(index++, info);
119 }
120
121 return childInfo;
122 }
123
GenMeasureChildArray(std::list<RefPtr<NG::LayoutWrapper>> children)124 JSRef<JSArray> GenMeasureChildArray(std::list<RefPtr<NG::LayoutWrapper>> children)
125 {
126 JSRef<JSArray> childInfo = JSRef<JSArray>::New();
127 JSRef<JSFunc> measureFunc = JSRef<JSFunc>::New<FunctionCallback>(ViewMeasureLayout::JSMeasure);
128 size_t index = 0;
129
130 for (const auto& iter : children) {
131 JSRef<JSObject> info = JSRef<JSObject>::New();
132 FillSubComponetProperty(info, iter, index);
133 info->SetPropertyObject("measure", measureFunc);
134 childInfo->SetValueAt(index++, info);
135 }
136
137 return childInfo;
138 }
139
140 } // namespace
141
ExecuteLayout(NG::LayoutWrapper * layoutWrapper)142 void ViewFunctions::ExecuteLayout(NG::LayoutWrapper* layoutWrapper)
143 {
144 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
145 ACE_SCOPED_TRACE("ViewFunctions::ExecuteLayout");
146 auto children = layoutWrapper->GetAllChildrenWithBuild();
147 auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
148 auto constraint = GenConstraint(parentConstraint);
149 auto childArray = GenLayoutChildArray(children);
150 JSRef<JSVal> params[2] = { childArray, constraint };
151
152 ViewMeasureLayout::SetLayoutChildren(layoutWrapper->GetAllChildrenWithBuild());
153 ViewMeasureLayout::SetDefaultMeasureConstraint(parentConstraint.value());
154 jsLayoutFunc_.Lock()->Call(jsObject_.Lock(), 2, params);
155 }
156
ExecuteMeasure(NG::LayoutWrapper * layoutWrapper)157 void ViewFunctions::ExecuteMeasure(NG::LayoutWrapper* layoutWrapper)
158 {
159 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
160 ACE_SCOPED_TRACE("ViewFunctions::ExecuteMeasure");
161 auto children = layoutWrapper->GetAllChildrenWithBuild();
162 auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
163 auto constraint = GenConstraint(parentConstraint);
164 auto childArray = GenMeasureChildArray(children);
165 JSRef<JSVal> params[2];
166
167 params[0] = childArray;
168 params[1] = constraint;
169
170 ViewMeasureLayout::SetMeasureChildren(children);
171 ViewMeasureLayout::SetDefaultMeasureConstraint(parentConstraint.value());
172 jsMeasureFunc_.Lock()->Call(jsObject_.Lock(), 2, params);
173 }
174
ExecuteReload(bool deep)175 void ViewFunctions::ExecuteReload(bool deep)
176 {
177 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
178 ACE_SCOPED_TRACE("ViewFunctions::ExecuteReload");
179 auto func = jsReloadFunc_.Lock();
180 if (!func.IsEmpty()) {
181 JSRef<JSVal> params[1];
182 params[0] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(deep)));
183 func->Call(jsObject_.Lock(), 1, params);
184 } else {
185 LOGE("the reload func is null");
186 }
187 }
188
ExecuteForceNodeRerender(int32_t elemId)189 void ViewFunctions::ExecuteForceNodeRerender(int32_t elemId)
190 {
191 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
192 ACE_SCOPED_TRACE("ViewFunctions::ExecuteForceNodeRerender");
193 auto func = jsForceRerenderNodeFunc_.Lock();
194 if (!func.IsEmpty()) {
195 JSRef<JSVal> params[1];
196 params[0] = JSRef<JSVal>(JSVal(JsiValueConvertor::toJsiValue(elemId)));
197 func->Call(jsObject_.Lock(), 1, params);
198 } else {
199 LOGE("the force node rerender func is null");
200 }
201 }
202
203 #else
204
205 void ViewFunctions::ExecuteLayout(NG::LayoutWrapper* layoutWrapper) {}
206
207 void ViewFunctions::ExecuteMeasure(NG::LayoutWrapper* layoutWrapper) {}
208
209 void ViewFunctions::ExecuteReload(bool deep) {}
210
211 void ViewFunctions::ExecuteForceNodeRerender(int32_t elemId) {}
212
213 #endif
214
InitViewFunctions(const JSRef<JSObject> & jsObject,const JSRef<JSFunc> & jsRenderFunction,bool partialUpdate)215 void ViewFunctions::InitViewFunctions(
216 const JSRef<JSObject>& jsObject, const JSRef<JSFunc>& jsRenderFunction, bool partialUpdate)
217 {
218 jsObject_ = jsObject;
219
220 if (partialUpdate) {
221 if (jsObject->GetProperty("initialRender")->IsFunction()) {
222 JSRef<JSVal> jsRenderFunc = jsObject->GetProperty("initialRenderView");
223 if (jsRenderFunc->IsFunction()) {
224 jsRenderFunc_ = JSRef<JSFunc>::Cast(jsRenderFunc);
225 } else {
226 LOGE("View lacks mandatory 'initialRenderView()' function, fatal internal error.");
227 }
228 } else {
229 LOGE("View lacks mandatory 'initialRender()' function, fatal internal error.");
230 }
231
232 JSRef<JSVal> jsRerenderFunc = jsObject->GetProperty("rerender");
233 if (jsRerenderFunc->IsFunction()) {
234 jsRerenderFunc_ = JSRef<JSFunc>::Cast(jsRerenderFunc);
235 } else {
236 LOGE("View lacks mandatory 'rerender()' function, fatal internal error.");
237 }
238
239 JSRef<JSVal> jsReloadFunc = jsObject->GetProperty("forceCompleteRerender");
240 if (jsReloadFunc->IsFunction()) {
241 jsReloadFunc_ = JSRef<JSFunc>::Cast(jsReloadFunc);
242 } else {
243 LOGE("View lacks mandatory 'forceCompleteRerender()' function, fatal internal error.");
244 }
245
246 JSRef<JSVal> jsForceRerenderNodeFunc = jsObject->GetProperty("forceRerenderNode");
247 if (jsReloadFunc->IsFunction()) {
248 jsForceRerenderNodeFunc_ = JSRef<JSFunc>::Cast(jsForceRerenderNodeFunc);
249 } else {
250 LOGE("View lacks mandatory 'forceRerenderNode()' function, fatal internal error.");
251 }
252 }
253
254 JSRef<JSVal> jsAppearFunc = jsObject->GetProperty("aboutToAppear");
255 if (jsAppearFunc->IsFunction()) {
256 jsAppearFunc_ = JSRef<JSFunc>::Cast(jsAppearFunc);
257 }
258
259 JSRef<JSVal> jsDisappearFunc = jsObject->GetProperty("aboutToDisappear");
260 if (jsDisappearFunc->IsFunction()) {
261 jsDisappearFunc_ = JSRef<JSFunc>::Cast(jsDisappearFunc);
262 } else {
263 LOGD("aboutToDisappear is not a function");
264 }
265
266 JSRef<JSVal> jsLayoutFunc = jsObject->GetProperty("onLayout");
267 if (jsLayoutFunc->IsFunction()) {
268 jsLayoutFunc_ = JSRef<JSFunc>::Cast(jsLayoutFunc);
269 }
270
271 JSRef<JSVal> jsMeasureFunc = jsObject->GetProperty("onMeasure");
272 if (jsMeasureFunc->IsFunction()) {
273 jsMeasureFunc_ = JSRef<JSFunc>::Cast(jsMeasureFunc);
274 }
275
276 JSRef<JSVal> jsAboutToBeDeletedFunc = jsObject->GetProperty("aboutToBeDeleted");
277 if (jsAboutToBeDeletedFunc->IsFunction()) {
278 jsAboutToBeDeletedFunc_ = JSRef<JSFunc>::Cast(jsAboutToBeDeletedFunc);
279 } else {
280 LOGD("aboutToBeDeleted is not a function");
281 }
282
283 JSRef<JSVal> jsAboutToRenderFunc = jsObject->GetProperty("aboutToRender");
284 if (jsAboutToRenderFunc->IsFunction()) {
285 jsAboutToRenderFunc_ = JSRef<JSFunc>::Cast(jsAboutToRenderFunc);
286 } else {
287 LOGD("aboutToRender is not a function");
288 }
289
290 JSRef<JSVal> jsRenderDoneFunc = jsObject->GetProperty("onRenderDone");
291 if (jsRenderDoneFunc->IsFunction()) {
292 jsRenderDoneFunc_ = JSRef<JSFunc>::Cast(jsRenderDoneFunc);
293 } else {
294 LOGD("onRenderDone is not a function");
295 }
296
297 JSRef<JSVal> jsAboutToBuildFunc = jsObject->GetProperty("aboutToBuild");
298 if (jsAboutToBuildFunc->IsFunction()) {
299 jsAboutToBuildFunc_ = JSRef<JSFunc>::Cast(jsAboutToBuildFunc);
300 } else {
301 LOGD("aboutToBuild is not a function");
302 }
303
304 JSRef<JSVal> jsBuildDoneFunc = jsObject->GetProperty("onBuildDone");
305 if (jsBuildDoneFunc->IsFunction()) {
306 jsBuildDoneFunc_ = JSRef<JSFunc>::Cast(jsBuildDoneFunc);
307 } else {
308 LOGD("onBuildDone is not a function");
309 }
310
311 JSRef<JSVal> jsTransitionFunc = jsObject->GetProperty("pageTransition");
312 if (jsTransitionFunc->IsFunction()) {
313 jsTransitionFunc_ = JSRef<JSFunc>::Cast(jsTransitionFunc);
314 } else {
315 LOGD("transition is not a function");
316 }
317
318 JSRef<JSVal> jsOnHideFunc = jsObject->GetProperty("onPageHide");
319 if (jsOnHideFunc->IsFunction()) {
320 jsOnHideFunc_ = JSRef<JSFunc>::Cast(jsOnHideFunc);
321 } else {
322 LOGD("onHide is not a function");
323 }
324
325 JSRef<JSVal> jsOnShowFunc = jsObject->GetProperty("onPageShow");
326 if (jsOnShowFunc->IsFunction()) {
327 jsOnShowFunc_ = JSRef<JSFunc>::Cast(jsOnShowFunc);
328 } else {
329 LOGD("onShow is not a function");
330 }
331
332 JSRef<JSVal> jsBackPressFunc = jsObject->GetProperty("onBackPress");
333 if (jsBackPressFunc->IsFunction()) {
334 jsBackPressFunc_ = JSRef<JSFunc>::Cast(jsBackPressFunc);
335 } else {
336 LOGD("onBackPress is not a function");
337 }
338
339 JSRef<JSVal> jsSetInitiallyProvidedValueFunc = jsObject->GetProperty("setInitiallyProvidedValue");
340 if (jsSetInitiallyProvidedValueFunc->IsFunction()) {
341 jsSetInitiallyProvidedValueFunc_ = JSRef<JSFunc>::Cast(jsSetInitiallyProvidedValueFunc);
342 }
343
344 if (!partialUpdate) {
345 JSRef<JSVal> jsUpdateWithValueParamsFunc = jsObject->GetProperty("updateWithValueParams");
346 if (jsUpdateWithValueParamsFunc->IsFunction()) {
347 LOGD("updateWithValueParams is a function");
348 jsUpdateWithValueParamsFunc_ = JSRef<JSFunc>::Cast(jsUpdateWithValueParamsFunc);
349 } else {
350 LOGD("updateWithValueParams is not a function");
351 }
352
353 #ifdef UICAST_COMPONENT_SUPPORTED
354 JSRef<JSVal> jsCreateChildViewFunc = jsObject->GetProperty("createChildView");
355 if (jsCreateChildViewFunc->IsFunction()) {
356 LOGI("UICast createChildView is a function");
357 jsCreateChildViewFunc_ = JSRef<JSFunc>::Cast(jsCreateChildViewFunc);
358 } else {
359 LOGI("UICast createChildView is not a function");
360 }
361
362 JSRef<JSVal> jsRouterHandleFunc = jsObject->GetProperty("routerHandle");
363 if (jsRouterHandleFunc->IsFunction()) {
364 LOGI("UICast routerHandle is a function");
365 jsRouterHandleFunc_ = JSRef<JSFunc>::Cast(jsRouterHandleFunc);
366 } else {
367 LOGI("UICast routerHandle is not a function");
368 }
369
370 JSRef<JSVal> jsReplayOnEventFunc = jsObject->GetProperty("replayOnEvent");
371 if (jsReplayOnEventFunc->IsFunction()) {
372 LOGI("UICast replayOnEvent is a function");
373 jsReplayOnEventFunc_ = JSRef<JSFunc>::Cast(jsReplayOnEventFunc);
374 } else {
375 LOGI("UICast replayOnEvent is not a function");
376 }
377 #endif
378
379 jsRenderFunc_ = jsRenderFunction;
380 }
381 }
382
ViewFunctions(const JSRef<JSObject> & jsObject,const JSRef<JSFunc> & jsRenderFunction)383 ViewFunctions::ViewFunctions(const JSRef<JSObject>& jsObject, const JSRef<JSFunc>& jsRenderFunction)
384 {
385 ACE_DCHECK(jsObject);
386 InitViewFunctions(jsObject, jsRenderFunction, false);
387 }
388
ExecuteRender()389 void ViewFunctions::ExecuteRender()
390 {
391 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
392 if (jsRenderFunc_.IsEmpty()) {
393 LOGE("no render function in View!");
394 return;
395 }
396
397 auto func = jsRenderFunc_.Lock();
398 JSRef<JSVal> jsThis = jsObject_.Lock();
399 jsRenderResult_ = func->Call(jsThis);
400 }
401
ExecuteAppear()402 void ViewFunctions::ExecuteAppear()
403 {
404 ExecuteFunction(jsAppearFunc_, "aboutToAppear");
405 }
406
ExecuteDisappear()407 void ViewFunctions::ExecuteDisappear()
408 {
409 ExecuteFunction(jsDisappearFunc_, "aboutToDisappear");
410 }
411
HasLayout() const412 bool ViewFunctions::HasLayout() const
413 {
414 return !jsLayoutFunc_.IsEmpty();
415 }
416
HasMeasure() const417 bool ViewFunctions::HasMeasure() const
418 {
419 return !jsMeasureFunc_.IsEmpty();
420 }
421
ExecuteAboutToBeDeleted()422 void ViewFunctions::ExecuteAboutToBeDeleted()
423 {
424 ExecuteFunction(jsAboutToBeDeletedFunc_, "aboutToDisappear");
425 }
426
ExecuteAboutToRender()427 void ViewFunctions::ExecuteAboutToRender()
428 {
429 // for developer callback.
430 ExecuteFunction(jsAboutToBuildFunc_, "aboutToBuild");
431 // for state manager mark rendering progress.
432 ExecuteFunction(jsAboutToRenderFunc_, "aboutToRender");
433 }
434
ExecuteOnRenderDone()435 void ViewFunctions::ExecuteOnRenderDone()
436 {
437 // for state manager reset rendering progress.
438 ExecuteFunction(jsRenderDoneFunc_, "onRenderDone");
439 // for developer callback.
440 ExecuteFunction(jsBuildDoneFunc_, "onBuildDone");
441 }
442
ExecuteTransition()443 void ViewFunctions::ExecuteTransition()
444 {
445 ExecuteFunction(jsTransitionFunc_, "pageTransition");
446 }
447
HasPageTransition() const448 bool ViewFunctions::HasPageTransition() const
449 {
450 return !jsTransitionFunc_.IsEmpty();
451 }
452
ExecuteShow()453 void ViewFunctions::ExecuteShow()
454 {
455 ExecuteFunction(jsOnShowFunc_, "onPageShow");
456 }
457
ExecuteHide()458 void ViewFunctions::ExecuteHide()
459 {
460 ExecuteFunction(jsOnHideFunc_, "onPageHide");
461 }
462
ExecuteInitiallyProvidedValue(const std::string & jsonData)463 void ViewFunctions::ExecuteInitiallyProvidedValue(const std::string& jsonData)
464 {
465 ExecuteFunctionWithParams(jsSetInitiallyProvidedValueFunc_, "setInitiallyProvidedValue", jsonData);
466 }
467
468 // Method not needed for Partial Update code path
ExecuteUpdateWithValueParams(const std::string & jsonData)469 void ViewFunctions::ExecuteUpdateWithValueParams(const std::string& jsonData)
470 {
471 ExecuteFunctionWithParams(jsUpdateWithValueParamsFunc_, "updateWithValueParams", jsonData);
472 }
473
474 #ifdef UICAST_COMPONENT_SUPPORTED
ExecuteCreateChildView(const std::string & jsonData)475 void ViewFunctions::ExecuteCreateChildView(const std::string& jsonData)
476 {
477 ExecuteFunctionWithParams(jsCreateChildViewFunc_, "createChildView", jsonData);
478 }
479
ExecuteRouterHandle(const std::string & jsonData)480 void ViewFunctions::ExecuteRouterHandle(const std::string& jsonData)
481 {
482 ExecuteFunctionWithParams(jsRouterHandleFunc_, "routerHandle", jsonData);
483 }
484
ExecuteReplayOnEvent(const std::string & jsonData)485 void ViewFunctions::ExecuteReplayOnEvent(const std::string& jsonData)
486 {
487 ExecuteFunctionWithParams(jsReplayOnEventFunc_, "replayOnEvent", jsonData);
488 }
489 #endif
490
ExecuteOnBackPress()491 bool ViewFunctions::ExecuteOnBackPress()
492 {
493 auto ret = ExecuteFunctionWithReturn(jsBackPressFunc_, "onBackPress");
494 if (!ret->IsEmpty() && ret->IsBoolean()) {
495 return ret->ToBoolean();
496 }
497 return false;
498 }
499
ExecuteFunction(JSWeak<JSFunc> & func,const char * debugInfo)500 void ViewFunctions::ExecuteFunction(JSWeak<JSFunc>& func, const char* debugInfo)
501 {
502 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
503 if (func.IsEmpty()) {
504 LOGD("View doesn't have %{public}s() method!", debugInfo);
505 return;
506 }
507 ACE_SCOPED_TRACE("%s", debugInfo);
508 JSRef<JSVal> jsObject = jsObject_.Lock();
509 func.Lock()->Call(jsObject);
510 }
511
ExecuteFunctionWithReturn(JSWeak<JSFunc> & func,const char * debugInfo)512 JSRef<JSVal> ViewFunctions::ExecuteFunctionWithReturn(JSWeak<JSFunc>& func, const char* debugInfo)
513 {
514 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_, JSRef<JSVal>::Make())
515 if (func.IsEmpty()) {
516 LOGD("View doesn't have %{public}s() method!", debugInfo);
517 return JSRef<JSVal>::Make();
518 }
519 ACE_SCOPED_TRACE("%s", debugInfo);
520 JSRef<JSVal> jsObject = jsObject_.Lock();
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 LOGD("View doesn't have %{public}s() method!", debugInfo);
533 return;
534 }
535
536 JSRef<JSObject> obj = JSRef<JSObject>::New();
537 JSRef<JSVal> param = obj->ToJsonObject(jsonData.c_str());
538
539 JSRef<JSVal> jsObject = jsObject_.Lock();
540 JSRef<JSVal> result = func.Lock()->Call(jsObject, 1, ¶m);
541 if (result.IsEmpty()) {
542 LOGE("Error calling %{public}s", debugInfo);
543 }
544 }
545
546 // Baseline version of Destroy
Destroy(JSView * parentCustomView)547 void ViewFunctions::Destroy(JSView* parentCustomView)
548 {
549 LOGD("Destroy");
550 // Might be called from parent view, before any result has been produced??
551 if (jsRenderResult_.IsEmpty()) {
552 LOGD("ViewFunctions::Destroy() -> no previous render result to delete");
553 return;
554 }
555
556 auto renderRes = jsRenderResult_.Lock();
557 if (renderRes.IsEmpty() || !renderRes->IsObject()) {
558 LOGD("ViewFunctions::Destroy() -> result not an object");
559 return;
560 }
561
562 JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
563 if (!obj.IsEmpty()) {
564 // jsRenderResult_ maybe an js exception, not a JSView
565 JSView* view = obj->Unwrap<JSView>();
566 if (view != nullptr) {
567 view->Destroy(parentCustomView);
568 }
569 }
570 jsRenderResult_.Reset();
571 LOGD("ViewFunctions::Destroy() end");
572 }
573
574 // PartialUpdate version of Destroy
Destroy()575 void ViewFunctions::Destroy()
576 {
577 LOGD("Destroy");
578
579 // Might be called from parent view, before any result has been produced??
580 if (jsRenderResult_.IsEmpty()) {
581 LOGD("ViewFunctions::Destroy() -> no previous render result to delete");
582 return;
583 }
584
585 auto renderRes = jsRenderResult_.Lock();
586 if (renderRes.IsEmpty() || !renderRes->IsObject()) {
587 LOGD("ViewFunctions::Destroy() -> result not an object");
588 return;
589 }
590
591 // merging: when would a render function return a JSView ?
592 JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
593 if (!obj.IsEmpty()) {
594 // jsRenderResult_ maybe an js exception, not a JSView
595 JSView* view = obj->Unwrap<JSView>();
596 if (view != nullptr) {
597 LOGE("NOTE NOTE NOTE render returned a JSView object that's dangling!");
598 }
599 }
600 jsObject_.Reset();
601 jsRenderResult_.Reset();
602
603 LOGD("ViewFunctions::Destroy() end");
604 }
605
606 // Partial update method
ExecuteRerender()607 void ViewFunctions::ExecuteRerender()
608 {
609 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
610 if (jsRerenderFunc_.IsEmpty()) {
611 LOGE("no rerender function in View!");
612 return;
613 }
614
615 auto func = jsRerenderFunc_.Lock();
616 JSRef<JSVal> jsThis = jsObject_.Lock();
617 jsRenderResult_ = func->Call(jsThis);
618 }
619
620 // Partial update method
ViewFunctions(const JSRef<JSObject> & jsObject)621 ViewFunctions::ViewFunctions(const JSRef<JSObject>& jsObject)
622 {
623 InitViewFunctions(jsObject, JSRef<JSFunc>(), true);
624 }
625
626 } // namespace OHOS::Ace::Framework
627