1 /**
2 * Copyright (c) 2021-2025 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 #ifndef PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_JS_CONVERT_STDLIB_H
17 #define PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_JS_CONVERT_STDLIB_H
18
19 #include "js_convert_base.h"
20
21 namespace ark::ets::interop::js {
22
23 JSCONVERT_DEFINE_TYPE(StdlibBoolean, EtsObject *);
JSCONVERT_WRAP(StdlibBoolean)24 JSCONVERT_WRAP(StdlibBoolean)
25 {
26 auto *val = reinterpret_cast<EtsBoxPrimitive<EtsBoolean> *>(etsVal);
27 napi_value jsVal;
28 NAPI_CHECK_FATAL(napi_get_boolean(env, val->GetValue(), &jsVal));
29 return jsVal;
30 }
JSCONVERT_UNWRAP(StdlibBoolean)31 JSCONVERT_UNWRAP(StdlibBoolean)
32 {
33 napi_value result = jsVal;
34 napi_valuetype valueType = GetValueType(env, jsVal);
35 if (valueType == napi_object && !GetValueByValueOf(env, jsVal, CONSTRUCTOR_NAME_BOOLEAN, &result)) {
36 TypeCheckFailed();
37 return {};
38 }
39 if (UNLIKELY(GetValueType(env, result) != napi_boolean)) {
40 TypeCheckFailed();
41 return {};
42 }
43 bool val;
44 NAPI_CHECK_FATAL(napi_get_value_bool(env, result, &val));
45 return EtsBoxPrimitive<EtsBoolean>::Create(EtsCoroutine::GetCurrent(), static_cast<EtsBoolean>(val));
46 }
47
48 JSCONVERT_DEFINE_TYPE(StdlibByte, EtsObject *);
JSCONVERT_WRAP(StdlibByte)49 JSCONVERT_WRAP(StdlibByte)
50 {
51 auto *val = reinterpret_cast<EtsBoxPrimitive<EtsByte> *>(etsVal);
52 napi_value jsVal;
53 NAPI_CHECK_FATAL(napi_create_int32(env, val->GetValue(), &jsVal));
54 return jsVal;
55 }
JSCONVERT_UNWRAP(StdlibByte)56 JSCONVERT_UNWRAP(StdlibByte)
57 {
58 napi_value result = jsVal;
59 napi_valuetype valueType = GetValueType(env, jsVal);
60 if (valueType == napi_object && !GetValueByValueOf(env, jsVal, CONSTRUCTOR_NAME_NUMBER, &result)) {
61 TypeCheckFailed();
62 return {};
63 }
64 if (UNLIKELY(GetValueType(env, result) != napi_number)) {
65 TypeCheckFailed();
66 return {};
67 }
68 int32_t val;
69 NAPI_CHECK_FATAL(napi_get_value_int32(env, result, &val));
70 return EtsBoxPrimitive<EtsByte>::Create(EtsCoroutine::GetCurrent(), val);
71 }
72
GetValueFromNumber(napi_env env,napi_value & jsVal,EtsChar & val)73 static bool GetValueFromNumber(napi_env env, napi_value &jsVal, EtsChar &val)
74 {
75 napi_valuetype valueType = GetValueType(env, jsVal);
76 napi_value result = jsVal;
77 if (valueType == napi_object && !GetValueByValueOf(env, jsVal, CONSTRUCTOR_NAME_NUMBER, &result)) {
78 return false;
79 }
80 napi_valuetype resultType = GetValueType(env, result);
81 if (resultType != napi_number) {
82 return false;
83 }
84 int32_t ival;
85 NAPI_CHECK_FATAL(napi_get_value_int32(env, result, &ival));
86 if (ival < 0 || ival > std::numeric_limits<EtsChar>::max()) {
87 return false;
88 }
89 val = static_cast<uint16_t>(ival);
90 return true;
91 }
92
GetValueFromString(napi_env env,napi_value & jsVal,EtsChar & val)93 static bool GetValueFromString(napi_env env, napi_value &jsVal, EtsChar &val)
94 {
95 napi_valuetype valueType = GetValueType(env, jsVal);
96 napi_value result = jsVal;
97 if (valueType == napi_object && !GetValueByValueOf(env, jsVal, CONSTRUCTOR_NAME_STRING, &result)) {
98 return false;
99 }
100 napi_valuetype resultType = GetValueType(env, result);
101 if (resultType != napi_string) {
102 return false;
103 }
104 size_t len = 0;
105 NAPI_CHECK_FATAL(napi_get_value_string_utf16(env, result, nullptr, 0, &len));
106 if (len != 1) {
107 return false;
108 }
109 const size_t charArrayLength = 2U;
110 std::array<char16_t, charArrayLength> cval {};
111 NAPI_CHECK_FATAL(napi_get_value_string_utf16(env, result, cval.data(), charArrayLength, &len));
112 val = static_cast<EtsChar>(cval[0]);
113 return true;
114 }
115
116 JSCONVERT_DEFINE_TYPE(StdlibChar, EtsObject *);
JSCONVERT_WRAP(StdlibChar)117 JSCONVERT_WRAP(StdlibChar)
118 {
119 auto *val = reinterpret_cast<EtsBoxPrimitive<EtsChar> *>(etsVal);
120 napi_value jsVal;
121 std::array<char16_t, 2U> str = {static_cast<char16_t>(val->GetValue()), 0};
122 NAPI_CHECK_FATAL(napi_create_string_utf16(env, str.data(), 1, &jsVal));
123 return jsVal;
124 }
JSCONVERT_UNWRAP(StdlibChar)125 JSCONVERT_UNWRAP(StdlibChar)
126 {
127 EtsChar val = 0;
128 if (GetValueFromNumber(env, jsVal, val) || GetValueFromString(env, jsVal, val)) {
129 return EtsBoxPrimitive<EtsChar>::Create(EtsCoroutine::GetCurrent(), static_cast<EtsChar>(val));
130 }
131 TypeCheckFailed();
132 return {};
133 }
134
135 JSCONVERT_DEFINE_TYPE(StdlibShort, EtsObject *);
JSCONVERT_WRAP(StdlibShort)136 JSCONVERT_WRAP(StdlibShort)
137 {
138 auto *val = reinterpret_cast<EtsBoxPrimitive<EtsShort> *>(etsVal);
139 napi_value jsVal;
140 NAPI_CHECK_FATAL(napi_create_int32(env, val->GetValue(), &jsVal));
141 return jsVal;
142 }
JSCONVERT_UNWRAP(StdlibShort)143 JSCONVERT_UNWRAP(StdlibShort)
144 {
145 napi_value result = jsVal;
146 napi_valuetype valueType = GetValueType(env, jsVal);
147 if (valueType == napi_object && !GetValueByValueOf(env, jsVal, CONSTRUCTOR_NAME_NUMBER, &result)) {
148 TypeCheckFailed();
149 return {};
150 }
151 if (UNLIKELY(GetValueType(env, result) != napi_number)) {
152 TypeCheckFailed();
153 return {};
154 }
155 int32_t val;
156 NAPI_CHECK_FATAL(napi_get_value_int32(env, result, &val));
157 return EtsBoxPrimitive<EtsShort>::Create(EtsCoroutine::GetCurrent(), static_cast<EtsShort>(val));
158 }
159
160 JSCONVERT_DEFINE_TYPE(StdlibInt, EtsObject *);
JSCONVERT_WRAP(StdlibInt)161 JSCONVERT_WRAP(StdlibInt)
162 {
163 auto *val = reinterpret_cast<EtsBoxPrimitive<EtsInt> *>(etsVal);
164 napi_value jsVal;
165 NAPI_CHECK_FATAL(napi_create_int32(env, val->GetValue(), &jsVal));
166 return jsVal;
167 }
JSCONVERT_UNWRAP(StdlibInt)168 JSCONVERT_UNWRAP(StdlibInt)
169 {
170 napi_value result = jsVal;
171 napi_valuetype valueType = GetValueType(env, jsVal);
172 if (valueType == napi_object && !GetValueByValueOf(env, jsVal, CONSTRUCTOR_NAME_NUMBER, &result)) {
173 TypeCheckFailed();
174 return {};
175 }
176 if (UNLIKELY(GetValueType(env, result) != napi_number)) {
177 TypeCheckFailed();
178 return {};
179 }
180 EtsLong val;
181 NAPI_CHECK_FATAL(napi_get_value_int64(env, result, &val));
182 return EtsBoxPrimitive<EtsInt>::Create(EtsCoroutine::GetCurrent(), static_cast<EtsInt>(val));
183 }
184
185 JSCONVERT_DEFINE_TYPE(StdlibLong, EtsObject *);
JSCONVERT_WRAP(StdlibLong)186 JSCONVERT_WRAP(StdlibLong)
187 {
188 auto *val = reinterpret_cast<EtsBoxPrimitive<EtsLong> *>(etsVal);
189 napi_value jsVal;
190 NAPI_CHECK_FATAL(napi_create_int64(env, val->GetValue(), &jsVal));
191 return jsVal;
192 }
JSCONVERT_UNWRAP(StdlibLong)193 JSCONVERT_UNWRAP(StdlibLong)
194 {
195 napi_value result = jsVal;
196 napi_valuetype valueType = GetValueType(env, jsVal);
197 if (valueType == napi_object && !GetValueByValueOf(env, jsVal, CONSTRUCTOR_NAME_NUMBER, &result)) {
198 TypeCheckFailed();
199 return {};
200 }
201 if (UNLIKELY(GetValueType(env, result) != napi_number)) {
202 TypeCheckFailed();
203 return {};
204 }
205 EtsLong val;
206 NAPI_CHECK_FATAL(napi_get_value_int64(env, result, &val));
207 return EtsBoxPrimitive<EtsLong>::Create(EtsCoroutine::GetCurrent(), val);
208 }
209
210 JSCONVERT_DEFINE_TYPE(StdlibFloat, EtsObject *);
JSCONVERT_WRAP(StdlibFloat)211 JSCONVERT_WRAP(StdlibFloat)
212 {
213 auto *val = reinterpret_cast<EtsBoxPrimitive<EtsFloat> *>(etsVal);
214 napi_value jsVal;
215 NAPI_CHECK_FATAL(napi_create_double(env, static_cast<double>(val->GetValue()), &jsVal));
216 return jsVal;
217 }
JSCONVERT_UNWRAP(StdlibFloat)218 JSCONVERT_UNWRAP(StdlibFloat)
219 {
220 napi_value result = jsVal;
221 napi_valuetype valueType = GetValueType(env, jsVal);
222 if (valueType == napi_object && !GetValueByValueOf(env, jsVal, CONSTRUCTOR_NAME_NUMBER, &result)) {
223 TypeCheckFailed();
224 return {};
225 }
226 if (UNLIKELY(GetValueType(env, result) != napi_number)) {
227 TypeCheckFailed();
228 return {};
229 }
230 double val;
231 NAPI_CHECK_FATAL(napi_get_value_double(env, result, &val));
232 auto fval = static_cast<EtsFloat>(val);
233 return EtsBoxPrimitive<EtsFloat>::Create(EtsCoroutine::GetCurrent(), fval);
234 }
235
236 JSCONVERT_DEFINE_TYPE(StdlibDouble, EtsObject *);
JSCONVERT_WRAP(StdlibDouble)237 JSCONVERT_WRAP(StdlibDouble)
238 {
239 auto *val = reinterpret_cast<EtsBoxPrimitive<EtsDouble> *>(etsVal);
240 napi_value jsVal;
241 NAPI_CHECK_FATAL(napi_create_double(env, val->GetValue(), &jsVal));
242 return jsVal;
243 }
JSCONVERT_UNWRAP(StdlibDouble)244 JSCONVERT_UNWRAP(StdlibDouble)
245 {
246 napi_value result = jsVal;
247 napi_valuetype valueType = GetValueType(env, jsVal);
248 if (valueType == napi_object && !GetValueByValueOf(env, jsVal, CONSTRUCTOR_NAME_NUMBER, &result)) {
249 TypeCheckFailed();
250 return {};
251 }
252 if (UNLIKELY(GetValueType(env, result) != napi_number)) {
253 TypeCheckFailed();
254 return {};
255 }
256 EtsDouble val;
257 NAPI_CHECK_FATAL(napi_get_value_double(env, result, &val));
258 return EtsBoxPrimitive<EtsDouble>::Create(EtsCoroutine::GetCurrent(), val);
259 }
260
261 } // namespace ark::ets::interop::js
262
263 #endif // !PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_JS_CONVERT_STDLIB_H
264