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