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> (&params)[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