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, ¶m);
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