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/engine/jsi/nativeModule/arkts_native_xcomponent_node_bridge.h"
17 
18 #include "bridge/declarative_frontend/jsview/js_xcomponent.h"
19 #include "bridge/declarative_frontend/jsview/js_xcomponent_controller.h"
20 
21 namespace OHOS::Ace::NG {
22 
SetXComponentNodeParams(ArkUIRuntimeCallInfo * runtimeCallInfo,EcmaVM * vm)23 Framework::XComponentParams XComponentNodeBridge::SetXComponentNodeParams(
24     ArkUIRuntimeCallInfo* runtimeCallInfo, EcmaVM* vm)
25 {
26     Framework::XComponentParams params;
27 
28     // elmtId
29     Local<JSValueRef> arg = runtimeCallInfo->GetCallArgRef(0);
30     if (arg->IsNumber()) {
31         params.elmtId = arg->Int32Value(vm);
32     }
33     // xcomponent id
34     arg = runtimeCallInfo->GetCallArgRef(1);
35     if (arg->IsString(vm)) {
36         params.xcomponentId = arg->ToString(vm)->ToString(vm);
37     }
38     // xcomponentType
39     arg = runtimeCallInfo->GetCallArgRef(2);
40     if (arg->IsNumber()) {
41         params.xcomponentType = arg->Int32Value(vm);
42     }
43     // renderType
44     arg = runtimeCallInfo->GetCallArgRef(3);
45     if (arg->IsNumber()) {
46         params.renderType = arg->Int32Value(vm);
47     }
48     // surfaceId
49     arg = runtimeCallInfo->GetCallArgRef(4);
50     if (arg->IsString(vm)) {
51         params.surfaceId = arg->ToString(vm)->ToString(vm);
52     }
53     // selfIdealWidth
54     arg = runtimeCallInfo->GetCallArgRef(5);
55     if (arg->IsNumber()) {
56         params.width = arg->Int32Value(vm);
57     }
58     // selfIdealHeight
59     arg = runtimeCallInfo->GetCallArgRef(6);
60     if (arg->IsNumber()) {
61         params.height = arg->Int32Value(vm);
62     }
63     // libraryname
64     arg = runtimeCallInfo->GetCallArgRef(7);
65     if (arg->IsString(vm)) {
66         params.libraryName = arg->ToString(vm)->ToString(vm);
67     }
68     // xComponentController
69     arg = runtimeCallInfo->GetCallArgRef(8);
70     if (!arg->IsUndefined()) {
71         params.controller =
72             static_cast<Framework::JSXComponentController*>(Local<panda::ObjectRef>(arg)->GetNativePointerField(
73                 vm, 0));
74     }
75 
76     return params;
77 }
78 
Create(ArkUIRuntimeCallInfo * runtimeCallInfo)79 ArkUINativeModuleValue XComponentNodeBridge::Create(ArkUIRuntimeCallInfo* runtimeCallInfo)
80 {
81     EcmaVM* vm = runtimeCallInfo->GetVM();
82     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
83     Framework::XComponentParams params = SetXComponentNodeParams(runtimeCallInfo, vm);
84     void* jsXComponent = Framework::JSXComponent::Create(params);
85     auto nativeModule = panda::NativePointerRef::New(
86         vm, reinterpret_cast<void*>(jsXComponent),
87         [](void *env, void* data, [[maybe_unused]] void* hint) {
88             auto* jsXComponent = reinterpret_cast<Framework::JSXComponent*>(data);
89             if (jsXComponent) {
90                 delete jsXComponent;
91                 jsXComponent = nullptr;
92             }
93         },
94         reinterpret_cast<void*>(jsXComponent), sizeof(void*));
95     return nativeModule;
96 }
97 
GetFrameNode(ArkUIRuntimeCallInfo * runtimeCallInfo)98 ArkUINativeModuleValue XComponentNodeBridge::GetFrameNode(ArkUIRuntimeCallInfo* runtimeCallInfo)
99 {
100     EcmaVM* vm = runtimeCallInfo->GetVM();
101     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
102     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
103     Framework::JSXComponent* jsXComponent =
104         reinterpret_cast<Framework::JSXComponent*>(firstArg->ToNativePointer(vm)->Value());
105     if (jsXComponent) {
106         auto frameNode = jsXComponent->GetFrameNode();
107         auto nativeModule = panda::NativePointerRef::New(vm, reinterpret_cast<void*>(AceType::RawPtr(frameNode)));
108         return nativeModule;
109     }
110     return panda::JSValueRef::Undefined(vm);
111 }
112 
RegisterOnCreateCallback(ArkUIRuntimeCallInfo * runtimeCallInfo)113 ArkUINativeModuleValue XComponentNodeBridge::RegisterOnCreateCallback(ArkUIRuntimeCallInfo* runtimeCallInfo)
114 {
115     EcmaVM* vm = runtimeCallInfo->GetVM();
116     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
117     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
118     Framework::JSXComponent* jsXComponent =
119         reinterpret_cast<Framework::JSXComponent*>(firstArg->ToNativePointer(vm)->Value());
120     Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(1);
121     if (jsXComponent && secondArg->IsFunction(vm)) {
122         Framework::JsiExecutionContext execCtx = { vm };
123         jsXComponent->RegisterOnCreate(execCtx, secondArg);
124     }
125     return panda::JSValueRef::Undefined(vm);
126 }
127 
RegisterOnDestroyCallback(ArkUIRuntimeCallInfo * runtimeCallInfo)128 ArkUINativeModuleValue XComponentNodeBridge::RegisterOnDestroyCallback(ArkUIRuntimeCallInfo* runtimeCallInfo)
129 {
130     EcmaVM* vm = runtimeCallInfo->GetVM();
131     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
132     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
133     Framework::JSXComponent* jsXComponent =
134         reinterpret_cast<Framework::JSXComponent*>(firstArg->ToNativePointer(vm)->Value());
135     Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(1);
136     if (jsXComponent && secondArg->IsFunction(vm)) {
137         Framework::JsiExecutionContext execCtx = { vm };
138         jsXComponent->RegisterOnDestroy(execCtx, secondArg);
139     }
140     return panda::JSValueRef::Undefined(vm);
141 }
142 
ChangeRenderType(ArkUIRuntimeCallInfo * runtimeCallInfo)143 ArkUINativeModuleValue XComponentNodeBridge::ChangeRenderType(ArkUIRuntimeCallInfo* runtimeCallInfo)
144 {
145     EcmaVM* vm = runtimeCallInfo->GetVM();
146     auto defaultNativeModule = panda::BooleanRef::New(vm, false);
147     CHECK_NULL_RETURN(vm, defaultNativeModule);
148     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0);
149     Framework::JSXComponent* jsXComponent =
150         reinterpret_cast<Framework::JSXComponent*>(firstArg->ToNativePointer(vm)->Value());
151     Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(1);
152     if (jsXComponent && secondArg->IsNumber()) {
153         auto ret = jsXComponent->ChangeRenderType(secondArg->Int32Value(vm));
154         auto nativeModule = panda::BooleanRef::New(vm, ret);
155         return nativeModule;
156     }
157     return defaultNativeModule;
158 }
159 } // namespace OHOS::Ace::NG
160