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 if (!jsThis->IsUndefined()) {
400 jsRenderResult_ = func->Call(jsThis);
401 } else {
402 LOGE("jsView Object is undefined and will not execute render function");
403 }
404 }
405
ExecuteAppear()406 void ViewFunctions::ExecuteAppear()
407 {
408 ExecuteFunction(jsAppearFunc_, "aboutToAppear");
409 }
410
ExecuteDisappear()411 void ViewFunctions::ExecuteDisappear()
412 {
413 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
414 if (jsDisappearFunc_.IsEmpty()) {
415 LOGD("View doesn't have %{public}s() method!", "aboutToDisappear");
416 return;
417 }
418 ACE_SCOPED_TRACE("%s", "aboutToDisappear");
419 JSRef<JSVal> jsObject = jsObject_.Lock();
420 std::string functionName("aboutToDisappear");
421 if (!jsObject->IsUndefined()) {
422 jsDisappearFunc_.Lock()->Call(jsObject);
423 } else {
424 LOGE("jsView Object is undefined and will not execute aboutToDisappear function");
425 }
426 }
427
HasLayout() const428 bool ViewFunctions::HasLayout() const
429 {
430 return !jsLayoutFunc_.IsEmpty();
431 }
432
HasMeasure() const433 bool ViewFunctions::HasMeasure() const
434 {
435 return !jsMeasureFunc_.IsEmpty();
436 }
437
ExecuteAboutToBeDeleted()438 void ViewFunctions::ExecuteAboutToBeDeleted()
439 {
440 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
441 if (jsAboutToBeDeletedFunc_.IsEmpty()) {
442 LOGD("View doesn't have %{public}s() method!", "aboutToBeDeleted");
443 return;
444 }
445 ACE_SCOPED_TRACE("%s", "aboutToBeDeleted");
446 JSRef<JSVal> jsObject = jsObject_.Lock();
447 std::string functionName("aboutToBeDeleted");
448 if (!jsObject->IsUndefined()) {
449 jsAboutToBeDeletedFunc_.Lock()->Call(jsObject);
450 } else {
451 LOGE("jsView Object is undefined and will not execute aboutToBeDeleted function");
452 }
453 }
454
ExecuteAboutToRender()455 void ViewFunctions::ExecuteAboutToRender()
456 {
457 // for developer callback.
458 ExecuteFunction(jsAboutToBuildFunc_, "aboutToBuild");
459 // for state manager mark rendering progress.
460 ExecuteFunction(jsAboutToRenderFunc_, "aboutToRender");
461 }
462
ExecuteOnRenderDone()463 void ViewFunctions::ExecuteOnRenderDone()
464 {
465 // for state manager reset rendering progress.
466 ExecuteFunction(jsRenderDoneFunc_, "onRenderDone");
467 // for developer callback.
468 ExecuteFunction(jsBuildDoneFunc_, "onBuildDone");
469 }
470
ExecuteTransition()471 void ViewFunctions::ExecuteTransition()
472 {
473 ExecuteFunction(jsTransitionFunc_, "pageTransition");
474 }
475
HasPageTransition() const476 bool ViewFunctions::HasPageTransition() const
477 {
478 return !jsTransitionFunc_.IsEmpty();
479 }
480
ExecuteShow()481 void ViewFunctions::ExecuteShow()
482 {
483 ExecuteFunction(jsOnShowFunc_, "onPageShow");
484 }
485
ExecuteHide()486 void ViewFunctions::ExecuteHide()
487 {
488 ExecuteFunction(jsOnHideFunc_, "onPageHide");
489 }
490
ExecuteInitiallyProvidedValue(const std::string & jsonData)491 void ViewFunctions::ExecuteInitiallyProvidedValue(const std::string& jsonData)
492 {
493 ExecuteFunctionWithParams(jsSetInitiallyProvidedValueFunc_, "setInitiallyProvidedValue", jsonData);
494 }
495
496 // Method not needed for Partial Update code path
ExecuteUpdateWithValueParams(const std::string & jsonData)497 void ViewFunctions::ExecuteUpdateWithValueParams(const std::string& jsonData)
498 {
499 ExecuteFunctionWithParams(jsUpdateWithValueParamsFunc_, "updateWithValueParams", jsonData);
500 }
501
502 #ifdef UICAST_COMPONENT_SUPPORTED
ExecuteCreateChildView(const std::string & jsonData)503 void ViewFunctions::ExecuteCreateChildView(const std::string& jsonData)
504 {
505 ExecuteFunctionWithParams(jsCreateChildViewFunc_, "createChildView", jsonData);
506 }
507
ExecuteRouterHandle(const std::string & jsonData)508 void ViewFunctions::ExecuteRouterHandle(const std::string& jsonData)
509 {
510 ExecuteFunctionWithParams(jsRouterHandleFunc_, "routerHandle", jsonData);
511 }
512
ExecuteReplayOnEvent(const std::string & jsonData)513 void ViewFunctions::ExecuteReplayOnEvent(const std::string& jsonData)
514 {
515 ExecuteFunctionWithParams(jsReplayOnEventFunc_, "replayOnEvent", jsonData);
516 }
517 #endif
518
ExecuteOnBackPress()519 bool ViewFunctions::ExecuteOnBackPress()
520 {
521 auto ret = ExecuteFunctionWithReturn(jsBackPressFunc_, "onBackPress");
522 if (!ret->IsEmpty() && ret->IsBoolean()) {
523 return ret->ToBoolean();
524 }
525 return false;
526 }
527
ExecuteFunction(JSWeak<JSFunc> & func,const char * debugInfo)528 void ViewFunctions::ExecuteFunction(JSWeak<JSFunc>& func, const char* debugInfo)
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 ACE_SCOPED_TRACE("%s", debugInfo);
536 JSRef<JSVal> jsObject = jsObject_.Lock();
537 func.Lock()->Call(jsObject);
538 }
539
ExecuteFunctionWithReturn(JSWeak<JSFunc> & func,const char * debugInfo)540 JSRef<JSVal> ViewFunctions::ExecuteFunctionWithReturn(JSWeak<JSFunc>& func, const char* debugInfo)
541 {
542 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_, JSRef<JSVal>::Make())
543 if (func.IsEmpty()) {
544 LOGD("View doesn't have %{public}s() method!", debugInfo);
545 return JSRef<JSVal>::Make();
546 }
547 ACE_SCOPED_TRACE("%s", debugInfo);
548 JSRef<JSVal> jsObject = jsObject_.Lock();
549 JSRef<JSVal> result = func.Lock()->Call(jsObject);
550 if (result.IsEmpty()) {
551 LOGE("Error calling %{public}s", debugInfo);
552 }
553 return result;
554 }
555
ExecuteFunctionWithParams(JSWeak<JSFunc> & func,const char * debugInfo,const std::string & jsonData)556 void ViewFunctions::ExecuteFunctionWithParams(JSWeak<JSFunc>& func, const char* debugInfo, const std::string& jsonData)
557 {
558 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
559 if (func.IsEmpty()) {
560 LOGD("View doesn't have %{public}s() method!", debugInfo);
561 return;
562 }
563
564 JSRef<JSObject> obj = JSRef<JSObject>::New();
565 JSRef<JSVal> param = obj->ToJsonObject(jsonData.c_str());
566
567 JSRef<JSVal> jsObject = jsObject_.Lock();
568 JSRef<JSVal> result = func.Lock()->Call(jsObject, 1, ¶m);
569 if (result.IsEmpty()) {
570 LOGE("Error calling %{public}s", debugInfo);
571 }
572 }
573
574 // Baseline version of Destroy
Destroy(JSView * parentCustomView)575 void ViewFunctions::Destroy(JSView* parentCustomView)
576 {
577 LOGD("Destroy");
578 // Might be called from parent view, before any result has been produced??
579 if (jsRenderResult_.IsEmpty()) {
580 LOGD("ViewFunctions::Destroy() -> no previous render result to delete");
581 return;
582 }
583
584 auto renderRes = jsRenderResult_.Lock();
585 if (renderRes.IsEmpty() || !renderRes->IsObject()) {
586 LOGD("ViewFunctions::Destroy() -> result not an object");
587 return;
588 }
589
590 JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
591 if (!obj.IsEmpty()) {
592 // jsRenderResult_ maybe an js exception, not a JSView
593 JSView* view = obj->Unwrap<JSView>();
594 if (view != nullptr) {
595 view->Destroy(parentCustomView);
596 }
597 }
598 jsRenderResult_.Reset();
599 LOGD("ViewFunctions::Destroy() end");
600 }
601
602 // PartialUpdate version of Destroy
Destroy()603 void ViewFunctions::Destroy()
604 {
605 LOGD("Destroy");
606
607 // Might be called from parent view, before any result has been produced??
608 if (jsRenderResult_.IsEmpty()) {
609 LOGD("ViewFunctions::Destroy() -> no previous render result to delete");
610 return;
611 }
612
613 auto renderRes = jsRenderResult_.Lock();
614 if (renderRes.IsEmpty() || !renderRes->IsObject()) {
615 LOGD("ViewFunctions::Destroy() -> result not an object");
616 return;
617 }
618
619 // merging: when would a render function return a JSView ?
620 JSRef<JSObject> obj = JSRef<JSObject>::Cast(renderRes);
621 if (!obj.IsEmpty()) {
622 // jsRenderResult_ maybe an js exception, not a JSView
623 JSView* view = obj->Unwrap<JSView>();
624 if (view != nullptr) {
625 LOGE("NOTE NOTE NOTE render returned a JSView object that's dangling!");
626 }
627 }
628 jsObject_.Reset();
629 jsRenderResult_.Reset();
630
631 LOGD("ViewFunctions::Destroy() end");
632 }
633
634 // Partial update method
ExecuteRerender()635 void ViewFunctions::ExecuteRerender()
636 {
637 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(context_)
638 if (jsRerenderFunc_.IsEmpty()) {
639 LOGE("no rerender function in View!");
640 return;
641 }
642
643 auto func = jsRerenderFunc_.Lock();
644 JSRef<JSVal> jsThis = jsObject_.Lock();
645 if (!jsThis->IsUndefined()) {
646 jsRenderResult_ = func->Call(jsThis);
647 } else {
648 LOGE("jsView Object is undefined and will not execute rerender function");
649 }
650 }
651
652 // Partial update method
ViewFunctions(const JSRef<JSObject> & jsObject)653 ViewFunctions::ViewFunctions(const JSRef<JSObject>& jsObject)
654 {
655 InitViewFunctions(jsObject, JSRef<JSFunc>(), true);
656 }
657
658 } // namespace OHOS::Ace::Framework
659