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> (¶ms)[PARAM_SIZE])857 bool ParseRecycleParams(const JSCallbackInfo& info, JSRef<JSVal> (¶ms)[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