1 /*
2 * Copyright (c) 2021 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 "napi/n_val.h"
17
18 #include <limits>
19 #include <sstream>
20 #include <string>
21 #include "securec.h"
22 #include "util/log.h"
23 #include "napi/n_class.h"
24
25 namespace OHOS {
26 namespace Rosen {
27 using namespace std;
28
NVal(napi_env nEnv,napi_value nVal=nullptr)29 NVal::NVal(napi_env nEnv, napi_value nVal = nullptr) : env_(nEnv), val_(nVal) {}
30
31 NVal::operator bool() const
32 {
33 return env_ && val_;
34 }
35
TypeIs(napi_valuetype expType) const36 bool NVal::TypeIs(napi_valuetype expType) const
37 {
38 if (!*this) {
39 return false;
40 }
41
42 napi_valuetype valueType;
43 napi_typeof(env_, val_, &valueType);
44
45 if (expType != valueType) {
46 return false;
47 }
48 return true;
49 }
50
IsNull() const51 bool NVal::IsNull() const
52 {
53 if (val_ == nullptr) {
54 return true;
55 }
56 napi_valuetype valueType;
57 napi_typeof(env_, val_, &valueType);
58 if (valueType == napi_null) {
59 return true;
60 }
61 if (valueType == napi_undefined) {
62 return true;
63 }
64 return false;
65 }
66
IsUndefined() const67 bool NVal::IsUndefined() const
68 {
69 if (val_ == nullptr) {
70 return false;
71 }
72 napi_valuetype valueType;
73 napi_typeof(env_, val_, &valueType);
74 if (valueType == napi_undefined) {
75 return true;
76 }
77 return false;
78 }
79
IsBufferArray() const80 bool NVal::IsBufferArray() const
81 {
82 if (val_ == nullptr) {
83 return false;
84 }
85 bool type = false;
86 napi_is_dataview(env_, val_, &type);
87 if (type) {
88 return true;
89 }
90 napi_is_arraybuffer(env_, val_, &type);
91 if (type) {
92 return true;
93 }
94 napi_is_typedarray(env_, val_, &type);
95 if (type) {
96 return true;
97 }
98 return false;
99 }
100
IsArray() const101 tuple<bool, bool> NVal::IsArray() const
102 {
103 bool res = false;
104 napi_status status = napi_is_array(env_, val_, &res);
105 return make_tuple(status == napi_ok, res);
106 }
107
ToUTF8String() const108 tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF8String() const
109 {
110 napi_valuetype valueType;
111 napi_typeof(env_, val_, &valueType);
112 if (valueType == napi_null) {
113 unique_ptr<char[]> str = make_unique<char[]>(1);
114 str[0] = '\0';
115 return {true, move(str), 0};
116 } else if (valueType != napi_string) {
117 return {false, nullptr, 0};
118 }
119 size_t strLen = 0;
120 napi_status status = napi_get_value_string_utf8(env_, val_, nullptr, -1, &strLen);
121 if (status != napi_ok) {
122 return {false, nullptr, 0};
123 }
124
125 size_t bufLen = strLen + 1;
126 unique_ptr<char[]> str = make_unique<char[]>(bufLen);
127 status = napi_get_value_string_utf8(env_, val_, str.get(), bufLen, &strLen);
128 return make_tuple(status == napi_ok, move(str), strLen);
129 }
130
ToUTF16String() const131 tuple<bool, unique_ptr<char[]>, size_t> NVal::ToUTF16String() const
132 {
133 #ifdef FILE_SUBSYSTEM_DEV_ON_PC
134 size_t strLen = 0;
135 napi_status status = napi_get_value_string_utf16(env_, val_, nullptr, -1, &strLen);
136 if (status != napi_ok) {
137 return { false, nullptr, 0 };
138 }
139
140 auto str = make_unique<char16_t[]>(++strLen);
141 status = napi_get_value_string_utf16(env_, val_, str.get(), strLen, nullptr);
142 if (status != napi_ok) {
143 return { false, nullptr, 0 };
144 }
145
146 strLen = reinterpret_cast<char *>(str.get() + strLen) - reinterpret_cast<char *>(str.get());
147 auto strRet = unique_ptr<char[]>(reinterpret_cast<char *>(str.release()));
148 return { true, move(strRet), strLen };
149 #else
150 // Note that quickjs doesn't support utf16
151 return ToUTF8String();
152 #endif
153 }
154
ToPointer() const155 tuple<bool, void *> NVal::ToPointer() const
156 {
157 void *res = nullptr;
158 napi_status status = napi_get_value_external(env_, val_, &res);
159 return make_tuple(status == napi_ok, res);
160 }
161
IsTypeArray() const162 tuple<bool, bool> NVal::IsTypeArray() const
163 {
164 bool res = false;
165 napi_status status = napi_is_typedarray(env_, val_, &res);
166 return make_tuple(status == napi_ok, res);
167 }
168
IsDataView() const169 bool NVal::IsDataView() const
170 {
171 bool res = false;
172 napi_status status = napi_is_dataview(env_, val_, &res);
173 return ((status == napi_ok) && res);
174 }
175
ToBool() const176 tuple<bool, bool> NVal::ToBool() const
177 {
178 bool flag = false;
179 if (IsNull()) {
180 return make_tuple(true, flag);
181 }
182 napi_status status = napi_get_value_bool(env_, val_, &flag);
183 return make_tuple(status == napi_ok, flag);
184 }
185
ToDouble() const186 tuple<bool, double> NVal::ToDouble() const
187 {
188 double res = 0.0;
189 napi_status status = napi_get_value_double(env_, val_, &res);
190 return make_tuple(status == napi_ok, res);
191 }
192
ToFloat() const193 tuple<bool, GLfloat> NVal::ToFloat() const
194 {
195 if (IsUndefined()) {
196 float f = 0;
197 memset_s(&f, sizeof(f), 0xff, sizeof(f));
198 return make_tuple(true, f);
199 }
200 if (IsNull()) {
201 return make_tuple(true, 0);
202 }
203 double res = 0.0;
204 napi_status status = napi_get_value_double(env_, val_, &res);
205 return make_tuple(status == napi_ok, static_cast<GLfloat>(res));
206 }
207
ToInt32() const208 tuple<bool, int32_t> NVal::ToInt32() const
209 {
210 int32_t res = 0;
211 if (IsNull()) {
212 return make_tuple(true, res);
213 }
214 napi_status status = napi_get_value_int32(env_, val_, &res);
215 return make_tuple(status == napi_ok, res);
216 }
217
ToUint32() const218 tuple<bool, uint32_t> NVal::ToUint32() const
219 {
220 uint32_t res = 0;
221 if (IsNull()) {
222 return make_tuple(true, res);
223 }
224 napi_status status = napi_get_value_uint32(env_, val_, &res);
225 return make_tuple(status == napi_ok, res);
226 }
227
ToInt64() const228 tuple<bool, int64_t> NVal::ToInt64() const
229 {
230 int64_t res = 0;
231 if (IsNull()) {
232 return make_tuple(true, res);
233 }
234 napi_status status = napi_get_value_int64(env_, val_, &res);
235 return make_tuple(status == napi_ok, res);
236 }
237
ToGLsizei() const238 tuple<bool, GLsizei> NVal::ToGLsizei() const
239 {
240 int64_t res = 0;
241 if (IsNull()) {
242 return make_tuple(true, res);
243 }
244 napi_status status = napi_get_value_int64(env_, val_, &res);
245 return make_tuple(status == napi_ok, static_cast<GLsizei>(res));
246 }
247
ToGLenum() const248 tuple<bool, GLenum> NVal::ToGLenum() const
249 {
250 int64_t res = 0;
251 napi_valuetype valueType;
252 napi_typeof(env_, val_, &valueType);
253 if (valueType == napi_null) {
254 return make_tuple(true, static_cast<GLenum>(res));
255 }
256 napi_status status = napi_get_value_int64(env_, val_, &res);
257 return make_tuple(status == napi_ok, static_cast<GLenum>(res));
258 }
259
ToArraybuffer() const260 tuple<bool, void *, size_t> NVal::ToArraybuffer() const
261 {
262 void *buf = nullptr;
263 size_t bufLen = 0;
264 bool status = napi_get_arraybuffer_info(env_, val_, &buf, &bufLen);
265 return make_tuple(status == napi_ok, buf, bufLen);
266 }
267
ToTypedArray() const268 tuple<bool, napi_typedarray_type, void *, size_t> NVal::ToTypedArray() const
269 {
270 napi_typedarray_type type;
271 napi_value in_array_buffer = nullptr;
272 size_t byte_offset;
273 size_t length;
274 void *data = nullptr;
275 napi_status status = napi_get_typedarray_info(env_, val_, &type, &length, (void **) &data, &in_array_buffer,
276 &byte_offset);
277 return make_tuple(status == napi_ok, type, data, length);
278 }
279
ToDataview() const280 tuple<bool, void *, size_t> NVal::ToDataview() const
281 {
282 size_t bufLen = 0;
283 void *buf = nullptr;
284 napi_value arraybuffer = nullptr;
285 size_t byteoff = 0;
286 bool status = napi_get_dataview_info(env_, val_, &bufLen, &buf, &arraybuffer, &byteoff);
287 return make_tuple(status == napi_ok, buf, bufLen);
288 }
289
ToTypedArrayInfo() const290 tuple<bool, void *, size_t, size_t, napi_typedarray_type> NVal::ToTypedArrayInfo() const
291 {
292 napi_typedarray_type type;
293 napi_value in_array_buffer = nullptr;
294 size_t byte_offset;
295 size_t length;
296 void *data = nullptr;
297 napi_status status =
298 napi_get_typedarray_info(env_, val_, &type, &length, (void **)&data, &in_array_buffer, &byte_offset);
299 return make_tuple(status == napi_ok, data, length, byte_offset, type);
300 }
301
HasProp(string propName) const302 bool NVal::HasProp(string propName) const
303 {
304 bool res = false;
305
306 if (!env_ || !val_ || !TypeIs(napi_object)) {
307 return false;
308 }
309
310 napi_status status = napi_has_named_property(env_, val_, propName.c_str(), &res);
311 return (status == napi_ok) && res;
312 }
313
GetProp(string propName) const314 NVal NVal::GetProp(string propName) const
315 {
316 if (!HasProp(propName)) {
317 return {env_, nullptr};
318 }
319 napi_value prop = nullptr;
320 napi_status status = napi_get_named_property(env_, val_, propName.c_str(), &prop);
321 if (status != napi_ok) {
322 return {env_, nullptr};
323 }
324 return NVal(env_, prop);
325 }
326
AddProp(vector<napi_property_descriptor> && propVec) const327 bool NVal::AddProp(vector<napi_property_descriptor> &&propVec) const
328 {
329 if (!TypeIs(napi_valuetype::napi_object)) {
330 return false;
331 }
332 napi_status status = napi_define_properties(env_, val_, propVec.size(), propVec.data());
333 if (status != napi_ok) {
334 return false;
335 }
336 return true;
337 }
338
AddProp(string propName,napi_value val) const339 bool NVal::AddProp(string propName, napi_value val) const
340 {
341 if (!TypeIs(napi_valuetype::napi_object) || HasProp(propName)) {
342 return false;
343 }
344
345 napi_status status = napi_set_named_property(env_, val_, propName.c_str(), val);
346 if (status != napi_ok) {
347 return false;
348 }
349 return true;
350 }
351
CreateUndefined(napi_env env)352 NVal NVal::CreateUndefined(napi_env env)
353 {
354 napi_value res = nullptr;
355 napi_get_undefined(env, &res);
356 return {env, res};
357 }
358
CreateNull(napi_env env)359 NVal NVal::CreateNull(napi_env env)
360 {
361 napi_value res = nullptr;
362 napi_get_null(env, &res);
363 return {env, res};
364 }
365
CreateInt64(napi_env env,int64_t val)366 NVal NVal::CreateInt64(napi_env env, int64_t val)
367 {
368 napi_value res = nullptr;
369 napi_create_int64(env, val, &res);
370 return {env, res};
371 }
372
CreateObject(napi_env env)373 NVal NVal::CreateObject(napi_env env)
374 {
375 napi_value res = nullptr;
376 napi_create_object(env, &res);
377 return {env, res};
378 }
379
CreateBool(napi_env env,bool val)380 NVal NVal::CreateBool(napi_env env, bool val)
381 {
382 napi_value res = nullptr;
383 napi_get_boolean(env, val, &res);
384 return {env, res};
385 }
386
CreateUTF8String(napi_env env,std::string str)387 NVal NVal::CreateUTF8String(napi_env env, std::string str)
388 {
389 napi_value res = nullptr;
390 napi_create_string_utf8(env, str.c_str(), str.length(), &res);
391 return {env, res};
392 }
393
CreateUint8Array(napi_env env,void * buf,size_t bufLen)394 NVal NVal::CreateUint8Array(napi_env env, void *buf, size_t bufLen)
395 {
396 napi_value output_buffer = nullptr;
397 napi_create_external_arraybuffer(env, buf, bufLen,
398 [](napi_env env, void *finalize_data, void *finalize_hint) { free(finalize_data); },
399 NULL, &output_buffer);
400 napi_value output_array = nullptr;
401 napi_create_typedarray(env, napi_uint8_array, bufLen, output_buffer, 0, &output_array);
402 return {env, output_array};
403 }
404
CreateDouble(napi_env env,double val)405 NVal NVal::CreateDouble(napi_env env, double val)
406 {
407 napi_value res = nullptr;
408 napi_create_double(env, val, &res);
409 return {env, res};
410 }
411
DeclareNapiProperty(const char * name,napi_value val)412 napi_property_descriptor NVal::DeclareNapiProperty(const char *name, napi_value val)
413 {
414 return {(name), nullptr, nullptr, nullptr, nullptr, val, napi_default, nullptr};
415 }
416
DeclareNapiStaticProperty(const char * name,napi_value val)417 napi_property_descriptor NVal::DeclareNapiStaticProperty(const char *name, napi_value val)
418 {
419 return {(name), nullptr, nullptr, nullptr, nullptr, val, napi_static, nullptr};
420 }
421
DeclareNapiFunction(const char * name,napi_callback func)422 napi_property_descriptor NVal::DeclareNapiFunction(const char *name, napi_callback func)
423 {
424 return {(name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, nullptr};
425 }
426
DeclareNapiStaticFunction(const char * name,napi_callback func)427 napi_property_descriptor NVal::DeclareNapiStaticFunction(const char *name, napi_callback func)
428 {
429 return {(name), nullptr, (func), nullptr, nullptr, nullptr, napi_static, nullptr};
430 }
431
DeclareNapiGetter(const char * name,napi_callback getter)432 napi_property_descriptor NVal::DeclareNapiGetter(const char *name, napi_callback getter)
433 {
434 return {(name), nullptr, nullptr, (getter), nullptr, nullptr, napi_default, nullptr};
435 }
436
DeclareNapiSetter(const char * name,napi_callback setter)437 napi_property_descriptor NVal::DeclareNapiSetter(const char *name, napi_callback setter)
438 {
439 return {(name), nullptr, nullptr, nullptr, (setter), nullptr, napi_default, nullptr};
440 }
441
DeclareNapiGetterSetter(const char * name,napi_callback getter,napi_callback setter)442 napi_property_descriptor NVal::DeclareNapiGetterSetter(const char *name, napi_callback getter, napi_callback setter)
443 {
444 return {(name), nullptr, nullptr, (getter), (setter), nullptr, napi_default, nullptr};
445 }
446 } // namespace Rosen
447 } // namespace OHOS
448