• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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_node_container.h"
17 
18 #include <functional>
19 #include <mutex>
20 #include <unistd.h>
21 
22 #include "base/geometry/ng/size_t.h"
23 #include "base/utils/utils.h"
24 #include "bridge/common/utils/engine_helper.h"
25 #include "bridge/declarative_frontend/engine/functions/js_function.h"
26 #include "bridge/declarative_frontend/engine/js_converter.h"
27 #include "bridge/declarative_frontend/engine/jsi/jsi_types.h"
28 #include "bridge/declarative_frontend/engine/jsi/nativeModule/ui_context_helper.h"
29 #include "bridge/declarative_frontend/jsview/js_base_node.h"
30 #include "core/common/container_scope.h"
31 #include "core/components_ng/base/view_abstract_model.h"
32 #include "core/components_ng/base/view_stack_processor.h"
33 #include "core/components_ng/pattern/node_container/node_container_model_ng.h"
34 
35 namespace OHOS::Ace {
36 namespace {
37 const char* NODE_CONTAINER_ID = "_nodeContainerId";
38 const char* INTERNAL_FIELD_VALUE = "_value";
39 const char* NODEPTR_OF_UINODE = "nodePtr_";
40 constexpr int32_t INVALID_NODE_CONTAINER_ID = -1;
41 
RemoveFromNodeControllerMap(EcmaVM * vm,int32_t nodeId)42 void RemoveFromNodeControllerMap(EcmaVM* vm, int32_t nodeId)
43 {
44     auto global = JSNApi::GetGlobalObject(vm);
45     auto funcName = panda::StringRef::NewFromUtf8(vm, "__RemoveFromNodeControllerMap__");
46     auto obj = global->Get(vm, funcName);
47     if (obj->IsFunction(vm)) {
48         panda::Local<panda::FunctionRef> detachFunc = obj;
49         auto func = panda::CopyableGlobal(vm, detachFunc);
50         panda::Local<panda::JSValueRef> params[] = { panda::NumberRef::New(vm, nodeId) };
51         func->Call(vm, func.ToLocal(), params, ArraySize(params));
52     }
53 }
54 
BindFunc(const Framework::JSCallbackInfo & info,const RefPtr<NG::FrameNode> & frameNode)55 void BindFunc(const Framework::JSCallbackInfo& info, const RefPtr<NG::FrameNode>& frameNode)
56 {
57     CHECK_NULL_VOID(frameNode);
58     CHECK_NULL_VOID(!frameNode->HasOnNodeDestroyCallback());
59     EcmaVM* vm = info.GetVm();
60     CHECK_NULL_VOID(vm);
61     auto global = JSNApi::GetGlobalObject(vm);
62     auto funcName = panda::StringRef::NewFromUtf8(vm, "__RemoveFromNodeControllerMap__");
63     auto obj = global->Get(vm, funcName);
64     auto nodeContainerEventHub = frameNode->GetOrCreateEventHub<NG::NodeContainerEventHub>();
65     auto weakEventHub = AceType::WeakClaim(AceType::RawPtr(nodeContainerEventHub));
66     if (obj->IsFunction(vm)) {
67         frameNode->SetOnNodeDestroyCallback([vm, weakEventHub](int32_t nodeId) {
68             auto eventHub = weakEventHub.Upgrade();
69             CHECK_NULL_VOID(eventHub);
70             eventHub->FireOnWillUnbind(nodeId);
71             RemoveFromNodeControllerMap(vm, nodeId);
72             eventHub->FireOnUnbind(nodeId);
73         });
74     }
75 }
76 
AddToNodeControllerMap(EcmaVM * vm,int32_t nodeId,const Framework::JSRef<Framework::JSObject> & object)77 void AddToNodeControllerMap(EcmaVM* vm, int32_t nodeId, const Framework::JSRef<Framework::JSObject>& object)
78 {
79     auto global = JSNApi::GetGlobalObject(vm);
80     auto funcName = panda::StringRef::NewFromUtf8(vm, "__AddToNodeControllerMap__");
81     auto obj = global->Get(vm, funcName);
82     if (obj->IsFunction(vm)) {
83         panda::Local<panda::FunctionRef> attachFunc = obj;
84         panda::Local<panda::JSValueRef> params[] = { panda::NumberRef::New(vm, nodeId),
85             panda::CopyableGlobal(vm, object->GetLocalHandle()).ToLocal() };
86         attachFunc->Call(vm, attachFunc, params, ArraySize(params));
87     }
88 }
89 } // namespace
90 
91 std::unique_ptr<NodeContainerModel> NodeContainerModel::instance_;
92 std::mutex NodeContainerModel::mutex_;
93 
GetInstance()94 NodeContainerModel* NodeContainerModel::GetInstance()
95 {
96     if (!instance_) {
97         std::lock_guard<std::mutex> lock(mutex_);
98         if (!instance_) {
99 #ifdef NG_BUILD
100             instance_.reset(new NG::NodeContainerModelNG());
101 #else
102             if (Container::IsCurrentUseNewPipeline()) {
103                 instance_.reset(new NG::NodeContainerModelNG());
104             } else {
105                 LOGE("NodeContainerModelNG is not supported in OldPipeline.");
106                 return nullptr;
107             }
108 #endif
109         }
110     }
111     return instance_.get();
112 }
113 } // namespace OHOS::Ace
114 
115 namespace OHOS::Ace::Framework {
Create(const JSCallbackInfo & info)116 void JSNodeContainer::Create(const JSCallbackInfo& info)
117 {
118     NodeContainerModel* nodeContainerModelInstance = NodeContainerModel::GetInstance();
119     CHECK_NULL_VOID(nodeContainerModelInstance);
120     nodeContainerModelInstance->Create();
121     auto frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
122     CHECK_NULL_VOID(frameNode);
123     if (info.Length() < 1 || !info[0]->IsObject() || info[0]->IsNull()) {
124         frameNode->RemoveChildAtIndex(0);
125         frameNode->MarkNeedFrameFlushDirty(NG::PROPERTY_UPDATE_MEASURE);
126         ResetNodeController();
127         return;
128     }
129     auto object = JSRef<JSObject>::Cast(info[0]);
130 
131     JSObject firstArg = JSRef<JSObject>::Cast(info[0]).Get();
132     auto nodeContainerId = frameNode->GetId();
133     EcmaVM* vm = info.GetVm();
134     CHECK_NULL_VOID(vm);
135     // check if it's the same object, and if it is, return it;
136     auto internalField = firstArg->GetProperty(NODE_CONTAINER_ID);
137     if (internalField->IsObject()) {
138         auto obj = JSRef<JSObject>::Cast(internalField);
139         auto insideId = obj->GetProperty(INTERNAL_FIELD_VALUE);
140         if (insideId->IsNumber()) {
141             auto id = insideId->ToNumber<int32_t>();
142             if (id == nodeContainerId) {
143                 return;
144             } else if (id != INVALID_NODE_CONTAINER_ID) {
145                 JSNodeContainer::FireOnWillUnbind(nodeContainerId);
146                 RemoveFromNodeControllerMap(vm, id);
147                 JSNodeContainer::FireOnUnbind(nodeContainerId);
148             }
149         }
150     }
151     // clear the _nodeContainerId in pre controller;
152     nodeContainerModelInstance->ResetController();
153 
154     BindFunc(info, AceType::Claim(frameNode));
155     // set a function to reset the _nodeContainerId in controller;
156     auto resetFunc = [firstArg = JSWeak<JSObject>(object), nodeContainerId, vm]() {
157         JSNodeContainer::ResetNodeContainerId(firstArg, nodeContainerId, vm);
158     };
159     nodeContainerModelInstance->BindController(std::move(resetFunc));
160     auto execCtx = info.GetExecutionContext();
161 
162     SetNodeController(object, execCtx);
163     JSNodeContainer::FireOnWillBind(nodeContainerId);
164     AddToNodeControllerMap(vm, nodeContainerId, object);
165     // set the _nodeContainerId to nodeController
166     if (internalField->IsObject()) {
167         auto obj = JSRef<JSObject>::Cast(internalField);
168         obj->SetProperty(INTERNAL_FIELD_VALUE, nodeContainerId);
169     }
170     JSNodeContainer::FireOnBind(nodeContainerId);
171     nodeContainerModelInstance->FireMakeNode();
172 }
173 
ResetNodeContainerId(const JSWeak<JSObject> & firstArg,int32_t nodeContainerId,EcmaVM * vm)174 void JSNodeContainer::ResetNodeContainerId(const JSWeak<JSObject>& firstArg, int32_t nodeContainerId, EcmaVM* vm)
175 {
176     CHECK_NULL_VOID(!firstArg.IsEmpty());
177     JSObject args = firstArg.Lock().Get();
178     auto internalField = args->GetProperty(NODE_CONTAINER_ID);
179     CHECK_NULL_VOID(internalField->IsObject());
180     auto obj = JSRef<JSObject>::Cast(internalField);
181     auto insideId = obj->GetProperty(INTERNAL_FIELD_VALUE);
182     if (insideId->IsNumber()) {
183         auto id = insideId->ToNumber<int32_t>();
184         if (id != nodeContainerId) {
185             return;
186         }
187     }
188     JSNodeContainer::FireOnWillUnbind(nodeContainerId);
189     RemoveFromNodeControllerMap(vm, nodeContainerId);
190     obj->SetProperty(INTERNAL_FIELD_VALUE, INVALID_NODE_CONTAINER_ID);
191     JSNodeContainer::FireOnUnbind(nodeContainerId);
192 }
193 
SetNodeController(const JSRef<JSObject> & object,JsiExecutionContext execCtx)194 void JSNodeContainer::SetNodeController(const JSRef<JSObject>& object, JsiExecutionContext execCtx)
195 {
196     // get the function to makeNode
197     JSRef<JSVal> jsMakeNodeFunc = object->GetProperty("__makeNode__");
198     if (!jsMakeNodeFunc->IsFunction()) {
199         ResetNodeController();
200         return;
201     }
202     NodeContainerModel* nodeContainerModelInstance = NodeContainerModel::GetInstance();
203     CHECK_NULL_VOID(nodeContainerModelInstance);
204 
205     auto jsFunc = JSRef<JSFunc>::Cast(jsMakeNodeFunc);
206     auto containerId = Container::CurrentId();
207     RefPtr<JsFunction> jsMake = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(object), jsFunc);
208     nodeContainerModelInstance->SetMakeFunction(
209         [func = std::move(jsMake), containerId, execCtx]() -> RefPtr<NG::UINode> {
210             JAVASCRIPT_EXECUTION_SCOPE(execCtx);
211             ContainerScope scope(containerId);
212             panda::Local<panda::JSValueRef> uiContext = NG::UIContextHelper::GetUIContext(execCtx.vm_, containerId);
213             auto jsVal = JSRef<JSVal>::Make(uiContext);
214             JSRef<JSVal> result = func->ExecuteJS(1, &jsVal);
215             if (result.IsEmpty() || !result->IsObject()) {
216                 return nullptr;
217             }
218             JSRef<JSObject> obj = JSRef<JSObject>::Cast(result);
219             JSRef<JSVal> nodeptr = obj->GetProperty(NODEPTR_OF_UINODE);
220             if (nodeptr.IsEmpty()) {
221                 return nullptr;
222             }
223             const auto* vm = nodeptr->GetEcmaVM();
224             auto* node = nodeptr->GetLocalHandle()->ToNativePointer(vm)->Value();
225             auto* uiNode = reinterpret_cast<NG::UINode*>(node);
226             CHECK_NULL_RETURN(uiNode, nullptr);
227             return AceType::Claim(uiNode);
228         });
229 
230     SetOnAppearFunc(object, execCtx);
231     SetOnDisappearFunc(object, execCtx);
232     SetOnResizeFunc(object, execCtx);
233     SetOnTouchEventFunc(object, execCtx);
234     SetOnAttachFunc(object, execCtx);
235     SetOnDetachFunc(object, execCtx);
236     SetOnWillBindFunc(object, execCtx);
237     SetOnWillUnbindFunc(object, execCtx);
238     SetOnBindFunc(object, execCtx);
239     SetOnUnbindFunc(object, execCtx);
240 }
241 
ResetNodeController()242 void JSNodeContainer::ResetNodeController()
243 {
244     NodeContainerModel* nodeContainerModelInstance = NodeContainerModel::GetInstance();
245     CHECK_NULL_VOID(nodeContainerModelInstance);
246     nodeContainerModelInstance->ResetController();
247     nodeContainerModelInstance->SetMakeFunction(nullptr);
248     nodeContainerModelInstance->SetOnTouchEvent(nullptr);
249     nodeContainerModelInstance->SetOnResize(nullptr);
250     nodeContainerModelInstance->SetOnAppear(nullptr);
251     nodeContainerModelInstance->SetOnDisAppear(nullptr);
252     nodeContainerModelInstance->SetOnWillBind(nullptr);
253     nodeContainerModelInstance->SetOnWillUnbind(nullptr);
254     nodeContainerModelInstance->SetOnBind(nullptr);
255     nodeContainerModelInstance->SetOnUnbind(nullptr);
256     nodeContainerModelInstance->SetOnAttach(nullptr);
257     nodeContainerModelInstance->SetOnDetach(nullptr);
258     ViewAbstractModel::GetInstance()->SetOnAttach(nullptr);
259     ViewAbstractModel::GetInstance()->SetOnDetach(nullptr);
260 }
261 
SetOnAppearFunc(const JSRef<JSObject> & object,JsiExecutionContext execCtx)262 void JSNodeContainer::SetOnAppearFunc(const JSRef<JSObject>& object, JsiExecutionContext execCtx)
263 {
264     auto showCallback = object->GetProperty("aboutToAppear");
265     CHECK_NULL_VOID(showCallback->IsFunction());
266     NodeContainerModel* nodeContainerModelInstance = NodeContainerModel::GetInstance();
267     CHECK_NULL_VOID(nodeContainerModelInstance);
268     RefPtr<JsFunction> jsAppearFunc =
269         AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(object), JSRef<JSFunc>::Cast(showCallback));
270     auto onAppear = [func = std::move(jsAppearFunc), execCtx]() {
271         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
272         func->Execute();
273     };
274     nodeContainerModelInstance->SetOnAppear(onAppear);
275 }
276 
SetOnDisappearFunc(const JSRef<JSObject> & object,JsiExecutionContext execCtx)277 void JSNodeContainer::SetOnDisappearFunc(const JSRef<JSObject>& object, JsiExecutionContext execCtx)
278 {
279     auto dismissCallback = object->GetProperty("aboutToDisappear");
280     CHECK_NULL_VOID(dismissCallback->IsFunction());
281     NodeContainerModel* nodeContainerModelInstance = NodeContainerModel::GetInstance();
282     CHECK_NULL_VOID(nodeContainerModelInstance);
283     RefPtr<JsFunction> jsDisappearFunc =
284         AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(object), JSRef<JSFunc>::Cast(dismissCallback));
285     auto onDisappear = [func = std::move(jsDisappearFunc), execCtx]() {
286         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
287         func->Execute();
288     };
289     nodeContainerModelInstance->SetOnDisAppear(onDisappear);
290 }
291 
SetOnAttachFunc(const JSRef<JSObject> & object,JsiExecutionContext execCtx)292 void JSNodeContainer::SetOnAttachFunc(const JSRef<JSObject>& object, JsiExecutionContext execCtx)
293 {
294     auto showCallback = object->GetProperty("onAttach");
295     CHECK_NULL_VOID(showCallback->IsFunction());
296     NodeContainerModel* nodeContainerModelInstance = NodeContainerModel::GetInstance();
297     CHECK_NULL_VOID(nodeContainerModelInstance);
298     RefPtr<JsFunction> jsAttachFunc =
299         AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(object), JSRef<JSFunc>::Cast(showCallback));
300     auto onAttach = [func = std::move(jsAttachFunc), execCtx]() {
301         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
302         func->Execute();
303     };
304     nodeContainerModelInstance->SetOnAttach(onAttach);
305 }
306 
SetOnDetachFunc(const JSRef<JSObject> & object,JsiExecutionContext execCtx)307 void JSNodeContainer::SetOnDetachFunc(const JSRef<JSObject>& object, JsiExecutionContext execCtx)
308 {
309     auto dismissCallback = object->GetProperty("onDetach");
310     CHECK_NULL_VOID(dismissCallback->IsFunction());
311     NodeContainerModel* nodeContainerModelInstance = NodeContainerModel::GetInstance();
312     CHECK_NULL_VOID(nodeContainerModelInstance);
313     RefPtr<JsFunction> jsDetachFunc =
314         AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(object), JSRef<JSFunc>::Cast(dismissCallback));
315     auto onDetach = [func = std::move(jsDetachFunc), execCtx]() {
316         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
317         func->Execute();
318     };
319     nodeContainerModelInstance->SetOnDetach(onDetach);
320 }
321 
SetOnTouchEventFunc(const JSRef<JSObject> & object,JsiExecutionContext execCtx)322 void JSNodeContainer::SetOnTouchEventFunc(const JSRef<JSObject>& object, JsiExecutionContext execCtx)
323 {
324     auto onTouchEventCallback = object->GetProperty("onTouchEvent");
325     CHECK_NULL_VOID(onTouchEventCallback->IsFunction());
326     NodeContainerModel* nodeContainerModelInstance = NodeContainerModel::GetInstance();
327     CHECK_NULL_VOID(nodeContainerModelInstance);
328     RefPtr<JsTouchFunction> jsOnTouchFunc =
329         AceType::MakeRefPtr<JsTouchFunction>(JSRef<JSObject>(object), JSRef<JSFunc>::Cast(onTouchEventCallback));
330     WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
331     auto onTouch = [execCtx, func = std::move(jsOnTouchFunc), node = frameNode](TouchEventInfo& info) {
332         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
333         PipelineContext::SetCallBackNode(node);
334         func->Execute(info);
335     };
336     nodeContainerModelInstance->SetOnTouchEvent(std::move(onTouch));
337 }
338 
SetOnResizeFunc(const JSRef<JSObject> & object,JsiExecutionContext execCtx)339 void JSNodeContainer::SetOnResizeFunc(const JSRef<JSObject>& object, JsiExecutionContext execCtx)
340 {
341     auto aboutToResize = object->GetProperty("aboutToResize");
342     CHECK_NULL_VOID(aboutToResize->IsFunction());
343     NodeContainerModel* nodeContainerModelInstance = NodeContainerModel::GetInstance();
344     CHECK_NULL_VOID(nodeContainerModelInstance);
345     RefPtr<JsFunction> jsAboutToResizeFunc =
346         AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(object), JSRef<JSFunc>::Cast(aboutToResize));
347     auto onResize = [func = std::move(jsAboutToResizeFunc), execCtx](const NG::SizeF& size) {
348         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
349         JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
350         objectTemplate->SetInternalFieldCount(1);
351         JSRef<JSObject> obj = objectTemplate->NewInstance();
352         obj->SetProperty<double>("width", PipelineBase::Px2VpWithCurrentDensity(size.Width()));
353         obj->SetProperty<double>("height", PipelineBase::Px2VpWithCurrentDensity(size.Height()));
354         JSRef<JSVal> param = JSRef<JSVal>::Cast(obj);
355         func->ExecuteJS(1, &param);
356     };
357     nodeContainerModelInstance->SetOnResize(onResize);
358 }
359 
SetOnWillBindFunc(const JSRef<JSObject> & object,JsiExecutionContext execCtx)360 void JSNodeContainer::SetOnWillBindFunc(const JSRef<JSObject>& object, JsiExecutionContext execCtx)
361 {
362     auto onWillBindCallback = object->GetProperty("onWillBind");
363     CHECK_NULL_VOID(onWillBindCallback->IsFunction());
364     NodeContainerModel* nodeContainerModelInstance = NodeContainerModel::GetInstance();
365     CHECK_NULL_VOID(nodeContainerModelInstance);
366     RefPtr<JsFunction> jsOnWillBindFunc =
367         AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(object), JSRef<JSFunc>::Cast(onWillBindCallback));
368     auto onWillBind = [execCtx, func = std::move(jsOnWillBindFunc)](int32_t containerId) {
369         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
370         JSRef<JSVal> nodeContainerIndex = JSRef<JSVal>::Make(ToJSValue(containerId));
371         func->ExecuteJS(1, &nodeContainerIndex);
372     };
373     nodeContainerModelInstance->SetOnWillBind(std::move(onWillBind));
374 }
375 
SetOnWillUnbindFunc(const JSRef<JSObject> & object,JsiExecutionContext execCtx)376 void JSNodeContainer::SetOnWillUnbindFunc(const JSRef<JSObject>& object, JsiExecutionContext execCtx)
377 {
378     auto onWillUnbindCallback = object->GetProperty("onWillUnbind");
379     CHECK_NULL_VOID(onWillUnbindCallback->IsFunction());
380     NodeContainerModel* nodeContainerModelInstance = NodeContainerModel::GetInstance();
381     CHECK_NULL_VOID(nodeContainerModelInstance);
382     RefPtr<JsFunction> jsOnWillUnbindFunc =
383         AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(object), JSRef<JSFunc>::Cast(onWillUnbindCallback));
384     auto onWillUnbind = [execCtx, func = std::move(jsOnWillUnbindFunc)](int32_t containerId) {
385         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
386         JSRef<JSVal> nodeContainerIndex = JSRef<JSVal>::Make(ToJSValue(containerId));
387         func->ExecuteJS(1, &nodeContainerIndex);
388     };
389     nodeContainerModelInstance->SetOnWillUnbind(std::move(onWillUnbind));
390 }
391 
SetOnBindFunc(const JSRef<JSObject> & object,JsiExecutionContext execCtx)392 void JSNodeContainer::SetOnBindFunc(const JSRef<JSObject>& object, JsiExecutionContext execCtx)
393 {
394     auto onBindCallback = object->GetProperty("onBind");
395     CHECK_NULL_VOID(onBindCallback->IsFunction());
396     NodeContainerModel* nodeContainerModelInstance = NodeContainerModel::GetInstance();
397     CHECK_NULL_VOID(nodeContainerModelInstance);
398     RefPtr<JsFunction> jsOnBindFunc =
399         AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(object), JSRef<JSFunc>::Cast(onBindCallback));
400     auto onBind = [execCtx, func = std::move(jsOnBindFunc)](int32_t containerId) {
401         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
402         JSRef<JSVal> nodeContainerIndex = JSRef<JSVal>::Make(ToJSValue(containerId));
403         func->ExecuteJS(1, &nodeContainerIndex);
404     };
405     nodeContainerModelInstance->SetOnBind(std::move(onBind));
406 }
407 
SetOnUnbindFunc(const JSRef<JSObject> & object,JsiExecutionContext execCtx)408 void JSNodeContainer::SetOnUnbindFunc(const JSRef<JSObject>& object, JsiExecutionContext execCtx)
409 {
410     auto onUnbindCallback = object->GetProperty("onUnbind");
411     CHECK_NULL_VOID(onUnbindCallback->IsFunction());
412     NodeContainerModel* nodeContainerModelInstance = NodeContainerModel::GetInstance();
413     CHECK_NULL_VOID(nodeContainerModelInstance);
414     RefPtr<JsFunction> jsOnUnbindFunc =
415         AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(object), JSRef<JSFunc>::Cast(onUnbindCallback));
416     auto onUnbind = [execCtx, func = std::move(jsOnUnbindFunc)](int32_t containerId) {
417         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
418         JSRef<JSVal> nodeContainerIndex = JSRef<JSVal>::Make(ToJSValue(containerId));
419         func->ExecuteJS(1, &nodeContainerIndex);
420     };
421     nodeContainerModelInstance->SetOnUnbind(std::move(onUnbind));
422 }
423 
GetNodeContainerPattern(int32_t containerId)424 RefPtr<NG::NodeContainerPattern> JSNodeContainer::GetNodeContainerPattern(int32_t containerId)
425 {
426     auto uiNode = ElementRegister::GetInstance()->GetUINodeById(containerId);
427     if (!uiNode) {
428         return nullptr;
429     }
430     if (AceType::InstanceOf<NG::FrameNode>(uiNode)) {
431         auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
432         if (frameNode) {
433             return frameNode->GetPattern<NG::NodeContainerPattern>();
434         }
435     }
436     return nullptr;
437 }
438 
FireOnWillBind(int32_t containerId)439 void JSNodeContainer::FireOnWillBind(int32_t containerId)
440 {
441     auto nodeContainerPattern = JSNodeContainer::GetNodeContainerPattern(containerId);
442     if (nodeContainerPattern) {
443         nodeContainerPattern->FireOnWillBind(containerId);
444     }
445 }
446 
FireOnWillUnbind(int32_t containerId)447 void JSNodeContainer::FireOnWillUnbind(int32_t containerId)
448 {
449     auto nodeContainerPattern = JSNodeContainer::GetNodeContainerPattern(containerId);
450     if (nodeContainerPattern) {
451         nodeContainerPattern->FireOnWillUnbind(containerId);
452     }
453 }
454 
FireOnBind(int32_t containerId)455 void JSNodeContainer::FireOnBind(int32_t containerId)
456 {
457     auto nodeContainerPattern = JSNodeContainer::GetNodeContainerPattern(containerId);
458     if (nodeContainerPattern) {
459         nodeContainerPattern->FireOnBind(containerId);
460     }
461 }
462 
FireOnUnbind(int32_t containerId)463 void JSNodeContainer::FireOnUnbind(int32_t containerId)
464 {
465     auto nodeContainerPattern = JSNodeContainer::GetNodeContainerPattern(containerId);
466     if (nodeContainerPattern) {
467         nodeContainerPattern->FireOnUnbind(containerId);
468     }
469 }
470 
GetCurrentContext()471 JSRef<JSVal> JSNodeContainer::GetCurrentContext()
472 {
473     auto container = Container::Current();
474     CHECK_NULL_RETURN(container, JSRef<JSVal>());
475     auto frontend = container->GetFrontend();
476     CHECK_NULL_RETURN(frontend, JSRef<JSVal>());
477     auto context = frontend->GetContextValue();
478     auto jsVal = JsConverter::ConvertNapiValueToJsVal(context);
479     return jsVal;
480 }
481 
JSBind(BindingTarget globalObj)482 void JSNodeContainer::JSBind(BindingTarget globalObj)
483 {
484     JSClass<JSNodeContainer>::Declare("NodeContainer");
485 
486     MethodOptions opt = MethodOptions::NONE;
487     JSClass<JSNodeContainer>::StaticMethod("create", &JSNodeContainer::Create, opt);
488     JSClass<JSNodeContainer>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
489     JSClass<JSNodeContainer>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
490     JSClass<JSNodeContainer>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
491     JSClass<JSNodeContainer>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
492     JSClass<JSNodeContainer>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
493     JSClass<JSNodeContainer>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
494     JSClass<JSNodeContainer>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
495     JSClass<JSNodeContainer>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
496 
497     JSClass<JSNodeContainer>::InheritAndBind<JSViewAbstract>(globalObj);
498 }
499 } // namespace OHOS::Ace::Framework
500