1 /*
2 * Copyright (c) 2021-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.h"
17
18 #include "base/log/ace_checker.h"
19 #include "base/log/ace_performance_check.h"
20 #include "base/log/ace_trace.h"
21 #include "base/memory/ace_type.h"
22 #include "base/memory/referenced.h"
23 #include "base/utils/system_properties.h"
24 #include "base/utils/utils.h"
25 #include "bridge/common/utils/engine_helper.h"
26 #include "bridge/declarative_frontend/engine/js_converter.h"
27 #include "bridge/declarative_frontend/engine/js_execution_scope_defines.h"
28 #include "bridge/declarative_frontend/engine/js_types.h"
29 #include "bridge/declarative_frontend/jsview/js_navigation_stack.h"
30 #include "bridge/declarative_frontend/jsview/js_view_stack_processor.h"
31 #include "bridge/declarative_frontend/jsview/models/view_full_update_model_impl.h"
32 #include "bridge/declarative_frontend/jsview/models/view_partial_update_model_impl.h"
33 #include "bridge/declarative_frontend/ng/declarative_frontend_ng.h"
34 #include "core/common/container.h"
35 #include "core/common/container_scope.h"
36 #include "core/common/layout_inspector.h"
37 #include "core/components_ng/base/observer_handler.h"
38 #include "core/components_ng/base/ui_node.h"
39 #include "core/components_ng/base/view_full_update_model.h"
40 #include "core/components_ng/base/view_full_update_model_ng.h"
41 #include "core/components_ng/base/view_partial_update_model.h"
42 #include "core/components_ng/base/view_partial_update_model_ng.h"
43 #include "core/components_ng/base/view_stack_model.h"
44 #include "core/components_ng/base/view_stack_processor.h"
45 #include "core/components_ng/layout/layout_wrapper.h"
46 #include "core/components_ng/pattern/custom/custom_measure_layout_node.h"
47 #include "core/components_ng/pattern/recycle_view/recycle_dummy_node.h"
48 #include "core/pipeline/base/element_register.h"
49
50 namespace OHOS::Ace {
51
52 std::unique_ptr<ViewFullUpdateModel> ViewFullUpdateModel::instance_ = nullptr;
53 std::mutex ViewFullUpdateModel::mutex_;
54
GetInstance()55 ViewFullUpdateModel* ViewFullUpdateModel::GetInstance()
56 {
57 if (!instance_) {
58 std::lock_guard<std::mutex> lock(mutex_);
59 if (!instance_) {
60 #ifdef NG_BUILD
61 instance_.reset(new NG::ViewFullUpdateModelNG());
62 #else
63 if (Container::IsCurrentUseNewPipeline()) {
64 instance_.reset(new NG::ViewFullUpdateModelNG());
65 } else {
66 instance_.reset(new Framework::ViewFullUpdateModelImpl());
67 }
68 #endif
69 }
70 }
71 return instance_.get();
72 }
73
GetInstance()74 ViewPartialUpdateModel* ViewPartialUpdateModel::GetInstance()
75 {
76 #ifdef NG_BUILD
77 static NG::ViewPartialUpdateModelNG instance;
78 return &instance;
79 #else
80 if (Container::IsCurrentUseNewPipeline()) {
81 static NG::ViewPartialUpdateModelNG instance;
82 return &instance;
83 } else {
84 static Framework::ViewPartialUpdateModelImpl instance;
85 return &instance;
86 }
87 #endif
88 }
89 } // namespace OHOS::Ace
90
91 namespace OHOS::Ace::Framework {
92
JSBind(BindingTarget object)93 void JSView::JSBind(BindingTarget object)
94 {
95 JSViewPartialUpdate::JSBind(object);
96 JSViewFullUpdate::JSBind(object);
97 }
98
RenderJSExecution()99 void JSView::RenderJSExecution()
100 {
101 JAVASCRIPT_EXECUTION_SCOPE_STATIC;
102 if (!jsViewFunction_) {
103 return;
104 }
105 {
106 ACE_SCORING_EVENT("Component.AboutToRender");
107 jsViewFunction_->ExecuteAboutToRender();
108 }
109 if (!jsViewFunction_) {
110 return;
111 }
112 {
113 ACE_SCORING_EVENT("Component.Build");
114 ViewStackModel::GetInstance()->PushKey(viewId_);
115 jsViewFunction_->ExecuteRender();
116 ViewStackModel::GetInstance()->PopKey();
117 }
118 if (!jsViewFunction_) {
119 return;
120 }
121 {
122 ACE_SCORING_EVENT("Component.OnRenderDone");
123 jsViewFunction_->ExecuteOnRenderDone();
124 if (notifyRenderDone_) {
125 notifyRenderDone_();
126 }
127 }
128 }
129
SyncInstanceId()130 void JSView::SyncInstanceId()
131 {
132 if (primaryStackSize_ >= PRIMARY_ID_STACK_SIZE) {
133 restoreInstanceIdStack_.emplace_back(Container::CurrentId());
134 } else {
135 primaryIdStack_[primaryStackSize_++] = Container::CurrentId();
136 }
137 ContainerScope::UpdateCurrent(instanceId_);
138 }
139
RestoreInstanceId()140 void JSView::RestoreInstanceId()
141 {
142 if (primaryStackSize_ >= PRIMARY_ID_STACK_SIZE && !restoreInstanceIdStack_.empty()) {
143 // Checking primaryStackSize_ is necessary, because the pointer in restoreInstanceIdStack_ may be corrupted.
144 ContainerScope::UpdateCurrent(restoreInstanceIdStack_.back());
145 restoreInstanceIdStack_.pop_back();
146 return;
147 }
148 if (primaryStackSize_ == 0) {
149 ContainerScope::UpdateCurrent(-1);
150 return;
151 }
152 ContainerScope::UpdateCurrent(primaryIdStack_[--primaryStackSize_]);
153 }
154
GetInstanceId(const JSCallbackInfo & info)155 void JSView::GetInstanceId(const JSCallbackInfo& info)
156 {
157 info.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(instanceId_)));
158 }
159
JsSetCardId(int64_t cardId)160 void JSView::JsSetCardId(int64_t cardId)
161 {
162 cardId_ = cardId;
163 }
164
JsGetCardId(const JSCallbackInfo & info)165 void JSView::JsGetCardId(const JSCallbackInfo& info)
166 {
167 info.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(cardId_)));
168 }
169
170
JSViewFullUpdate(const std::string & viewId,JSRef<JSObject> jsObject,JSRef<JSFunc> jsRenderFunction)171 JSViewFullUpdate::JSViewFullUpdate(const std::string& viewId, JSRef<JSObject> jsObject, JSRef<JSFunc> jsRenderFunction)
172 {
173 viewId_ = viewId;
174 jsViewFunction_ = AceType::MakeRefPtr<ViewFunctions>(jsObject, jsRenderFunction);
175 jsViewObject_ = jsObject;
176 }
177
~JSViewFullUpdate()178 JSViewFullUpdate::~JSViewFullUpdate()
179 {
180 jsViewFunction_.Reset();
181 };
182
CreateViewNode(bool isTitleNode)183 RefPtr<AceType> JSViewFullUpdate::CreateViewNode(bool isTitleNode)
184 {
185 auto appearFunc = [weak = AceType::WeakClaim(this)] {
186 auto jsView = weak.Upgrade();
187 CHECK_NULL_VOID(jsView);
188 ContainerScope scope(jsView->GetInstanceId());
189 ACE_SCORING_EVENT("Component[" + jsView->viewId_ + "].Appear");
190 if (jsView->viewNode_.Invalid() && jsView->jsViewFunction_) {
191 jsView->jsViewFunction_->ExecuteAppear();
192 }
193 };
194
195 auto renderFunction = [weak = AceType::WeakClaim(this)]() -> RefPtr<AceType> {
196 auto jsView = weak.Upgrade();
197 CHECK_NULL_RETURN(jsView, nullptr);
198 ContainerScope scope(jsView->GetInstanceId());
199 return jsView->InternalRender();
200 };
201
202 auto pageTransitionFunction = [weak = AceType::WeakClaim(this)]() {
203 auto jsView = weak.Upgrade();
204 if (!jsView || !jsView->jsViewFunction_) {
205 return;
206 }
207 {
208 ContainerScope scope(jsView->GetInstanceId());
209 ACE_SCORING_EVENT("Component[" + jsView->viewId_ + "].Transition");
210 jsView->jsViewFunction_->ExecuteTransition();
211 }
212 };
213
214 auto updateViewNodeFunction = [weak = AceType::WeakClaim(this)](const RefPtr<AceType>& node) {
215 auto jsView = weak.Upgrade();
216 if (jsView) {
217 jsView->viewNode_ = node;
218 }
219 };
220
221 auto removeFunction = [weak = AceType::WeakClaim(this)]() -> void {
222 auto jsView = weak.Upgrade();
223 if (jsView && jsView->jsViewFunction_) {
224 ContainerScope scope(jsView->GetInstanceId());
225 jsView->jsViewFunction_->ExecuteDisappear();
226 }
227 };
228
229 NodeInfo info = { .viewId = viewId_,
230 .appearFunc = std::move(appearFunc),
231 .renderFunc = std::move(renderFunction),
232 .removeFunc = std::move(removeFunction),
233 .updateNodeFunc = std::move(updateViewNodeFunction),
234 .isStatic = IsStatic() };
235
236 if (jsViewFunction_ && jsViewFunction_->HasPageTransition()) {
237 info.pageTransitionFunc = std::move(pageTransitionFunction);
238 }
239
240 return ViewFullUpdateModel::GetInstance()->CreateNode(std::move(info));
241 }
242
InternalRender()243 RefPtr<AceType> JSViewFullUpdate::InternalRender()
244 {
245 JAVASCRIPT_EXECUTION_SCOPE_STATIC;
246 needsUpdate_ = false;
247 RenderJSExecution();
248 CleanUpAbandonedChild();
249 jsViewFunction_->Destroy();
250 return ViewStackModel::GetInstance()->Finish();
251 }
252
253 /**
254 * marks the JSView's composed component as needing update / rerender
255 */
MarkNeedUpdate()256 void JSViewFullUpdate::MarkNeedUpdate()
257 {
258 ACE_SCOPED_TRACE("JSView::MarkNeedUpdate");
259 needsUpdate_ = ViewFullUpdateModel::GetInstance()->MarkNeedUpdate(viewNode_);
260 }
261
Destroy(JSView * parentCustomView)262 void JSViewFullUpdate::Destroy(JSView* parentCustomView)
263 {
264 DestroyChild(parentCustomView);
265 {
266 ACE_SCORING_EVENT("Component[" + viewId_ + "].Disappear");
267 jsViewFunction_->ExecuteDisappear();
268 }
269 {
270 ACE_SCORING_EVENT("Component[" + viewId_ + "].AboutToBeDeleted");
271 jsViewFunction_->ExecuteAboutToBeDeleted();
272 }
273 jsViewObject_.Reset();
274 }
275
Create(const JSCallbackInfo & info)276 void JSViewFullUpdate::Create(const JSCallbackInfo& info)
277 {
278 ACE_DCHECK(!Container::IsCurrentUsePartialUpdate());
279
280 if (info[0]->IsObject()) {
281 JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
282 auto* view = object->Unwrap<JSViewFullUpdate>();
283 if (view == nullptr) {
284 return;
285 }
286 ViewStackModel::GetInstance()->Push(view->CreateViewNode(), true);
287 }
288 }
289
JSBind(BindingTarget object)290 void JSViewFullUpdate::JSBind(BindingTarget object)
291 {
292 JSClass<JSViewFullUpdate>::Declare("NativeViewFullUpdate");
293 JSClass<JSViewFullUpdate>::StaticMethod("create", &JSViewFullUpdate::Create);
294 JSClass<JSViewFullUpdate>::Method("markNeedUpdate", &JSViewFullUpdate::MarkNeedUpdate);
295 JSClass<JSViewFullUpdate>::Method("syncInstanceId", &JSViewFullUpdate::SyncInstanceId);
296 JSClass<JSViewFullUpdate>::Method("restoreInstanceId", &JSViewFullUpdate::RestoreInstanceId);
297 JSClass<JSViewFullUpdate>::CustomMethod("getInstanceId", &JSViewFullUpdate::GetInstanceId);
298 JSClass<JSViewFullUpdate>::Method("needsUpdate", &JSViewFullUpdate::NeedsUpdate);
299 JSClass<JSViewFullUpdate>::Method("markStatic", &JSViewFullUpdate::MarkStatic);
300 JSClass<JSViewFullUpdate>::Method("setCardId", &JSViewFullUpdate::JsSetCardId);
301 JSClass<JSViewFullUpdate>::CustomMethod("getCardId", &JSViewFullUpdate::JsGetCardId);
302 JSClass<JSViewFullUpdate>::CustomMethod("findChildById", &JSViewFullUpdate::FindChildById);
303 JSClass<JSViewFullUpdate>::CustomMethod("findChildByIdForPreview", &JSViewFullUpdate::FindChildByIdForPreview);
304 JSClass<JSViewFullUpdate>::InheritAndBind<JSViewAbstract>(object, ConstructorCallback, DestructorCallback);
305 }
306
FindChildById(const JSCallbackInfo & info)307 void JSViewFullUpdate::FindChildById(const JSCallbackInfo& info)
308 {
309 if (info[0]->IsNumber() || info[0]->IsString()) {
310 std::string viewId = info[0]->ToString();
311 info.SetReturnValue(GetChildById(viewId));
312 } else {
313 JSException::Throw("%s", "JSView FindChildById with invalid arguments.");
314 }
315 }
316
FindChildByIdForPreview(const JSCallbackInfo & info)317 void JSViewFullUpdate::FindChildByIdForPreview(const JSCallbackInfo& info)
318 {
319 if (!info[0]->IsNumber()) {
320 return;
321 }
322 std::string viewId = std::to_string(info[0]->ToNumber<int32_t>());
323 if (viewId_ == viewId) {
324 info.SetReturnValue(jsViewObject_);
325 return;
326 }
327 JSRef<JSObject> targetView = JSRef<JSObject>::New();
328 for (auto&& child : customViewChildren_) {
329 if (GetChildByViewId(viewId, child.second, targetView)) {
330 break;
331 }
332 }
333 auto view = targetView->Unwrap<JSViewFullUpdate>();
334 if (view) {
335 info.SetReturnValue(targetView);
336 }
337 return;
338 }
339
GetChildByViewId(const std::string & viewId,JSRef<JSObject> & childView,JSRef<JSObject> & targetView)340 bool JSViewFullUpdate::GetChildByViewId(
341 const std::string& viewId, JSRef<JSObject>& childView, JSRef<JSObject>& targetView)
342 {
343 auto* view = childView->Unwrap<JSViewFullUpdate>();
344 CHECK_NULL_RETURN(view, false);
345 if (view->viewId_ == viewId) {
346 targetView = childView;
347 return true;
348 }
349 for (auto&& child : view->customViewChildren_) {
350 if (GetChildByViewId(viewId, child.second, targetView)) {
351 return true;
352 }
353 }
354 return false;
355 }
356
ConstructorCallback(const JSCallbackInfo & info)357 void JSViewFullUpdate::ConstructorCallback(const JSCallbackInfo& info)
358 {
359 JSRef<JSObject> thisObj = info.This();
360 JSRef<JSVal> renderFunc = thisObj->GetProperty("render");
361 if (!renderFunc->IsFunction()) {
362 JSException::Throw("%s", "View derived classes must provide render(){...} function");
363 return;
364 }
365
366 int argc = info.Length();
367 if (argc > 1 && (info[0]->IsNumber() || info[0]->IsString())) {
368 std::string viewId = info[0]->ToString();
369 auto instance = AceType::MakeRefPtr<JSViewFullUpdate>(viewId, info.This(), JSRef<JSFunc>::Cast(renderFunc));
370 auto context = info.GetExecutionContext();
371 instance->SetContext(context);
372 instance->IncRefCount();
373 info.SetReturnValue(AceType::RawPtr(instance));
374 if (!info[1]->IsUndefined() && info[1]->IsObject()) {
375 JSRef<JSObject> parentObj = JSRef<JSObject>::Cast(info[1]);
376 auto* parentView = parentObj->Unwrap<JSViewFullUpdate>();
377 if (parentView != nullptr) {
378 auto id = parentView->AddChildById(viewId, info.This());
379 instance->id_ = id;
380 }
381 }
382 } else {
383 JSException::Throw("%s", "JSView creation with invalid arguments.");
384 }
385 }
386
DestructorCallback(JSViewFullUpdate * view)387 void JSViewFullUpdate::DestructorCallback(JSViewFullUpdate* view)
388 {
389 if (view == nullptr) {
390 return;
391 }
392 view->DecRefCount();
393 }
394
DestroyChild(JSView * parentCustomView)395 void JSViewFullUpdate::DestroyChild(JSView* parentCustomView)
396 {
397 for (auto&& child : customViewChildren_) {
398 auto* view = child.second->Unwrap<JSView>();
399 if (view != nullptr) {
400 view->Destroy(this);
401 }
402 child.second.Reset();
403 }
404 customViewChildren_.clear();
405 for (auto&& lazyChild : customViewChildrenWithLazy_) {
406 auto* view = lazyChild.second->Unwrap<JSView>();
407 if (view != nullptr) {
408 view->Destroy(this);
409 }
410 lazyChild.second.Reset();
411 }
412 customViewChildrenWithLazy_.clear();
413 }
414
CleanUpAbandonedChild()415 void JSViewFullUpdate::CleanUpAbandonedChild()
416 {
417 auto startIter = customViewChildren_.begin();
418 auto endIter = customViewChildren_.end();
419 std::vector<std::string> removedViewIds;
420 while (startIter != endIter) {
421 auto found = lastAccessedViewIds_.find(startIter->first);
422 if (found == lastAccessedViewIds_.end()) {
423 removedViewIds.emplace_back(startIter->first);
424 auto* view = startIter->second->Unwrap<JSView>();
425 if (view != nullptr) {
426 view->Destroy(this);
427 }
428 startIter->second.Reset();
429 }
430 ++startIter;
431 }
432
433 for (auto& viewId : removedViewIds) {
434 customViewChildren_.erase(viewId);
435 }
436
437 lastAccessedViewIds_.clear();
438 }
439
GetChildById(const std::string & viewId)440 JSRef<JSObject> JSViewFullUpdate::GetChildById(const std::string& viewId)
441 {
442 std::string id = ViewStackModel::GetInstance()->ProcessViewId(viewId);
443 auto found = customViewChildren_.find(id);
444 if (found != customViewChildren_.end()) {
445 ChildAccessedById(id);
446 return found->second;
447 }
448 auto lazyItem = customViewChildrenWithLazy_.find(id);
449 if (lazyItem != customViewChildrenWithLazy_.end()) {
450 return lazyItem->second;
451 }
452 return {};
453 }
454
AddChildById(const std::string & viewId,const JSRef<JSObject> & obj)455 std::string JSViewFullUpdate::AddChildById(const std::string& viewId, const JSRef<JSObject>& obj)
456 {
457 std::string id = ViewStackModel::GetInstance()->ProcessViewId(viewId);
458 JSView* jsView = nullptr;
459 if (isLazyForEachProcessed_) {
460 auto result = customViewChildrenWithLazy_.try_emplace(id, obj);
461 if (!result.second) {
462 jsView = result.first->second->Unwrap<JSView>();
463 result.first->second = obj;
464 } else {
465 lazyItemGroups_[lazyItemGroupId_].emplace_back(id);
466 }
467 } else {
468 auto result = customViewChildren_.try_emplace(id, obj);
469 if (!result.second) {
470 jsView = result.first->second->Unwrap<JSView>();
471 result.first->second = obj;
472 }
473 ChildAccessedById(id);
474 }
475 if (jsView != nullptr) {
476 jsView->Destroy(this);
477 }
478 return id;
479 }
480
RemoveChildGroupById(const std::string & viewId)481 void JSViewFullUpdate::RemoveChildGroupById(const std::string& viewId)
482 {
483 // js runtime may be released
484 CHECK_JAVASCRIPT_SCOPE_AND_RETURN;
485 JAVASCRIPT_EXECUTION_SCOPE_STATIC;
486 auto iter = lazyItemGroups_.find(viewId);
487 if (iter == lazyItemGroups_.end()) {
488 return;
489 }
490 std::vector<std::string> removedViewIds;
491 for (auto&& item : iter->second) {
492 auto removeView = customViewChildrenWithLazy_.find(item);
493 if (removeView != customViewChildrenWithLazy_.end()) {
494 if (!removeView->second.IsEmpty()) {
495 auto* view = removeView->second->Unwrap<JSView>();
496 if (view != nullptr) {
497 view->Destroy(this);
498 }
499 removeView->second.Reset();
500 }
501 removedViewIds.emplace_back(item);
502 }
503 }
504
505 for (auto&& removeId : removedViewIds) {
506 customViewChildrenWithLazy_.erase(removeId);
507 }
508 lazyItemGroups_.erase(iter);
509 }
510
ChildAccessedById(const std::string & viewId)511 void JSViewFullUpdate::ChildAccessedById(const std::string& viewId)
512 {
513 lastAccessedViewIds_.emplace(viewId);
514 }
515
516 // =================================================================
517
518 std::map<std::string, JSRef<JSObject>> JSViewStackProcessor::viewMap_;
519
JSViewPartialUpdate(JSRef<JSObject> jsViewObject)520 JSViewPartialUpdate::JSViewPartialUpdate(JSRef<JSObject> jsViewObject)
521 {
522 jsViewFunction_ = AceType::MakeRefPtr<ViewFunctions>(jsViewObject);
523 // keep the reference to the JS View object to prevent GC
524 jsViewObject_ = jsViewObject;
525 }
526
~JSViewPartialUpdate()527 JSViewPartialUpdate::~JSViewPartialUpdate()
528 {
529 jsViewFunction_.Reset();
530 };
531
CreateViewNode(bool isTitleNode)532 RefPtr<AceType> JSViewPartialUpdate::CreateViewNode(bool isTitleNode)
533 {
534 auto updateViewIdFunc = [weak = AceType::WeakClaim(this)](const std::string& viewId) {
535 auto jsView = weak.Upgrade();
536 CHECK_NULL_VOID(jsView);
537 jsView->viewId_ = viewId;
538 };
539
540 auto appearFunc = [weak = AceType::WeakClaim(this)]() {
541 auto jsView = weak.Upgrade();
542 CHECK_NULL_VOID(jsView);
543 ContainerScope scope(jsView->GetInstanceId());
544 ACE_SCORING_EVENT("Component[" + jsView->viewId_ + "].Appear");
545 if (jsView->jsViewFunction_) {
546 jsView->jsViewFunction_->ExecuteAppear();
547 }
548 };
549
550 auto didBuildFunc = [weak = AceType::WeakClaim(this)]() {
551 auto jsView = weak.Upgrade();
552 CHECK_NULL_VOID(jsView);
553 ContainerScope scope(jsView->GetInstanceId());
554 if (jsView->jsViewFunction_) {
555 jsView->jsViewFunction_->ExecuteDidBuild();
556 }
557 };
558
559 auto renderFunction = [weak = AceType::WeakClaim(this)]() -> RefPtr<AceType> {
560 auto jsView = weak.Upgrade();
561 CHECK_NULL_RETURN(jsView, nullptr);
562 ContainerScope scope(jsView->GetInstanceId());
563 if (!jsView->isFirstRender_) {
564 return nullptr;
565 }
566 jsView->isFirstRender_ = false;
567 return jsView->InitialRender();
568 };
569
570 auto updateFunction = [weak = AceType::WeakClaim(this)]() -> void {
571 auto jsView = weak.Upgrade();
572 CHECK_NULL_VOID(jsView);
573 ContainerScope scope(jsView->GetInstanceId());
574 if (!jsView->needsUpdate_) {
575 return;
576 }
577 jsView->needsUpdate_ = false;
578 {
579 ACE_SCOPED_TRACE("JSView: ExecuteRerender");
580 jsView->jsViewFunction_->ExecuteRerender();
581 }
582 for (const UpdateTask& updateTask : jsView->pendingUpdateTasks_) {
583 ViewPartialUpdateModel::GetInstance()->FlushUpdateTask(updateTask);
584 }
585 jsView->pendingUpdateTasks_.clear();
586 };
587
588 auto reloadFunction = [weak = AceType::WeakClaim(this)](bool deep) {
589 auto jsView = weak.Upgrade();
590 CHECK_NULL_VOID(jsView);
591 CHECK_NULL_VOID(jsView->jsViewFunction_);
592 ContainerScope scope(jsView->GetInstanceId());
593 jsView->jsViewFunction_->ExecuteReload(deep);
594 };
595
596 // @Component level complete reload, can detect added/deleted frame nodes
597 auto completeReloadFunc = [weak = AceType::WeakClaim(this)]() -> RefPtr<AceType> {
598 auto jsView = weak.Upgrade();
599 CHECK_NULL_RETURN(jsView, nullptr);
600 ContainerScope scope(jsView->GetInstanceId());
601 return jsView->InitialRender();
602 };
603
604 auto pageTransitionFunction = [weak = AceType::WeakClaim(this)]() {
605 auto jsView = weak.Upgrade();
606 CHECK_NULL_VOID(jsView);
607 CHECK_NULL_VOID(jsView->jsViewFunction_);
608 ContainerScope scope(jsView->GetInstanceId());
609 {
610 ACE_SCORING_EVENT("Component[" + jsView->viewId_ + "].Transition");
611 jsView->jsViewFunction_->ExecuteTransition();
612 }
613 };
614
615 auto removeFunction = [weak = AceType::WeakClaim(this)]() -> void {
616 auto jsView = weak.Upgrade();
617 CHECK_NULL_VOID(jsView);
618 ContainerScope scope(jsView->GetInstanceId());
619 jsView->Destroy(nullptr);
620 jsView->viewNode_.Reset();
621 };
622
623 auto updateViewNodeFunction = [weak = AceType::WeakClaim(this)](const RefPtr<AceType>& node) {
624 auto jsView = weak.Upgrade();
625 CHECK_NULL_VOID(jsView);
626 jsView->viewNode_ = node;
627 };
628
629 auto nodeUpdateFunc = [weak = AceType::WeakClaim(this)](int32_t nodeId) {
630 auto jsView = weak.Upgrade();
631 CHECK_NULL_VOID(jsView);
632 CHECK_NULL_VOID(jsView->jsViewFunction_);
633 ContainerScope scope(jsView->GetInstanceId());
634 jsView->jsViewFunction_->ExecuteForceNodeRerender(nodeId);
635 };
636
637 auto hasNodeUpdateFunc = [weak = AceType::WeakClaim(this)](int32_t nodeId) -> bool {
638 auto jsView = weak.Upgrade();
639 CHECK_NULL_RETURN(jsView, false);
640 CHECK_NULL_RETURN(jsView->jsViewFunction_, false);
641 ContainerScope scope(jsView->GetInstanceId());
642 return jsView->jsViewFunction_->ExecuteHasNodeUpdateFunc(nodeId);
643 };
644
645 auto recycleCustomNode = [weak = AceType::WeakClaim(this)](const RefPtr<NG::CustomNodeBase>& recycleNode) -> void {
646 auto jsView = weak.Upgrade();
647 CHECK_NULL_VOID(jsView);
648 CHECK_NULL_VOID(jsView->jsViewFunction_);
649 ContainerScope scope(jsView->GetInstanceId());
650 auto name = jsView->GetRecycleCustomNodeName();
651 if (name.empty()) {
652 return;
653 }
654 auto recycleUINode = AceType::DynamicCast<NG::UINode>(recycleNode);
655 recycleUINode->SetActive(false);
656 jsView->SetRecycleCustomNode(recycleNode);
657 jsView->jsViewFunction_->ExecuteRecycle(jsView->GetRecycleCustomNodeName());
658 if (!recycleNode->HasRecycleRenderFunc() && jsView->recycleCustomNode_) {
659 recycleUINode->SetJSViewActive(false);
660 jsView->jsViewFunction_->ExecuteAboutToRecycle();
661 }
662 recycleNode->ResetRecycle();
663 };
664
665 auto setActiveFunc = [weak = AceType::WeakClaim(this)](bool active) -> void {
666 auto jsView = weak.Upgrade();
667 CHECK_NULL_VOID(jsView);
668 ContainerScope scope(jsView->GetInstanceId());
669 jsView->jsViewFunction_->ExecuteSetActive(active);
670 };
671
672 auto onDumpInfoFunc = [weak = AceType::WeakClaim(this)](const std::vector<std::string>& params) -> void {
673 auto jsView = weak.Upgrade();
674 CHECK_NULL_VOID(jsView);
675 ContainerScope scope(jsView->GetInstanceId());
676 jsView->jsViewFunction_->ExecuteOnDumpInfo(params);
677 };
678
679 auto onDumpInspectorFunc = [weak = AceType::WeakClaim(this)]() -> std::string {
680 auto jsView = weak.Upgrade();
681 CHECK_NULL_RETURN(jsView, "");
682 ContainerScope scope(jsView->GetInstanceId());
683 return jsView->jsViewFunction_->ExecuteOnDumpInfo();
684 };
685
686 auto getThisFunc = [weak = AceType::WeakClaim(this)]() -> void* {
687 auto jsView = weak.Upgrade();
688 CHECK_NULL_RETURN(jsView, nullptr);
689 ContainerScope scope(jsView->GetInstanceId());
690 return (void*)&(jsView->jsViewObject_);
691 };
692
693 NodeInfoPU info = { .appearFunc = std::move(appearFunc),
694 .didBuildFunc = std::move(didBuildFunc),
695 .renderFunc = std::move(renderFunction),
696 .updateFunc = std::move(updateFunction),
697 .removeFunc = std::move(removeFunction),
698 .updateNodeFunc = std::move(updateViewNodeFunction),
699 .pageTransitionFunc = std::move(pageTransitionFunction),
700 .reloadFunc = std::move(reloadFunction),
701 .completeReloadFunc = std::move(completeReloadFunc),
702 .nodeUpdateFunc = std::move(nodeUpdateFunc),
703 .hasNodeUpdateFunc = std::move(hasNodeUpdateFunc),
704 .recycleCustomNodeFunc = recycleCustomNode,
705 .setActiveFunc = std::move(setActiveFunc),
706 .onDumpInfoFunc = std::move(onDumpInfoFunc),
707 .onDumpInspectorFunc = std::move(onDumpInspectorFunc),
708 .getThisFunc = std::move(getThisFunc),
709 .hasMeasureOrLayout = jsViewFunction_->HasMeasure() || jsViewFunction_->HasLayout() ||
710 jsViewFunction_->HasMeasureSize() || jsViewFunction_->HasPlaceChildren(),
711 .isStatic = IsStatic(),
712 .jsViewName = GetJSViewName(),
713 .isV2 = GetJSIsV2() };
714
715 auto measureFunc = [weak = AceType::WeakClaim(this)](NG::LayoutWrapper* layoutWrapper) -> void {
716 auto jsView = weak.Upgrade();
717 CHECK_NULL_VOID(jsView);
718 ContainerScope scope(jsView->GetInstanceId());
719 jsView->jsViewFunction_->ExecuteMeasure(layoutWrapper);
720 };
721 if (jsViewFunction_->HasMeasure()) {
722 info.measureFunc = std::move(measureFunc);
723 }
724
725 auto layoutFunc = [weak = AceType::WeakClaim(this)](NG::LayoutWrapper* layoutWrapper) -> void {
726 auto jsView = weak.Upgrade();
727 CHECK_NULL_VOID(jsView);
728 ContainerScope scope(jsView->GetInstanceId());
729 jsView->jsViewFunction_->ExecuteLayout(layoutWrapper);
730 };
731 if (jsViewFunction_->HasLayout()) {
732 info.layoutFunc = std::move(layoutFunc);
733 }
734
735 if (jsViewFunction_->HasMeasureSize()) {
736 auto measureSizeFunc = [weak = AceType::WeakClaim(this)](NG::LayoutWrapper* layoutWrapper) -> void {
737 auto jsView = weak.Upgrade();
738 CHECK_NULL_VOID(jsView);
739 ContainerScope scope(jsView->GetInstanceId());
740 jsView->jsViewFunction_->ExecuteMeasureSize(layoutWrapper);
741 };
742 info.measureSizeFunc = std::move(measureSizeFunc);
743 }
744
745 if (jsViewFunction_->HasPlaceChildren()) {
746 auto placeChildren = [weak = AceType::WeakClaim(this)](NG::LayoutWrapper* layoutWrapper) -> void {
747 auto jsView = weak.Upgrade();
748 CHECK_NULL_VOID(jsView);
749 ContainerScope scope(jsView->GetInstanceId());
750 jsView->jsViewFunction_->ExecutePlaceChildren(layoutWrapper);
751 };
752 info.placeChildrenFunc = std::move(placeChildren);
753 }
754
755 if (isTitleNode) {
756 info.isCustomTitle = true;
757 }
758
759 JSRef<JSObject> jsViewExtraInfo = jsViewObject_->GetProperty("extraInfo_");
760 if (!jsViewExtraInfo->IsUndefined()) {
761 JSRef<JSVal> jsPage = jsViewExtraInfo->GetProperty("page");
762 JSRef<JSVal> jsLine = jsViewExtraInfo->GetProperty("line");
763 JSRef<JSVal> jsColumn = jsViewExtraInfo->GetProperty("col");
764 info.extraInfo = {.page = jsPage->ToString(), .line = jsLine->ToNumber<int32_t>(),
765 .col = jsColumn->ToNumber<int32_t>()};
766 }
767
768 auto node = ViewPartialUpdateModel::GetInstance()->CreateNode(std::move(info));
769 auto customMeasureLayoutNode = DynamicCast<NG::CustomMeasureLayoutNode>(node);
770 if (customMeasureLayoutNode) {
771 auto updateParamFunc = [weak = AceType::WeakClaim(this)](NG::LayoutWrapper* layoutWrapper) -> void {
772 auto jsView = weak.Upgrade();
773 CHECK_NULL_VOID(jsView);
774 ContainerScope scope(jsView->GetInstanceId());
775 jsView->jsViewFunction_->InitJsParam(layoutWrapper);
776 };
777 customMeasureLayoutNode->SetUpdateParamFunc(updateParamFunc);
778 }
779 #ifdef PREVIEW
780 auto uiNode = AceType::DynamicCast<NG::UINode>(node);
781 if (uiNode) {
782 Framework::JSViewStackProcessor::SetViewMap(std::to_string(uiNode->GetId()), jsViewObject_);
783 }
784 #endif
785
786 if (AceChecker::IsPerformanceCheckEnabled()) {
787 auto uiNode = AceType::DynamicCast<NG::UINode>(node);
788 if (uiNode) {
789 auto codeInfo = EngineHelper::GetPositionOnJsCode();
790 uiNode->SetRow(codeInfo.first);
791 uiNode->SetCol(codeInfo.second);
792 }
793 }
794 return node;
795 }
796
InitialRender()797 RefPtr<AceType> JSViewPartialUpdate::InitialRender()
798 {
799 needsUpdate_ = false;
800 RenderJSExecution();
801 return ViewStackModel::GetInstance()->Finish();
802 }
803
804 // parentCustomView in not used by PartialUpdate
Destroy(JSView * parentCustomView)805 void JSViewPartialUpdate::Destroy(JSView* parentCustomView)
806 {
807 if (jsViewFunction_ == nullptr) {
808 // already called Destroy before
809 return;
810 }
811 {
812 ACE_SCORING_EVENT("Component[" + viewId_ + "].Disappear");
813 jsViewFunction_->ExecuteDisappear();
814 }
815 {
816 ACE_SCORING_EVENT("Component[" + viewId_ + "].AboutToBeDeleted");
817 jsViewFunction_->ExecuteAboutToBeDeleted();
818 }
819 pendingUpdateTasks_.clear();
820 jsViewFunction_->Destroy();
821 jsViewFunction_.Reset();
822
823 // release reference to JS view object, and allow GC, calls DestructorCallback
824 jsViewObject_.Reset();
825 }
826
MarkNeedUpdate()827 void JSViewPartialUpdate::MarkNeedUpdate()
828 {
829 needsUpdate_ = ViewPartialUpdateModel::GetInstance()->MarkNeedUpdate(viewNode_);
830 }
831
832 /**
833 * in JS View.create(new View(...));
834 * used for FullRender case, not for re-render case
835 */
Create(const JSCallbackInfo & info)836 void JSViewPartialUpdate::Create(const JSCallbackInfo& info)
837 {
838 ACE_DCHECK(Container::IsCurrentUsePartialUpdate());
839
840 if (info[0]->IsObject()) {
841 JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
842 auto* view = object->Unwrap<JSView>();
843 if (view == nullptr) {
844 LOGE("View is null");
845 return;
846 }
847 ViewStackModel::GetInstance()->Push(view->CreateViewNode(), true);
848 }
849 }
850
851 enum {
852 PARAM_VIEW_OBJ = 0,
853 PARAM_IS_RECYCLE,
854 PARAM_NODE_NAME,
855 PARAM_RECYCLE_UPDATE_FUNC,
856
857 PARAM_SIZE,
858 };
859
ParseRecycleParams(const JSCallbackInfo & info,JSRef<JSVal> (& params)[PARAM_SIZE])860 bool ParseRecycleParams(const JSCallbackInfo& info, JSRef<JSVal> (¶ms)[PARAM_SIZE])
861 {
862 if (info.Length() != PARAM_SIZE) {
863 return false;
864 }
865 if (!info[PARAM_VIEW_OBJ]->IsObject()) {
866 return false;
867 }
868 if (!info[PARAM_IS_RECYCLE]->IsBoolean()) {
869 return false;
870 }
871 if (!info[PARAM_RECYCLE_UPDATE_FUNC]->IsFunction()) {
872 return false;
873 }
874
875 for (int32_t idx = PARAM_VIEW_OBJ; idx < PARAM_SIZE; ++idx) {
876 params[idx] = info[idx];
877 }
878 return true;
879 }
880
881 /**
882 * in JS ViewPU.createRecycle(...)
883 * create a recyclable custom node
884 */
CreateRecycle(const JSCallbackInfo & info)885 void JSViewPartialUpdate::CreateRecycle(const JSCallbackInfo& info)
886 {
887 ACE_DCHECK(Container::IsCurrentUsePartialUpdate());
888
889 JSRef<JSVal> params[PARAM_SIZE];
890 if (!ParseRecycleParams(info, params)) {
891 return;
892 }
893
894 auto viewObj = JSRef<JSObject>::Cast(params[PARAM_VIEW_OBJ]);
895 auto* view = viewObj->Unwrap<JSViewPartialUpdate>();
896 if (!view) {
897 return;
898 }
899 if (info[PARAM_NODE_NAME]->IsUndefined()) {
900 view->SetRecycleCustomNodeName("");
901 ViewStackModel::GetInstance()->Push(view->CreateViewNode(), true);
902 return;
903 }
904 auto recycle = params[PARAM_IS_RECYCLE]->ToBoolean();
905 auto nodeName = params[PARAM_NODE_NAME]->ToString();
906 auto jsRecycleUpdateFunc =
907 AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(params[PARAM_RECYCLE_UPDATE_FUNC]));
908 auto recycleUpdateFunc = [weak = AceType::WeakClaim(view), execCtx = info.GetExecutionContext(),
909 func = std::move(jsRecycleUpdateFunc)]() -> void {
910 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
911 auto jsView = weak.Upgrade();
912 CHECK_NULL_VOID(jsView);
913 jsView->SetIsRecycleRerender(true);
914 func->ExecuteJS();
915 jsView->SetIsRecycleRerender(false);
916 };
917
918 // update view and node property
919 view->SetRecycleCustomNodeName(nodeName);
920
921 RefPtr<AceType> node;
922
923 // get or create recycle node
924 if (recycle) {
925 node = view->GetCachedRecycleNode();
926 AceType::DynamicCast<NG::CustomNodeBase>(node)->SetRecycleRenderFunc(std::move(recycleUpdateFunc));
927 } else {
928 node = view->CreateViewNode();
929 }
930 auto* stack = NG::ViewStackProcessor::GetInstance();
931 auto dummyNode = NG::RecycleDummyNode::WrapRecycleDummyNode(node, stack->GetRecycleNodeId());
932 ViewStackModel::GetInstance()->Push(dummyNode, true);
933 }
934
OnDumpInfo(const std::vector<std::string> & params)935 void JSViewPartialUpdate::OnDumpInfo(const std::vector<std::string>& params)
936 {
937 CHECK_NULL_VOID(jsViewFunction_);
938 jsViewFunction_->ExecuteOnDumpInfo(params);
939 }
940
JSGetNavDestinationInfo(const JSCallbackInfo & info)941 void JSViewPartialUpdate::JSGetNavDestinationInfo(const JSCallbackInfo& info)
942 {
943 auto result = NG::UIObserverHandler::GetInstance().GetNavigationState(GetViewNode());
944 if (result) {
945 JSRef<JSObject> obj = JSRef<JSObject>::New();
946 obj->SetProperty<std::string>("navigationId", result->navigationId);
947 obj->SetProperty<std::string>("name", result->name);
948 obj->SetProperty<int32_t>("state", static_cast<int32_t>(result->state));
949 obj->SetProperty<int32_t>("index", result->index);
950 obj->SetPropertyObject("param", JsConverter::ConvertNapiValueToJsVal(result->param));
951 obj->SetProperty<std::string>("navDestinationId", result->navDestinationId);
952 info.SetReturnValue(obj);
953 }
954 }
955
JSGetRouterPageInfo(const JSCallbackInfo & info)956 void JSViewPartialUpdate::JSGetRouterPageInfo(const JSCallbackInfo& info)
957 {
958 auto result = NG::UIObserverHandler::GetInstance().GetRouterPageState(GetViewNode());
959 if (result) {
960 JSRef<JSObject> obj = JSRef<JSObject>::New();
961 auto jsContext = JsConverter::ConvertNapiValueToJsVal(result->context);
962 obj->SetPropertyObject("context", jsContext);
963 obj->SetProperty<int32_t>("index", result->index);
964 obj->SetProperty<std::string>("name", result->name);
965 obj->SetProperty<std::string>("path", result->path);
966 obj->SetProperty<int32_t>("state", static_cast<int32_t>(result->state));
967 obj->SetProperty<std::string>("pageId", result->pageId);
968 info.SetReturnValue(obj);
969 }
970 }
971
JSGetNavigationInfo(const JSCallbackInfo & info)972 void JSViewPartialUpdate::JSGetNavigationInfo(const JSCallbackInfo& info)
973 {
974 ContainerScope scope(GetInstanceId());
975 auto node = AceType::DynamicCast<NG::UINode>(this->GetViewNode());
976 CHECK_NULL_VOID(node);
977 auto pipeline = node->GetContext();
978 CHECK_NULL_VOID(pipeline);
979 auto navigationMgr = pipeline->GetNavigationManager();
980 CHECK_NULL_VOID(navigationMgr);
981 auto result = navigationMgr->GetNavigationInfo(GetViewNode());
982 CHECK_NULL_VOID(result);
983 auto stack = result->pathStack.Upgrade();
984 CHECK_NULL_VOID(stack);
985 auto jsStack = AceType::DynamicCast<JSNavigationStack>(stack);
986 CHECK_NULL_VOID(jsStack);
987 auto navPathStackObj = jsStack->GetDataSourceObj();
988 CHECK_NULL_VOID(!navPathStackObj->IsEmpty());
989 JSRef<JSObject> obj = JSRef<JSObject>::New();
990 obj->SetProperty<std::string>("navigationId", result->navigationId);
991 obj->SetPropertyObject("pathStack", navPathStackObj);
992 info.SetReturnValue(obj);
993 }
994
JSGetUIContext(const JSCallbackInfo & info)995 void JSViewPartialUpdate::JSGetUIContext(const JSCallbackInfo& info)
996 {
997 ContainerScope scope(GetInstanceId());
998 auto container = Container::Current();
999 CHECK_NULL_VOID(container);
1000 auto frontend = container->GetFrontend();
1001 CHECK_NULL_VOID(frontend);
1002 auto context = frontend->GetContextValue();
1003 auto jsVal = JsConverter::ConvertNapiValueToJsVal(context);
1004 info.SetReturnValue(jsVal);
1005 }
1006
JSGetUniqueId(const JSCallbackInfo & info)1007 void JSViewPartialUpdate::JSGetUniqueId(const JSCallbackInfo& info)
1008 {
1009 auto node = AceType::DynamicCast<NG::UINode>(this->GetViewNode());
1010 auto nodeId = -1;
1011 if (node) {
1012 nodeId = node->GetId();
1013 }
1014
1015 info.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(nodeId)));
1016 }
1017
JSSendStateInfo(const std::string & stateInfo)1018 void JSViewPartialUpdate::JSSendStateInfo(const std::string& stateInfo)
1019 {
1020 #if defined(PREVIEW) || !defined(OHOS_PLATFORM)
1021 return;
1022 #else
1023 ContainerScope scope(GetInstanceId());
1024 auto node = AceType::DynamicCast<NG::UINode>(this->GetViewNode());
1025 CHECK_NULL_VOID(node);
1026 auto pipeline = node->GetContext();
1027 CHECK_NULL_VOID(pipeline);
1028 if (!LayoutInspector::GetStateProfilerStatus()) {
1029 return;
1030 }
1031 TAG_LOGD(AceLogTag::ACE_STATE_MGMT, "ArkUI SendStateInfo %{public}s", stateInfo.c_str());
1032 auto info = JsonUtil::ParseJsonString(stateInfo);
1033 info->Put("timeStamp", GetCurrentTimestampMicroSecond());
1034 info->Put("vsyncID", (int32_t)pipeline->GetFrameCount());
1035 info->Put("processID", getpid());
1036 info->Put("windowID", (int32_t)pipeline->GetWindowId());
1037 LayoutInspector::SendStateProfilerMessage(info->ToString());
1038 #endif
1039 }
1040
JSSetIsV2(const bool isV2)1041 void JSViewPartialUpdate::JSSetIsV2(const bool isV2)
1042 {
1043 isV2_ = isV2;
1044 }
1045
JSBind(BindingTarget object)1046 void JSViewPartialUpdate::JSBind(BindingTarget object)
1047 {
1048 JSClass<JSViewPartialUpdate>::Declare("NativeViewPartialUpdate");
1049 MethodOptions opt = MethodOptions::NONE;
1050
1051 JSClass<JSViewPartialUpdate>::StaticMethod("create", &JSViewPartialUpdate::Create, opt);
1052 JSClass<JSViewPartialUpdate>::StaticMethod("createRecycle", &JSViewPartialUpdate::CreateRecycle, opt);
1053 JSClass<JSViewPartialUpdate>::Method("markNeedUpdate", &JSViewPartialUpdate::MarkNeedUpdate);
1054 JSClass<JSViewPartialUpdate>::Method("syncInstanceId", &JSViewPartialUpdate::SyncInstanceId);
1055 JSClass<JSViewPartialUpdate>::Method("restoreInstanceId", &JSViewPartialUpdate::RestoreInstanceId);
1056 JSClass<JSViewPartialUpdate>::CustomMethod("getInstanceId", &JSViewPartialUpdate::GetInstanceId);
1057 JSClass<JSViewPartialUpdate>::Method("markStatic", &JSViewPartialUpdate::MarkStatic);
1058 JSClass<JSViewPartialUpdate>::Method("finishUpdateFunc", &JSViewPartialUpdate::JsFinishUpdateFunc);
1059 JSClass<JSViewPartialUpdate>::Method("setCardId", &JSViewPartialUpdate::JsSetCardId);
1060 JSClass<JSViewPartialUpdate>::CustomMethod("getCardId", &JSViewPartialUpdate::JsGetCardId);
1061 JSClass<JSViewPartialUpdate>::Method("elmtIdExists", &JSViewPartialUpdate::JsElementIdExists);
1062 JSClass<JSViewPartialUpdate>::CustomMethod("isLazyItemRender", &JSViewPartialUpdate::JSGetProxiedItemRenderState);
1063 JSClass<JSViewPartialUpdate>::CustomMethod("isFirstRender", &JSViewPartialUpdate::IsFirstRender);
1064 JSClass<JSViewPartialUpdate>::CustomMethod(
1065 "findChildByIdForPreview", &JSViewPartialUpdate::FindChildByIdForPreview);
1066 JSClass<JSViewPartialUpdate>::CustomMethod(
1067 "resetRecycleCustomNode", &JSViewPartialUpdate::JSResetRecycleCustomNode);
1068 JSClass<JSViewPartialUpdate>::CustomMethod(
1069 "queryNavDestinationInfo", &JSViewPartialUpdate::JSGetNavDestinationInfo);
1070 JSClass<JSViewPartialUpdate>::CustomMethod(
1071 "queryNavigationInfo", &JSViewPartialUpdate::JSGetNavigationInfo);
1072 JSClass<JSViewPartialUpdate>::CustomMethod(
1073 "queryRouterPageInfo", &JSViewPartialUpdate::JSGetRouterPageInfo);
1074 JSClass<JSViewPartialUpdate>::CustomMethod("getUIContext", &JSViewPartialUpdate::JSGetUIContext);
1075 JSClass<JSViewPartialUpdate>::Method("sendStateInfo", &JSViewPartialUpdate::JSSendStateInfo);
1076 JSClass<JSViewPartialUpdate>::CustomMethod("getUniqueId", &JSViewPartialUpdate::JSGetUniqueId);
1077 JSClass<JSViewPartialUpdate>::Method("setIsV2", &JSViewPartialUpdate::JSSetIsV2);
1078 JSClass<JSViewPartialUpdate>::InheritAndBind<JSViewAbstract>(object, ConstructorCallback, DestructorCallback);
1079 }
1080
ConstructorCallback(const JSCallbackInfo & info)1081 void JSViewPartialUpdate::ConstructorCallback(const JSCallbackInfo& info)
1082 {
1083 JSRef<JSObject> thisObj = info.This();
1084
1085 // Get js view name by this.constructor.name
1086 JSRef<JSObject> constructor = thisObj->GetProperty("constructor");
1087 JSRef<JSVal> jsViewName = constructor->GetProperty("name");
1088 auto viewName = jsViewName->ToString();
1089 auto* instance = new JSViewPartialUpdate(thisObj);
1090
1091 auto context = info.GetExecutionContext();
1092 instance->SetContext(context);
1093 instance->SetJSViewName(viewName);
1094
1095 // The JS object owns the C++ object:
1096 // make sure the C++ is not destroyed when RefPtr thisObj goes out of scope
1097 // JSView::DestructorCallback has view->DecRefCount()
1098 instance->IncRefCount();
1099
1100 info.SetReturnValue(instance);
1101 }
1102
DestructorCallback(JSViewPartialUpdate * view)1103 void JSViewPartialUpdate::DestructorCallback(JSViewPartialUpdate* view)
1104 {
1105 if (view == nullptr) {
1106 return;
1107 }
1108 view->DecRefCount();
1109 }
1110
1111 // ===========================================================
1112 // partial update own functions start below
1113 // ===========================================================
1114
JsFinishUpdateFunc(int32_t elmtId)1115 void JSViewPartialUpdate::JsFinishUpdateFunc(int32_t elmtId)
1116 {
1117 ViewPartialUpdateModel::GetInstance()->FinishUpdate(
1118 viewNode_, elmtId, [weak = AceType::WeakClaim(this)](const UpdateTask& task) {
1119 auto jsView = weak.Upgrade();
1120 if (jsView) {
1121 jsView->pendingUpdateTasks_.push_back(task);
1122 }
1123 });
1124 }
1125
JsElementIdExists(int32_t elmtId)1126 bool JSViewPartialUpdate::JsElementIdExists(int32_t elmtId)
1127 {
1128 return ElementRegister::GetInstance()->Exists(elmtId);
1129 }
1130
JSGetProxiedItemRenderState(const JSCallbackInfo & info)1131 void JSViewPartialUpdate::JSGetProxiedItemRenderState(const JSCallbackInfo& info)
1132 {
1133 if (info.Length() != 1 || !info[0]->IsNumber()) {
1134 info.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(false)));
1135 return;
1136 }
1137 const auto elmtId = info[0]->ToNumber<int32_t>();
1138
1139 if (elmtId == ElementRegister::UndefinedElementId) {
1140 info.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(false)));
1141 return;
1142 }
1143 auto result = false;
1144
1145 // set boolean return value to JS
1146 info.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(result)));
1147 }
1148
IsFirstRender(const JSCallbackInfo & info)1149 void JSViewPartialUpdate::IsFirstRender(const JSCallbackInfo& info)
1150 {
1151 info.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(isFirstRender_)));
1152 }
1153
FindChildByIdForPreview(const JSCallbackInfo & info)1154 void JSViewPartialUpdate::FindChildByIdForPreview(const JSCallbackInfo& info)
1155 {
1156 if (!info[0]->IsNumber()) {
1157 return;
1158 }
1159 std::string viewId = std::to_string(info[0]->ToNumber<int32_t>());
1160 JSRef<JSObject> targetView = Framework::JSViewStackProcessor::GetViewById(viewId);
1161 info.SetReturnValue(targetView);
1162 return;
1163 }
1164
1165 } // namespace OHOS::Ace::Framework
1166