1 /*
2 * Copyright (c) 2024 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_value.h"
17
18 #include <string>
19
20 #include "app_log_wrapper.h"
21 #include "napi_business_error.h"
22
23 namespace OHOS {
24 namespace AppExecFwk {
25 namespace LIBZIP {
26 using namespace std;
27
NapiValue(napi_env nEnv,napi_value NapiValue=nullptr)28 NapiValue::NapiValue(napi_env nEnv, napi_value NapiValue = nullptr) : env_(nEnv), val_(NapiValue)
29 {}
30
31 NapiValue::operator bool() const
32 {
33 return env_ && val_;
34 }
35
TypeIs(napi_valuetype expType) const36 bool NapiValue::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 if (expType != valueType) {
45 return false;
46 }
47
48 return true;
49 }
50
TypeIsError(bool checkErrno) const51 bool NapiValue::TypeIsError(bool checkErrno) const
52 {
53 if (!*this) {
54 return false;
55 }
56
57 bool res = false;
58 napi_is_error(env_, val_, &res);
59
60 return res;
61 }
62
ToUTF8String() const63 tuple<bool, unique_ptr<char[]>, size_t> NapiValue::ToUTF8String() const
64 {
65 size_t strLen = 0;
66 napi_status status = napi_get_value_string_utf8(env_, val_, nullptr, -1, &strLen);
67 if (status != napi_ok) {
68 return {false, nullptr, 0};
69 }
70
71 size_t bufLen = strLen + 1;
72 unique_ptr<char[]> str = make_unique<char[]>(bufLen);
73 status = napi_get_value_string_utf8(env_, val_, str.get(), bufLen, &strLen);
74 return make_tuple(status == napi_ok, move(str), strLen);
75 }
76
ToUTF8String(string_view defaultValue) const77 tuple<bool, unique_ptr<char[]>, size_t> NapiValue::ToUTF8String(string_view defaultValue) const
78 {
79 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
80 auto str = make_unique<char[]>(defaultValue.size() + 1);
81 copy(defaultValue.begin(), defaultValue.end(), str.get());
82 return make_tuple(true, move(str), defaultValue.size());
83 }
84 return ToUTF8String();
85 }
86
ToUTF16String() const87 tuple<bool, unique_ptr<char[]>, size_t> NapiValue::ToUTF16String() const
88 {
89 #ifdef FILE_SUBSYSTEM_DEBUG_LOCAL
90 size_t strLen = 0;
91 napi_status status = napi_get_value_string_utf16(env_, val_, nullptr, -1, &strLen);
92 if (status != napi_ok) {
93 return {false, nullptr, 0};
94 }
95
96 auto str = make_unique<char16_t[]>(++strLen);
97 status = napi_get_value_string_utf16(env_, val_, str.get(), strLen, nullptr);
98 if (status != napi_ok) {
99 return {false, nullptr, 0};
100 }
101
102 strLen = reinterpret_cast<char *>(str.get() + strLen) - reinterpret_cast<char *>(str.get());
103 auto strRet = unique_ptr<char[]>(reinterpret_cast<char *>(str.release()));
104 return {true, move(strRet), strLen};
105 #else
106 // Note that quickjs doesn't support utf16
107 return ToUTF8String();
108 #endif
109 }
110
ToPointer() const111 tuple<bool, void *> NapiValue::ToPointer() const
112 {
113 void *res = nullptr;
114 napi_status status = napi_get_value_external(env_, val_, &res);
115 return make_tuple(status == napi_ok, res);
116 }
117
ToBool() const118 tuple<bool, bool> NapiValue::ToBool() const
119 {
120 bool flag = false;
121 napi_status status = napi_get_value_bool(env_, val_, &flag);
122 return make_tuple(status == napi_ok, flag);
123 }
124
ToBool(bool defaultValue) const125 tuple<bool, bool> NapiValue::ToBool(bool defaultValue) const
126 {
127 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
128 return make_tuple(true, defaultValue);
129 }
130 return ToBool();
131 }
132
ToInt32() const133 tuple<bool, int32_t> NapiValue::ToInt32() const
134 {
135 int32_t res = 0;
136 napi_status status = napi_get_value_int32(env_, val_, &res);
137 return make_tuple(status == napi_ok, res);
138 }
139
ToInt32(int32_t defaultValue) const140 tuple<bool, int32_t> NapiValue::ToInt32(int32_t defaultValue) const
141 {
142 if (TypeIs(napi_undefined) || TypeIs(napi_function)) {
143 return make_tuple(true, defaultValue);
144 }
145 return ToInt32();
146 }
147
ToInt64() const148 tuple<bool, int64_t> NapiValue::ToInt64() const
149 {
150 int64_t res = 0;
151 napi_status status = napi_get_value_int64(env_, val_, &res);
152 return make_tuple(status == napi_ok, res);
153 }
154
ToInt64(int64_t defaultValue) const155 tuple<bool, int64_t> NapiValue::ToInt64(int64_t defaultValue) const
156 {
157 if (TypeIs(napi_undefined) || TypeIs(napi_function) || TypeIs(napi_null)) {
158 return make_tuple(true, defaultValue);
159 }
160 return ToInt64();
161 }
162
ToUint32() const163 tuple<bool, uint32_t> NapiValue::ToUint32() const
164 {
165 uint32_t res = 0;
166 napi_status status = napi_get_value_uint32(env_, val_, &res);
167 return make_tuple(status == napi_ok, res);
168 }
169
ToDouble() const170 tuple<bool, double> NapiValue::ToDouble() const
171 {
172 double res = 0;
173 napi_status status = napi_get_value_double(env_, val_, &res);
174 return make_tuple(status == napi_ok, res);
175 }
176
ToUint64() const177 tuple<bool, uint64_t, bool> NapiValue::ToUint64() const
178 {
179 uint64_t res = 0;
180 bool lossless = false;
181 napi_status status = napi_get_value_bigint_uint64(env_, val_, &res, &lossless);
182 return make_tuple(status == napi_ok, res, lossless);
183 }
184
ToStringArray()185 tuple<bool, vector<string>, uint32_t> NapiValue::ToStringArray()
186 {
187 uint32_t size;
188 napi_status status = napi_get_array_length(env_, val_, &size);
189 vector<string> stringArray;
190 napi_value result;
191 for (uint32_t i = 0; i < size; i++) {
192 status = napi_get_element(env_, val_, i, &result);
193 auto [succ, str, ignore] = NapiValue(env_, result).ToUTF8String();
194 stringArray.push_back(string(str.get()));
195 }
196 return make_tuple(status == napi_ok, stringArray, size);
197 }
198
ToArrayBuffer() const199 tuple<bool, void *, size_t> NapiValue::ToArrayBuffer() const
200 {
201 void *buf = nullptr;
202 size_t bufLen = 0;
203 bool status = napi_get_arraybuffer_info(env_, val_, &buf, &bufLen);
204 return make_tuple(status == napi_ok, buf, bufLen);
205 }
206
ToTypedArray() const207 tuple<bool, void *, size_t> NapiValue::ToTypedArray() const
208 {
209 napi_typedarray_type type;
210 napi_value in_array_buffer = nullptr;
211 size_t byteOffset;
212 size_t length;
213 void *data = nullptr;
214 napi_status status =
215 napi_get_typedarray_info(env_, val_, &type, &length, (void **)&data, &in_array_buffer, &byteOffset);
216 return make_tuple(status == napi_ok, data, length);
217 }
218
HasProp(const string & propName) const219 bool NapiValue::HasProp(const string& propName) const
220 {
221 bool res = false;
222
223 if (!env_ || !val_ || !TypeIs(napi_object)) {
224 return false;
225 }
226
227 napi_status status = napi_has_named_property(env_, val_, propName.c_str(), &res);
228 return (status == napi_ok) && res;
229 }
230
GetProp(const string & propName) const231 NapiValue NapiValue::GetProp(const string &propName) const
232 {
233 if (!HasProp(propName)) {
234 return {env_, nullptr};
235 }
236
237 napi_value prop = nullptr;
238 napi_status status = napi_get_named_property(env_, val_, propName.c_str(), &prop);
239 if (status != napi_ok) {
240 return {env_, nullptr};
241 }
242
243 return NapiValue(env_, prop);
244 }
245
AddProp(vector<napi_property_descriptor> && propVec) const246 bool NapiValue::AddProp(vector<napi_property_descriptor> &&propVec) const
247 {
248 if (!TypeIs(napi_valuetype::napi_object)) {
249 APP_LOGE("INNER BUG. Prop should only be added to objects");
250 return false;
251 }
252
253 napi_status status = napi_define_properties(env_, val_, propVec.size(), propVec.data());
254 if (status != napi_ok) {
255 APP_LOGE("INNER BUG. Cannot define properties because of %{public}d", status);
256 return false;
257 }
258
259 return true;
260 }
261
AddProp(const string & propName,napi_value val) const262 bool NapiValue::AddProp(const string &propName, napi_value val) const
263 {
264 if (!TypeIs(napi_valuetype::napi_object) || HasProp(propName)) {
265 APP_LOGE("INNER BUG. Prop should only be added to objects");
266 return false;
267 }
268
269 napi_status status = napi_set_named_property(env_, val_, propName.c_str(), val);
270 if (status != napi_ok) {
271 APP_LOGE("INNER BUG. Cannot set named property because of %{public}d", status);
272 return false;
273 }
274
275 return true;
276 }
277
CreateUndefined(napi_env env)278 NapiValue NapiValue::CreateUndefined(napi_env env)
279 {
280 napi_value res = nullptr;
281 napi_get_undefined(env, &res);
282 return {env, res};
283 }
284
CreateBigInt64(napi_env env,int64_t val)285 NapiValue NapiValue::CreateBigInt64(napi_env env, int64_t val)
286 {
287 napi_value res = nullptr;
288 napi_create_bigint_int64(env, val, &res);
289 return {env, res};
290 }
291
CreateInt64(napi_env env,int64_t val)292 NapiValue NapiValue::CreateInt64(napi_env env, int64_t val)
293 {
294 napi_value res = nullptr;
295 napi_create_int64(env, val, &res);
296 return {env, res};
297 }
298
CreateUint64(napi_env env,uint64_t val)299 NapiValue NapiValue::CreateUint64(napi_env env, uint64_t val)
300 {
301 napi_value res = nullptr;
302 napi_create_bigint_uint64(env, val, &res);
303 return {env, res};
304 }
305
CreateInt32(napi_env env,int32_t val)306 NapiValue NapiValue::CreateInt32(napi_env env, int32_t val)
307 {
308 napi_value res = nullptr;
309 napi_create_int32(env, val, &res);
310 return {env, res};
311 }
312
CreateUint32(napi_env env,uint32_t val)313 NapiValue NapiValue::CreateUint32(napi_env env, uint32_t val)
314 {
315 napi_value res = nullptr;
316 napi_create_uint32(env, val, &res);
317 return {env, res};
318 }
319
CreateObject(napi_env env)320 NapiValue NapiValue::CreateObject(napi_env env)
321 {
322 napi_value res = nullptr;
323 napi_create_object(env, &res);
324 return {env, res};
325 }
326
CreateBool(napi_env env,bool val)327 NapiValue NapiValue::CreateBool(napi_env env, bool val)
328 {
329 napi_value res = nullptr;
330 napi_get_boolean(env, val, &res);
331 return {env, res};
332 }
333
CreateUTF8String(napi_env env,const std::string & str)334 NapiValue NapiValue::CreateUTF8String(napi_env env, const std::string &str)
335 {
336 napi_value res = nullptr;
337 napi_create_string_utf8(env, str.c_str(), str.length(), &res);
338 return {env, res};
339 }
340
CreateUTF8String(napi_env env,const char * str,ssize_t len)341 NapiValue NapiValue::CreateUTF8String(napi_env env, const char *str, ssize_t len)
342 {
343 napi_value res = nullptr;
344 napi_create_string_utf8(env, str, len, &res);
345 return {env, res};
346 }
347
CreateUint8Array(napi_env env,void * buf,size_t bufLen)348 NapiValue NapiValue::CreateUint8Array(napi_env env, void *buf, size_t bufLen)
349 {
350 napi_value output_buffer = nullptr;
351 napi_create_external_arraybuffer(
352 env,
353 buf,
354 bufLen,
355 [](napi_env env, void *finalize_data, void *finalize_hint) { free(finalize_data); },
356 NULL,
357 &output_buffer);
358 napi_value output_array = nullptr;
359 napi_create_typedarray(env, napi_uint8_array, bufLen, output_buffer, 0, &output_array);
360 return {env, output_array};
361 }
362
CreateArrayString(napi_env env,const vector<string> & strs)363 NapiValue NapiValue::CreateArrayString(napi_env env, const vector<string> &strs)
364 {
365 napi_value res = nullptr;
366 napi_create_array(env, &res);
367 for (size_t i = 0; i < strs.size(); i++) {
368 napi_value filename;
369 napi_create_string_utf8(env, strs[i].c_str(), strs[i].length(), &filename);
370 napi_set_element(env, res, i, filename);
371 }
372 return {env, res};
373 }
374
CreateArrayBuffer(napi_env env,size_t len)375 tuple<NapiValue, void *> NapiValue::CreateArrayBuffer(napi_env env, size_t len)
376 {
377 napi_value val;
378 void *buf = nullptr;
379 napi_create_arraybuffer(env, len, &buf, &val);
380 return {{env, val}, {buf}};
381 }
382
CreateInt64Array(napi_env env,const std::vector<int64_t> & int64Array)383 NapiValue NapiValue::CreateInt64Array(napi_env env, const std::vector<int64_t> &int64Array)
384 {
385 napi_value jsArray;
386 napi_create_array(env, &jsArray);
387 for (size_t i = 0; i < int64Array.size(); ++i) {
388 napi_value jsNumber;
389 napi_create_int64(env, int64Array[i], &jsNumber);
390 napi_set_element(env, jsArray, i, jsNumber);
391 }
392
393 return {env, jsArray};
394 }
395
CreateBigUint64Array(napi_env env,const std::vector<uint64_t> & int64Array)396 NapiValue NapiValue::CreateBigUint64Array(napi_env env, const std::vector<uint64_t> &int64Array)
397 {
398 napi_value jsArray;
399 napi_create_array(env, &jsArray);
400 for (size_t i = 0; i < int64Array.size(); ++i) {
401 napi_value jsNumber;
402 napi_create_bigint_uint64(env, int64Array[i], &jsNumber);
403 napi_set_element(env, jsArray, i, jsNumber);
404 }
405
406 return {env, jsArray};
407 }
408
DeclareNapiProperty(const char * name,napi_value val)409 napi_property_descriptor NapiValue::DeclareNapiProperty(const char *name, napi_value val)
410 {
411 return {(name), nullptr, nullptr, nullptr, nullptr, val, napi_default, nullptr};
412 }
413
DeclareNapiStaticProperty(const char * name,napi_value val)414 napi_property_descriptor NapiValue::DeclareNapiStaticProperty(const char *name, napi_value val)
415 {
416 return {(name), nullptr, nullptr, nullptr, nullptr, val, napi_static, nullptr};
417 }
418
DeclareNapiFunction(const char * name,napi_callback func)419 napi_property_descriptor NapiValue::DeclareNapiFunction(const char *name, napi_callback func)
420 {
421 return {(name), nullptr, (func), nullptr, nullptr, nullptr, napi_default, nullptr};
422 }
423
DeclareNapiStaticFunction(const char * name,napi_callback func)424 napi_property_descriptor NapiValue::DeclareNapiStaticFunction(const char *name, napi_callback func)
425 {
426 return {(name), nullptr, (func), nullptr, nullptr, nullptr, napi_static, nullptr};
427 }
428
DeclareNapiGetter(const char * name,napi_callback getter)429 napi_property_descriptor NapiValue::DeclareNapiGetter(const char *name, napi_callback getter)
430 {
431 return {(name), nullptr, nullptr, (getter), nullptr, nullptr, napi_default, nullptr};
432 }
433
DeclareNapiSetter(const char * name,napi_callback setter)434 napi_property_descriptor NapiValue::DeclareNapiSetter(const char *name, napi_callback setter)
435 {
436 return {(name), nullptr, nullptr, nullptr, (setter), nullptr, napi_default, nullptr};
437 }
438
DeclareNapiGetterSetter(const char * name,napi_callback getter,napi_callback setter)439 napi_property_descriptor NapiValue::DeclareNapiGetterSetter(
440 const char* name, napi_callback getter, napi_callback setter)
441 {
442 return { (name), nullptr, nullptr, (getter), (setter), nullptr, napi_default, nullptr };
443 }
444 } // namespace LIBZIP
445 } // namespace AppExecFwk
446 } // namespace OHOS