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 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_radio_bridge.h"
16 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_utils.h"
17 #include "core/components/checkable/checkable_theme.h"
18 #include "core/components_ng/base/frame_node.h"
19 #include "core/components_ng/pattern/radio/radio_model_ng.h"
20 
21 namespace OHOS::Ace::NG {
22 constexpr int NUM_0 = 0;
23 constexpr int NUM_1 = 1;
24 constexpr int NUM_2 = 2;
25 constexpr int NUM_3 = 3;
26 const char* RADIO_BUILDER_NODEPTR_OF_UINODE = "nodePtr_";
JsRadioChangeCallback(panda::JsiRuntimeCallInfo * runtimeCallInfo)27 panda::Local<panda::JSValueRef> JsRadioChangeCallback(panda::JsiRuntimeCallInfo* runtimeCallInfo)
28 {
29     auto vm = runtimeCallInfo->GetVM();
30     int32_t argc = static_cast<int32_t>(runtimeCallInfo->GetArgsNumber());
31     if (argc != NUM_1) {
32         return panda::JSValueRef::Undefined(vm);
33     }
34     auto firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
35     if (!firstArg->IsBoolean()) {
36         return panda::JSValueRef::Undefined(vm);
37     }
38     bool value = firstArg->ToBoolean(vm)->Value();
39     auto ref = runtimeCallInfo->GetThisRef();
40     auto obj = ref->ToObject(vm);
41     if (obj->GetNativePointerFieldCount(vm) < NUM_1) {
42         return panda::JSValueRef::Undefined(vm);
43     }
44     auto frameNode = static_cast<FrameNode*>(obj->GetNativePointerField(vm, 0));
45     CHECK_NULL_RETURN(frameNode, panda::JSValueRef::Undefined(vm));
46     RadioModelNG::SetChangeValue(frameNode, value);
47     return panda::JSValueRef::Undefined(vm);
48 }
49 
SetRadioChecked(ArkUIRuntimeCallInfo * runtimeCallInfo)50 ArkUINativeModuleValue RadioBridge::SetRadioChecked(ArkUIRuntimeCallInfo* runtimeCallInfo)
51 {
52     EcmaVM* vm = runtimeCallInfo->GetVM();
53     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
54     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
55     Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(NUM_1);
56     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
57     bool isCheck = secondArg->ToBoolean(vm)->Value();
58     GetArkUINodeModifiers()->getRadioModifier()->setRadioChecked(nativeNode, isCheck);
59     return panda::JSValueRef::Undefined(vm);
60 }
61 
ResetRadioChecked(ArkUIRuntimeCallInfo * runtimeCallInfo)62 ArkUINativeModuleValue RadioBridge::ResetRadioChecked(ArkUIRuntimeCallInfo* runtimeCallInfo)
63 {
64     EcmaVM* vm = runtimeCallInfo->GetVM();
65     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
66     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
67     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
68     GetArkUINodeModifiers()->getRadioModifier()->resetRadioChecked(nativeNode);
69     return panda::JSValueRef::Undefined(vm);
70 }
71 
SetRadioStyle(ArkUIRuntimeCallInfo * runtimeCallInfo)72 ArkUINativeModuleValue RadioBridge::SetRadioStyle(ArkUIRuntimeCallInfo* runtimeCallInfo)
73 {
74     EcmaVM* vm = runtimeCallInfo->GetVM();
75     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
76     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
77     Local<JSValueRef> checkedBackgroundColor = runtimeCallInfo->GetCallArgRef(NUM_1);
78     Local<JSValueRef> uncheckedBorderColor = runtimeCallInfo->GetCallArgRef(NUM_2);
79     Local<JSValueRef> indicatorColor = runtimeCallInfo->GetCallArgRef(NUM_3);
80     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
81 
82     auto pipeline = PipelineBase::GetCurrentContext();
83     CHECK_NULL_RETURN(pipeline, panda::NativePointerRef::New(vm, nullptr));
84     auto radioTheme = pipeline->GetTheme<RadioTheme>();
85     CHECK_NULL_RETURN(radioTheme, panda::NativePointerRef::New(vm, nullptr));
86 
87     Color checkedBackgroundColorVal;
88     if (checkedBackgroundColor->IsNull() || checkedBackgroundColor->IsUndefined() ||
89         !ArkTSUtils::ParseJsColorAlpha(vm, checkedBackgroundColor, checkedBackgroundColorVal)) {
90         checkedBackgroundColorVal = radioTheme->GetActiveColor();
91     }
92     Color uncheckedBorderColorVal;
93     if (uncheckedBorderColor->IsNull() || uncheckedBorderColor->IsUndefined() ||
94         !ArkTSUtils::ParseJsColorAlpha(vm, uncheckedBorderColor, uncheckedBorderColorVal)) {
95         uncheckedBorderColorVal = radioTheme->GetInactiveColor();
96     }
97     Color indicatorColorVal;
98     if (indicatorColor->IsNull() || indicatorColor->IsUndefined() ||
99         !ArkTSUtils::ParseJsColorAlpha(vm, indicatorColor, indicatorColorVal)) {
100         indicatorColorVal = radioTheme->GetPointColor();
101     }
102 
103     GetArkUINodeModifiers()->getRadioModifier()->setRadioStyle(nativeNode,
104         checkedBackgroundColorVal.GetValue(), uncheckedBorderColorVal.GetValue(), indicatorColorVal.GetValue());
105     return panda::JSValueRef::Undefined(vm);
106 }
107 
ResetRadioStyle(ArkUIRuntimeCallInfo * runtimeCallInfo)108 ArkUINativeModuleValue RadioBridge::ResetRadioStyle(ArkUIRuntimeCallInfo* runtimeCallInfo)
109 {
110     EcmaVM* vm = runtimeCallInfo->GetVM();
111     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
112     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
113     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
114     GetArkUINodeModifiers()->getRadioModifier()->resetRadioStyle(nativeNode);
115     return panda::JSValueRef::Undefined(vm);
116 }
117 
SetRadioWidth(ArkUIRuntimeCallInfo * runtimeCallInfo)118 ArkUINativeModuleValue RadioBridge::SetRadioWidth(ArkUIRuntimeCallInfo* runtimeCallInfo)
119 {
120     EcmaVM* vm = runtimeCallInfo->GetVM();
121     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
122     Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(0);
123     Local<JSValueRef> widthArg = runtimeCallInfo->GetCallArgRef(1);
124     auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
125     CalcDimension width;
126     if (!ArkTSUtils::ParseJsDimensionVpNG(vm, widthArg, width)) {
127         GetArkUINodeModifiers()->getRadioModifier()->resetRadioWidth(nativeNode);
128         return panda::JSValueRef::Undefined(vm);
129     }
130     if (LessNotEqual(width.Value(), 0.0)) {
131         width.SetValue(0.0);
132     }
133     std::string widthCalc = width.CalcValue();
134     GetArkUINodeModifiers()->getRadioModifier()->setRadioWidth(
135         nativeNode, width.Value(), static_cast<int32_t>(width.Unit()), widthCalc.c_str());
136     return panda::JSValueRef::Undefined(vm);
137 }
138 
ResetRadioWidth(ArkUIRuntimeCallInfo * runtimeCallInfo)139 ArkUINativeModuleValue RadioBridge::ResetRadioWidth(ArkUIRuntimeCallInfo* runtimeCallInfo)
140 {
141     EcmaVM* vm = runtimeCallInfo->GetVM();
142     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
143     Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(0); //0 is node arguments
144     auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
145     GetArkUINodeModifiers()->getRadioModifier()->resetRadioWidth(nativeNode);
146     return panda::JSValueRef::Undefined(vm);
147 }
148 
SetRadioHeight(ArkUIRuntimeCallInfo * runtimeCallInfo)149 ArkUINativeModuleValue RadioBridge::SetRadioHeight(ArkUIRuntimeCallInfo* runtimeCallInfo)
150 {
151     EcmaVM* vm = runtimeCallInfo->GetVM();
152     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
153     Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(0);
154     Local<JSValueRef> heightArg = runtimeCallInfo->GetCallArgRef(1);
155     auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
156     CalcDimension height;
157     if (!ArkTSUtils::ParseJsDimensionVpNG(vm, heightArg, height)) {
158         GetArkUINodeModifiers()->getRadioModifier()->resetRadioHeight(nativeNode);
159         return panda::JSValueRef::Undefined(vm);
160     }
161     if (LessNotEqual(height.Value(), 0.0)) {
162         height.SetValue(0.0);
163     }
164     std::string heightCalc = height.CalcValue();
165     GetArkUINodeModifiers()->getRadioModifier()->setRadioHeight(
166         nativeNode, height.Value(), static_cast<int32_t>(height.Unit()), heightCalc.c_str());
167     return panda::JSValueRef::Undefined(vm);
168 }
169 
ResetRadioHeight(ArkUIRuntimeCallInfo * runtimeCallInfo)170 ArkUINativeModuleValue RadioBridge::ResetRadioHeight(ArkUIRuntimeCallInfo* runtimeCallInfo)
171 {
172     EcmaVM* vm = runtimeCallInfo->GetVM();
173     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
174     Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(0); //0 is node arguments
175     auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
176     GetArkUINodeModifiers()->getRadioModifier()->resetRadioHeight(nativeNode);
177     return panda::JSValueRef::Undefined(vm);
178 }
179 
SetRadioSize(ArkUIRuntimeCallInfo * runtimeCallInfo)180 ArkUINativeModuleValue RadioBridge::SetRadioSize(ArkUIRuntimeCallInfo* runtimeCallInfo)
181 {
182     EcmaVM* vm = runtimeCallInfo->GetVM();
183     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
184     Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(0);     //0 is node arguments
185     Local<JSValueRef> widthArg = runtimeCallInfo->GetCallArgRef(1);  //1 is width value
186     Local<JSValueRef> heightArg = runtimeCallInfo->GetCallArgRef(2); //2 is height value
187     auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
188 
189     CalcDimension width;
190     CalcDimension height;
191     if (!ArkTSUtils::ParseJsDimensionVpNG(vm, widthArg, width)) {
192         GetArkUINodeModifiers()->getRadioModifier()->resetRadioWidth(nativeNode);
193     } else {
194         std::string widthCalc = width.CalcValue();
195         if (LessNotEqual(width.Value(), 0.0)) {
196             width.SetValue(0.0);
197         }
198         GetArkUINodeModifiers()->getRadioModifier()->setRadioWidth(
199             nativeNode, width.Value(), static_cast<int>(width.Unit()), widthCalc.c_str());
200     }
201     if (!ArkTSUtils::ParseJsDimensionVpNG(vm, heightArg, height)) {
202         GetArkUINodeModifiers()->getRadioModifier()->resetRadioHeight(nativeNode);
203     } else {
204         std::string heightCalc = height.CalcValue();
205         if (LessNotEqual(height.Value(), 0.0)) {
206             height.SetValue(0.0);
207         }
208         GetArkUINodeModifiers()->getRadioModifier()->setRadioHeight(
209             nativeNode, height.Value(), static_cast<int>(height.Unit()), heightCalc.c_str());
210     }
211     return panda::JSValueRef::Undefined(vm);
212 }
213 
ResetRadioSize(ArkUIRuntimeCallInfo * runtimeCallInfo)214 ArkUINativeModuleValue RadioBridge::ResetRadioSize(ArkUIRuntimeCallInfo* runtimeCallInfo)
215 {
216     EcmaVM* vm = runtimeCallInfo->GetVM();
217     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
218     Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(0); //0 is node arguments
219     auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
220     GetArkUINodeModifiers()->getRadioModifier()->resetRadioSize(nativeNode);
221     return panda::JSValueRef::Undefined(vm);
222 }
223 
SetRadioHoverEffect(ArkUIRuntimeCallInfo * runtimeCallInfo)224 ArkUINativeModuleValue RadioBridge::SetRadioHoverEffect(ArkUIRuntimeCallInfo* runtimeCallInfo)
225 {
226     EcmaVM* vm = runtimeCallInfo->GetVM();
227     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
228     Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(0);  //0 is node arguments
229     Local<JSValueRef> valueArg = runtimeCallInfo->GetCallArgRef(1); //1 is Jsvalue
230     auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
231 
232     if (valueArg->IsUndefined() || !valueArg->IsNumber()) {
233         GetArkUINodeModifiers()->getRadioModifier()->resetRadioHoverEffect(nativeNode);
234         return panda::JSValueRef::Undefined(vm);
235     }
236     int32_t intValue = valueArg->Int32Value(vm);
237     GetArkUINodeModifiers()->getRadioModifier()->setRadioHoverEffect(nativeNode, intValue);
238     return panda::JSValueRef::Undefined(vm);
239 }
240 
ResetRadioHoverEffect(ArkUIRuntimeCallInfo * runtimeCallInfo)241 ArkUINativeModuleValue RadioBridge::ResetRadioHoverEffect(ArkUIRuntimeCallInfo* runtimeCallInfo)
242 {
243     EcmaVM* vm = runtimeCallInfo->GetVM();
244     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
245     Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(0); //0 is node arguments
246     auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
247     GetArkUINodeModifiers()->getRadioModifier()->resetRadioHoverEffect(nativeNode);
248     return panda::JSValueRef::Undefined(vm);
249 }
250 
SetRadioPadding(ArkUIRuntimeCallInfo * runtimeCallInfo)251 ArkUINativeModuleValue RadioBridge::SetRadioPadding(ArkUIRuntimeCallInfo *runtimeCallInfo)
252 {
253     EcmaVM *vm = runtimeCallInfo->GetVM();
254     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
255     Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(0);   //0 is node arguments
256     Local<JSValueRef> topArg = runtimeCallInfo->GetCallArgRef(1);    //1 is top arguments
257     Local<JSValueRef> rightArg = runtimeCallInfo->GetCallArgRef(2);  //2 is right arguments
258     Local<JSValueRef> bottomArg = runtimeCallInfo->GetCallArgRef(3); //3 is bottom arguments
259     Local<JSValueRef> leftArg = runtimeCallInfo->GetCallArgRef(4);   //4 is left arguments
260     auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
261 
262     struct ArkUISizeType top = { 0.0, static_cast<int8_t>(DimensionUnit::VP) };
263     struct ArkUISizeType right = { 0.0, static_cast<int8_t>(DimensionUnit::VP) };
264     struct ArkUISizeType bottom = { 0.0, static_cast<int8_t>(DimensionUnit::VP) };
265     struct ArkUISizeType left = { 0.0, static_cast<int8_t>(DimensionUnit::VP) };
266 
267     CalcDimension topDimen(0, DimensionUnit::VP);
268     CalcDimension rightDimen(0, DimensionUnit::VP);
269     CalcDimension bottomDimen(0, DimensionUnit::VP);
270     CalcDimension leftDimen(0, DimensionUnit::VP);
271     ArkTSUtils::ParsePadding(vm, topArg, topDimen, top);
272     ArkTSUtils::ParsePadding(vm, rightArg, rightDimen, right);
273     ArkTSUtils::ParsePadding(vm, bottomArg, bottomDimen, bottom);
274     ArkTSUtils::ParsePadding(vm, leftArg, leftDimen, left);
275     GetArkUINodeModifiers()->getRadioModifier()->setRadioPadding(nativeNode, &top, &right, &bottom, &left);
276 
277     return panda::JSValueRef::Undefined(vm);
278 }
279 
ResetRadioPadding(ArkUIRuntimeCallInfo * runtimeCallInfo)280 ArkUINativeModuleValue RadioBridge::ResetRadioPadding(ArkUIRuntimeCallInfo *runtimeCallInfo)
281 {
282     EcmaVM *vm = runtimeCallInfo->GetVM();
283     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
284     Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(0); //0 is node arguments
285     auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
286     GetArkUINodeModifiers()->getRadioModifier()->resetRadioPadding(nativeNode);
287     return panda::JSValueRef::Undefined(vm);
288 }
289 
SetRadioResponseRegion(ArkUIRuntimeCallInfo * runtimeCallInfo)290 ArkUINativeModuleValue RadioBridge::SetRadioResponseRegion(ArkUIRuntimeCallInfo* runtimeCallInfo)
291 {
292     EcmaVM* vm = runtimeCallInfo->GetVM();
293     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
294     Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(0);   //0 is node arguments
295     Local<JSValueRef> valueArg = runtimeCallInfo->GetCallArgRef(1);  //1 is JsValue
296     Local<JSValueRef> lengthArg = runtimeCallInfo->GetCallArgRef(2); //2 is length arguments
297     auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
298     uint32_t length = static_cast<uint32_t>(lengthArg->Int32Value(vm));
299     ArkUI_Float32 regionArray[length];
300     int32_t regionUnits[length];
301     if (!ArkTSUtils::ParseResponseRegion(vm, valueArg, regionArray, regionUnits, length)) {
302         GetArkUINodeModifiers()->getRadioModifier()->resetRadioResponseRegion(nativeNode);
303         return panda::JSValueRef::Undefined(vm);
304     }
305     GetArkUINodeModifiers()->getRadioModifier()->setRadioResponseRegion(
306         nativeNode, regionArray, regionUnits, length);
307     return panda::JSValueRef::Undefined(vm);
308 }
309 
ResetRadioResponseRegion(ArkUIRuntimeCallInfo * runtimeCallInfo)310 ArkUINativeModuleValue RadioBridge::ResetRadioResponseRegion(ArkUIRuntimeCallInfo* runtimeCallInfo)
311 {
312     EcmaVM* vm = runtimeCallInfo->GetVM();
313     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
314     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0); //0 is node arguments
315     auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
316     GetArkUINodeModifiers()->getRadioModifier()->resetRadioResponseRegion(nativeNode);
317     return panda::JSValueRef::Undefined(vm);
318 }
319 
SetContentModifierBuilder(ArkUIRuntimeCallInfo * runtimeCallInfo)320 ArkUINativeModuleValue RadioBridge::SetContentModifierBuilder(ArkUIRuntimeCallInfo* runtimeCallInfo)
321 {
322     EcmaVM* vm = runtimeCallInfo->GetVM();
323     CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
324     Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
325     Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(NUM_1);
326     auto* frameNode = reinterpret_cast<FrameNode*>(firstArg->ToNativePointer(vm)->Value());
327     if (!secondArg->IsObject(vm)) {
328         RadioModelNG::SetBuilderFunc(frameNode, nullptr);
329         return panda::JSValueRef::Undefined(vm);
330     }
331     panda::CopyableGlobal<panda::ObjectRef> obj(vm, secondArg);
332     RadioModelNG::SetBuilderFunc(frameNode,
333         [vm, frameNode, obj = std::move(obj), containerId = Container::CurrentId()](
334             RadioConfiguration config) -> RefPtr<FrameNode> {
335             ContainerScope scope(containerId);
336             auto context = ArkTSUtils::GetContext(vm);
337             CHECK_EQUAL_RETURN(context->IsUndefined(), true, nullptr);
338             const char* keysOfRadio[] = { "value", "checked", "enabled", "triggerChange"};
339             Local<JSValueRef> valuesOfRadio[] = { panda::StringRef::NewFromUtf8(vm, config.value_.c_str()),
340                 panda::BooleanRef::New(vm, config.checked_), panda::BooleanRef::New(vm, config.enabled_),
341                 panda::FunctionRef::New(vm, JsRadioChangeCallback)};
342             auto radio = panda::ObjectRef::NewWithNamedProperties(vm,
343                 ArraySize(keysOfRadio), keysOfRadio, valuesOfRadio);
344             radio->SetNativePointerFieldCount(vm, 1);
345             radio->SetNativePointerField(vm, 0, static_cast<void*>(frameNode));
346             panda::Local<panda::JSValueRef> params[NUM_2] = { context, radio };
347             LocalScope pandaScope(vm);
348             panda::TryCatch trycatch(vm);
349             auto jsObject = obj.ToLocal();
350             auto makeFunc = jsObject->Get(vm, panda::StringRef::NewFromUtf8(vm, "makeContentModifierNode"));
351             CHECK_EQUAL_RETURN(makeFunc->IsFunction(vm), false, nullptr);
352             panda::Local<panda::FunctionRef> func = makeFunc;
353             auto result = func->Call(vm, jsObject, params, NUM_2);
354             JSNApi::ExecutePendingJob(vm);
355             CHECK_EQUAL_RETURN(result.IsEmpty() || trycatch.HasCaught() || !result->IsObject(vm), true, nullptr);
356             auto resultObj = result->ToObject(vm);
357             panda::Local<panda::JSValueRef> nodeptr =
358                 resultObj->Get(vm, panda::StringRef::NewFromUtf8(vm, RADIO_BUILDER_NODEPTR_OF_UINODE));
359             CHECK_EQUAL_RETURN(nodeptr.IsEmpty() || nodeptr->IsUndefined() || nodeptr->IsNull(), true, nullptr);
360             auto* frameNode = reinterpret_cast<FrameNode*>(nodeptr->ToNativePointer(vm)->Value());
361             CHECK_NULL_RETURN(frameNode, nullptr);
362             return AceType::Claim(frameNode);
363         });
364     return panda::JSValueRef::Undefined(vm);
365 }
366 }
367