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