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