1 /*
2  * Copyright (c) 2021-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 #include "napi_common_util.h"
16 
17 #include <cstring>
18 
19 #include "hilog_tag_wrapper.h"
20 #include "napi_common_data.h"
21 #include "napi_common_error.h"
22 #include "securec.h"
23 
24 namespace OHOS {
25 namespace AppExecFwk {
IsTypeForNapiValue(napi_env env,napi_value param,napi_valuetype expectType)26 bool IsTypeForNapiValue(napi_env env, napi_value param, napi_valuetype expectType)
27 {
28     TAG_LOGD(AAFwkTag::JSNAPI, "called");
29     napi_valuetype valueType = napi_undefined;
30 
31     if (param == nullptr) {
32         TAG_LOGD(AAFwkTag::JSNAPI, "param is nullptr");
33         return false;
34     }
35 
36     if (napi_typeof(env, param, &valueType) != napi_ok) {
37         return false;
38     }
39 
40     return valueType == expectType;
41 }
42 
IsArrayForNapiValue(napi_env env,napi_value param,uint32_t & arraySize)43 bool IsArrayForNapiValue(napi_env env, napi_value param, uint32_t &arraySize)
44 {
45     TAG_LOGD(AAFwkTag::JSNAPI, "called");
46     bool isArray = false;
47     arraySize = 0;
48 
49     if (napi_is_array(env, param, &isArray) != napi_ok || isArray == false) {
50         return false;
51     }
52 
53     if (napi_get_array_length(env, param, &arraySize) != napi_ok) {
54         TAG_LOGD(AAFwkTag::JSNAPI, "napi_get_array_length is 0");
55         return false;
56     }
57     return true;
58 }
59 
WrapVoidToJS(napi_env env)60 napi_value WrapVoidToJS(napi_env env)
61 {
62     napi_value result = nullptr;
63     NAPI_CALL(env, napi_get_null(env, &result));
64     return result;
65 }
66 
WrapUndefinedToJS(napi_env env)67 napi_value WrapUndefinedToJS(napi_env env)
68 {
69     napi_value result = nullptr;
70     NAPI_CALL(env, napi_get_undefined(env, &result));
71     return result;
72 }
73 
CreateJSObject(napi_env env)74 napi_value CreateJSObject(napi_env env)
75 {
76     napi_value result = nullptr;
77     NAPI_CALL(env, napi_create_object(env, &result));
78     return result;
79 }
80 
WrapInt32ToJS(napi_env env,int32_t value)81 napi_value WrapInt32ToJS(napi_env env, int32_t value)
82 {
83     napi_value result = nullptr;
84     NAPI_CALL(env, napi_create_int32(env, value, &result));
85     return result;
86 }
87 
UnwrapInt32FromJS(napi_env env,napi_value param,int defaultValue)88 int UnwrapInt32FromJS(napi_env env, napi_value param, int defaultValue)
89 {
90     int value = defaultValue;
91     if (napi_get_value_int32(env, param, &value) == napi_ok) {
92         return value;
93     } else {
94         return defaultValue;
95     }
96 }
97 
UnwrapInt32FromJS2(napi_env env,napi_value param,int & value)98 bool UnwrapInt32FromJS2(napi_env env, napi_value param, int &value)
99 {
100     bool result = false;
101     if (napi_get_value_int32(env, param, &value) == napi_ok) {
102         result = true;
103     }
104     return result;
105 }
106 
WrapLongToJS(napi_env env,long value)107 napi_value WrapLongToJS(napi_env env, long value)
108 {
109     napi_value result = nullptr;
110     NAPI_CALL(env, napi_create_int32(env, value, &result));
111     return result;
112 }
113 
UnwrapLongFromJS(napi_env env,napi_value param,long defaultValue)114 long UnwrapLongFromJS(napi_env env, napi_value param, long defaultValue)
115 {
116     int value = 0;
117     if (napi_get_value_int32(env, param, &value) == napi_ok) {
118         return value;
119     } else {
120         return defaultValue;
121     }
122 }
123 
UnwrapLongFromJS2(napi_env env,napi_value param,long & value)124 bool UnwrapLongFromJS2(napi_env env, napi_value param, long &value)
125 {
126     bool result = false;
127     int natValue = 0;
128     if (napi_get_value_int32(env, param, &natValue) == napi_ok) {
129         value = natValue;
130         result = true;
131     }
132     return result;
133 }
134 
WrapInt64ToJS(napi_env env,int64_t value)135 napi_value WrapInt64ToJS(napi_env env, int64_t value)
136 {
137     napi_value result = nullptr;
138     NAPI_CALL(env, napi_create_int64(env, value, &result));
139     return result;
140 }
141 
UnwrapInt64FromJS(napi_env env,napi_value param,int64_t defaultValue)142 int64_t UnwrapInt64FromJS(napi_env env, napi_value param, int64_t defaultValue)
143 {
144     int64_t value = defaultValue;
145     if (napi_get_value_int64(env, param, &value) == napi_ok) {
146         return value;
147     } else {
148         return defaultValue;
149     }
150 }
151 
UnwrapInt64FromJS2(napi_env env,napi_value param,int64_t & value)152 bool UnwrapInt64FromJS2(napi_env env, napi_value param, int64_t &value)
153 {
154     bool result = false;
155     if (napi_get_value_int64(env, param, &value) == napi_ok) {
156         result = true;
157     }
158     return result;
159 }
160 
WrapBoolToJS(napi_env env,bool value)161 napi_value WrapBoolToJS(napi_env env, bool value)
162 {
163     napi_value result = nullptr;
164     NAPI_CALL(env, napi_get_boolean(env, value, &result));
165     return result;
166 }
167 
UnwrapBoolFromJS(napi_env env,napi_value param,bool defaultValue)168 bool UnwrapBoolFromJS(napi_env env, napi_value param, bool defaultValue)
169 {
170     bool value = defaultValue;
171     if (napi_get_value_bool(env, param, &value) == napi_ok) {
172         return value;
173     } else {
174         return defaultValue;
175     }
176 }
177 
UnwrapBoolFromJS2(napi_env env,napi_value param,bool & value)178 bool UnwrapBoolFromJS2(napi_env env, napi_value param, bool &value)
179 {
180     bool result = false;
181     if (napi_get_value_bool(env, param, &value) == napi_ok) {
182         result = true;
183     }
184     return result;
185 }
186 
WrapDoubleToJS(napi_env env,double value)187 napi_value WrapDoubleToJS(napi_env env, double value)
188 {
189     napi_value result = nullptr;
190     NAPI_CALL(env, napi_create_double(env, value, &result));
191     return result;
192 }
193 
UnwrapDoubleFromJS(napi_env env,napi_value param,double defaultValue)194 double UnwrapDoubleFromJS(napi_env env, napi_value param, double defaultValue)
195 {
196     double value = defaultValue;
197     if (napi_get_value_double(env, param, &value) == napi_ok) {
198         return value;
199     } else {
200         return defaultValue;
201     }
202 }
203 
UnwrapDoubleFromJS2(napi_env env,napi_value param,double & value)204 bool UnwrapDoubleFromJS2(napi_env env, napi_value param, double &value)
205 {
206     bool result = false;
207     if (napi_get_value_double(env, param, &value) == napi_ok) {
208         result = true;
209     }
210     return result;
211 }
212 
WrapStringToJS(napi_env env,const std::string & value)213 napi_value WrapStringToJS(napi_env env, const std::string &value)
214 {
215     napi_value result = nullptr;
216     NAPI_CALL(env, napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result));
217     return result;
218 }
219 
UnwrapStringFromJS(napi_env env,napi_value param,const std::string & defaultValue)220 std::string UnwrapStringFromJS(napi_env env, napi_value param, const std::string &defaultValue)
221 {
222     TAG_LOGD(AAFwkTag::JSNAPI, "UnwrapStringFromJS enter");
223     size_t size = 0;
224     if (napi_get_value_string_utf8(env, param, nullptr, 0, &size) != napi_ok) {
225         return defaultValue;
226     }
227 
228     std::string value("");
229     if (size == 0) {
230         TAG_LOGD(AAFwkTag::JSNAPI, "size is 0");
231         return defaultValue;
232     }
233 
234     char *buf = new (std::nothrow) char[size + 1];
235     if (buf == nullptr) {
236         TAG_LOGD(AAFwkTag::JSNAPI, "buf is nullptr");
237         return value;
238     }
239     (void)memset_s(buf, size + 1, 0, size + 1);
240 
241     bool rev = napi_get_value_string_utf8(env, param, buf, size + 1, &size) == napi_ok;
242     if (rev) {
243         value = buf;
244     } else {
245         value = defaultValue;
246     }
247 
248     delete[] buf;
249     buf = nullptr;
250     return value;
251 }
252 
UnwrapStringFromJS2(napi_env env,napi_value param,std::string & value)253 bool UnwrapStringFromJS2(napi_env env, napi_value param, std::string &value)
254 {
255     value = "";
256     size_t size = 0;
257     if (napi_get_value_string_utf8(env, param, nullptr, 0, &size) != napi_ok) {
258         return false;
259     }
260 
261     if (size == 0) {
262         return true;
263     }
264 
265     char *buf = new (std::nothrow) char[size + 1];
266     if (buf == nullptr) {
267         return false;
268     }
269     (void)memset_s(buf, (size + 1), 0, (size + 1));
270 
271     bool rev = napi_get_value_string_utf8(env, param, buf, size + 1, &size) == napi_ok;
272     if (rev) {
273         value = buf;
274     }
275     delete[] buf;
276     buf = nullptr;
277     return rev;
278 }
279 
WrapArrayInt32ToJS(napi_env env,const std::vector<int> & value)280 napi_value WrapArrayInt32ToJS(napi_env env, const std::vector<int> &value)
281 {
282     TAG_LOGD(AAFwkTag::JSNAPI, "called");
283     napi_value jsArray = nullptr;
284     napi_value jsValue = nullptr;
285     uint32_t index = 0;
286 
287     NAPI_CALL(env, napi_create_array(env, &jsArray));
288     for (uint32_t i = 0; i < value.size(); i++) {
289         jsValue = nullptr;
290         if (napi_create_int32(env, value[i], &jsValue) == napi_ok) {
291             if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) {
292                 index++;
293             }
294         }
295     }
296     return jsArray;
297 }
298 
UnwrapArrayInt32FromJS(napi_env env,napi_value param,std::vector<int> & value)299 bool UnwrapArrayInt32FromJS(napi_env env, napi_value param, std::vector<int> &value)
300 {
301     uint32_t arraySize = 0;
302     napi_value jsValue = nullptr;
303     int natValue = 0;
304 
305     if (!IsArrayForNapiValue(env, param, arraySize)) {
306         TAG_LOGD(AAFwkTag::JSNAPI, "arraySize Expanding ArrayInt32 from JS failed");
307         return false;
308     }
309 
310     value.clear();
311     for (uint32_t i = 0; i < arraySize; i++) {
312         jsValue = nullptr;
313         natValue = 0;
314         if (napi_get_element(env, param, i, &jsValue) != napi_ok) {
315             TAG_LOGD(AAFwkTag::JSNAPI, "array item Expanding ArrayInt32 from JS failed");
316             return false;
317         }
318 
319         if (!UnwrapInt32FromJS2(env, jsValue, natValue)) {
320             return false;
321         }
322 
323         value.push_back(natValue);
324     }
325     return true;
326 }
327 
WrapArrayLongToJS(napi_env env,const std::vector<long> & value)328 napi_value WrapArrayLongToJS(napi_env env, const std::vector<long> &value)
329 {
330     napi_value jsArray = nullptr;
331     napi_value jsValue = nullptr;
332     uint32_t index = 0;
333 
334     NAPI_CALL(env, napi_create_array(env, &jsArray));
335     for (uint32_t i = 0; i < value.size(); i++) {
336         jsValue = nullptr;
337         if (napi_create_int32(env, (int)(value[i]), &jsValue) == napi_ok) {
338             if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) {
339                 index++;
340             }
341         }
342     }
343     return jsArray;
344 }
345 
UnwrapArrayLongFromJS(napi_env env,napi_value param,std::vector<long> & value)346 bool UnwrapArrayLongFromJS(napi_env env, napi_value param, std::vector<long> &value)
347 {
348     uint32_t arraySize = 0;
349     napi_value jsValue = nullptr;
350     long natValue = 0;
351 
352     if (!IsArrayForNapiValue(env, param, arraySize)) {
353         TAG_LOGD(AAFwkTag::JSNAPI, "arraySize Expanding ArrayInt32 from JS failed.");
354         return false;
355     }
356 
357     value.clear();
358     for (uint32_t i = 0; i < arraySize; i++) {
359         jsValue = nullptr;
360         natValue = 0;
361         if (napi_get_element(env, param, i, &jsValue) != napi_ok) {
362             TAG_LOGD(AAFwkTag::JSNAPI, "array item Expanding ArrayInt32 from JS failed.");
363             return false;
364         }
365 
366         if (!UnwrapLongFromJS2(env, jsValue, natValue)) {
367             return false;
368         }
369 
370         value.push_back(natValue);
371     }
372     return true;
373 }
374 
WrapArrayInt64ToJS(napi_env env,const std::vector<int64_t> & value)375 napi_value WrapArrayInt64ToJS(napi_env env, const std::vector<int64_t> &value)
376 {
377     napi_value jsArray = nullptr;
378     napi_value jsValue = nullptr;
379     uint32_t index = 0;
380 
381     NAPI_CALL(env, napi_create_array(env, &jsArray));
382     for (uint32_t i = 0; i < value.size(); i++) {
383         jsValue = nullptr;
384         if (napi_create_int64(env, value[i], &jsValue) == napi_ok) {
385             if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) {
386                 index++;
387             }
388         }
389     }
390     return jsArray;
391 }
392 
UnwrapArrayInt64FromJS(napi_env env,napi_value param,std::vector<int64_t> & value)393 bool UnwrapArrayInt64FromJS(napi_env env, napi_value param, std::vector<int64_t> &value)
394 {
395     uint32_t arraySize = 0;
396     napi_value jsValue = nullptr;
397     int64_t natValue = 0;
398 
399     if (!IsArrayForNapiValue(env, param, arraySize)) {
400         TAG_LOGD(AAFwkTag::JSNAPI, "arraySize Expanding ArrayInt32 from JS error");
401         return false;
402     }
403 
404     value.clear();
405     for (uint32_t i = 0; i < arraySize; i++) {
406         jsValue = nullptr;
407         natValue = 0;
408         if (napi_get_element(env, param, i, &jsValue) != napi_ok) {
409             TAG_LOGD(AAFwkTag::JSNAPI, "array item Expanding ArrayInt32 from JS error");
410             return false;
411         }
412 
413         if (!UnwrapInt64FromJS2(env, jsValue, natValue)) {
414             return false;
415         }
416 
417         value.push_back(natValue);
418     }
419     return true;
420 }
421 
WrapArrayDoubleToJS(napi_env env,const std::vector<double> & value)422 napi_value WrapArrayDoubleToJS(napi_env env, const std::vector<double> &value)
423 {
424     napi_value jsArray = nullptr;
425     napi_value jsValue = nullptr;
426     uint32_t index = 0;
427 
428     NAPI_CALL(env, napi_create_array(env, &jsArray));
429     for (uint32_t i = 0; i < value.size(); i++) {
430         jsValue = nullptr;
431         if (napi_create_double(env, value[i], &jsValue) == napi_ok) {
432             if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) {
433                 index++;
434             }
435         }
436     }
437     return jsArray;
438 }
439 
UnwrapArrayDoubleFromJS(napi_env env,napi_value param,std::vector<double> & value)440 bool UnwrapArrayDoubleFromJS(napi_env env, napi_value param, std::vector<double> &value)
441 {
442     uint32_t arraySize = 0;
443     napi_value jsValue = nullptr;
444     double natValue = 0;
445 
446     if (!IsArrayForNapiValue(env, param, arraySize)) {
447         TAG_LOGD(AAFwkTag::JSNAPI, "arraySize Expanding ArrayInt32 from JS error");
448         return false;
449     }
450 
451     value.clear();
452     for (uint32_t i = 0; i < arraySize; i++) {
453         jsValue = nullptr;
454         natValue = 0;
455         if (napi_get_element(env, param, i, &jsValue) != napi_ok) {
456             TAG_LOGD(AAFwkTag::JSNAPI, "array item Expanding ArrayInt32 from JS error");
457             return false;
458         }
459 
460         if (!UnwrapDoubleFromJS2(env, jsValue, natValue)) {
461             return false;
462         }
463 
464         value.push_back(natValue);
465     }
466     return true;
467 }
468 
WrapArrayBoolToJS(napi_env env,const std::vector<bool> & value)469 napi_value WrapArrayBoolToJS(napi_env env, const std::vector<bool> &value)
470 {
471     napi_value jsArray = nullptr;
472     napi_value jsValue = nullptr;
473     uint32_t index = 0;
474 
475     NAPI_CALL(env, napi_create_array(env, &jsArray));
476     for (uint32_t i = 0; i < value.size(); i++) {
477         jsValue = nullptr;
478         if (napi_get_boolean(env, value[i], &jsValue) == napi_ok) {
479             if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) {
480                 index++;
481             }
482         }
483     }
484     return jsArray;
485 }
486 
UnwrapArrayBoolFromJS(napi_env env,napi_value param,std::vector<bool> & value)487 bool UnwrapArrayBoolFromJS(napi_env env, napi_value param, std::vector<bool> &value)
488 {
489     uint32_t arraySize = 0;
490     napi_value jsValue = nullptr;
491     bool natValue = 0;
492 
493     if (!IsArrayForNapiValue(env, param, arraySize)) {
494         return false;
495     }
496 
497     value.clear();
498     for (uint32_t i = 0; i < arraySize; i++) {
499         jsValue = nullptr;
500         natValue = 0;
501         if (napi_get_element(env, param, i, &jsValue) != napi_ok) {
502             return false;
503         }
504 
505         if (!UnwrapBoolFromJS2(env, jsValue, natValue)) {
506             return false;
507         }
508 
509         value.push_back(natValue);
510     }
511     return true;
512 }
513 
WrapArrayStringToJS(napi_env env,const std::vector<std::string> & value)514 napi_value WrapArrayStringToJS(napi_env env, const std::vector<std::string> &value)
515 {
516     napi_value jsArray = nullptr;
517     napi_value jsValue = nullptr;
518     uint32_t index = 0;
519 
520     NAPI_CALL(env, napi_create_array(env, &jsArray));
521     for (uint32_t i = 0; i < value.size(); i++) {
522         jsValue = nullptr;
523         if (napi_create_string_utf8(env, value[i].c_str(), NAPI_AUTO_LENGTH, &jsValue) == napi_ok) {
524             if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) {
525                 index++;
526             }
527         }
528     }
529     return jsArray;
530 }
531 
UnwrapArrayStringFromJS(napi_env env,napi_value param,std::vector<std::string> & value)532 bool UnwrapArrayStringFromJS(napi_env env, napi_value param, std::vector<std::string> &value)
533 {
534     uint32_t arraySize = 0;
535     napi_value jsValue = nullptr;
536     std::string natValue("");
537 
538     if (!IsArrayForNapiValue(env, param, arraySize)) {
539         return false;
540     }
541 
542     value.clear();
543     for (uint32_t i = 0; i < arraySize; i++) {
544         jsValue = nullptr;
545         natValue = "";
546         if (napi_get_element(env, param, i, &jsValue) != napi_ok) {
547             return false;
548         }
549 
550         if (!UnwrapStringFromJS2(env, jsValue, natValue)) {
551             return false;
552         }
553 
554         value.push_back(natValue);
555     }
556     return true;
557 }
558 
UnwrapArrayComplexFromJSNumber(napi_env env,ComplexArrayData & value,bool isDouble,napi_value jsValue)559 bool UnwrapArrayComplexFromJSNumber(napi_env env, ComplexArrayData &value, bool isDouble, napi_value jsValue)
560 {
561     int32_t elementInt32 = 0;
562     double elementDouble = 0.0;
563     if (isDouble) {
564         if (napi_get_value_double(env, jsValue, &elementDouble) == napi_ok) {
565             value.doubleList.push_back(elementDouble);
566         }
567         return isDouble;
568     }
569 
570     bool isReadValue32 = napi_get_value_int32(env, jsValue, &elementInt32) == napi_ok;
571     bool isReadDouble = napi_get_value_double(env, jsValue, &elementDouble) == napi_ok;
572     if (isReadValue32 && isReadDouble) {
573         if (abs(elementDouble - elementInt32 * 1.0) > 0.0) {
574             isDouble = true;
575             if (value.intList.size() > 0) {
576                 for (size_t j = 0; j < value.intList.size(); j++) {
577                     value.doubleList.push_back(value.intList[j]);
578                 }
579                 value.intList.clear();
580             }
581             value.doubleList.push_back(elementDouble);
582         } else {
583             value.intList.push_back(elementInt32);
584         }
585     } else if (isReadValue32) {
586         value.intList.push_back(elementInt32);
587     } else if (isReadDouble) {
588         isDouble = true;
589         if (value.intList.size() > 0) {
590             for (size_t j = 0; j < value.intList.size(); j++) {
591                 value.doubleList.push_back(value.intList[j]);
592             }
593             value.intList.clear();
594         }
595         value.doubleList.push_back(elementDouble);
596     }
597     return isDouble;
598 }
599 
UnwrapArrayComplexFromJS(napi_env env,napi_value param,ComplexArrayData & value)600 bool UnwrapArrayComplexFromJS(napi_env env, napi_value param, ComplexArrayData &value)
601 {
602     uint32_t arraySize = 0;
603     if (!IsArrayForNapiValue(env, param, arraySize)) {
604         return false;
605     }
606 
607     napi_valuetype valueType = napi_undefined;
608     napi_value jsValue = nullptr;
609     bool isDouble = false;
610 
611     value.intList.clear();
612     value.longList.clear();
613     value.boolList.clear();
614     value.doubleList.clear();
615     value.stringList.clear();
616     value.objectList.clear();
617 
618     for (uint32_t i = 0; i < arraySize; i++) {
619         jsValue = nullptr;
620         valueType = napi_undefined;
621         NAPI_CALL_BASE(env, napi_get_element(env, param, i, &jsValue), false);
622         NAPI_CALL_BASE(env, napi_typeof(env, jsValue, &valueType), false);
623         switch (valueType) {
624             case napi_string: {
625                 std::string elementValue("");
626                 if (UnwrapStringFromJS2(env, jsValue, elementValue)) {
627                     value.stringList.push_back(elementValue);
628                 } else {
629                     return false;
630                 }
631                 break;
632             }
633             case napi_boolean: {
634                 bool elementValue = false;
635                 NAPI_CALL_BASE(env, napi_get_value_bool(env, jsValue, &elementValue), false);
636                 value.boolList.push_back(elementValue);
637                 break;
638             }
639             case napi_number: {
640                 isDouble = UnwrapArrayComplexFromJSNumber(env, value, isDouble, jsValue);
641                 break;
642             }
643             case napi_object: {
644                 value.objectList.push_back(jsValue);
645                 break;
646             }
647             default:
648                 break;
649         }
650     }
651     return true;
652 }
653 
654 /**
655  * @brief Indicates the specified attribute exists in the object passed by JS.
656  *
657  * @param env The environment that the Node-API call is invoked under.
658  * @param jsObject Indicates object passed by JS.
659  * @param propertyName Indicates the name of the property.
660  *
661  * @return Returns true if the attribute exists, else returns false.
662  */
IsExistsByPropertyName(napi_env env,napi_value jsObject,const char * propertyName)663 bool IsExistsByPropertyName(napi_env env, napi_value jsObject, const char *propertyName)
664 {
665     bool result = false;
666     if (napi_has_named_property(env, jsObject, propertyName, &result) == napi_ok) {
667         return result;
668     } else {
669         return false;
670     }
671 }
672 
673 /**
674  * @brief Get the JSValue of the specified name from the JS object.
675  *
676  * @param env The environment that the Node-API call is invoked under.
677  * @param jsObject Indicates object passed by JS.
678  * @param propertyName Indicates the name of the property.
679  * @param expectType Indicates expected JS data type.
680  *
681  * @return Return the property value of the specified property name int jsObject on success, otherwise return nullptr.
682  */
GetPropertyValueByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,napi_valuetype expectType)683 napi_value GetPropertyValueByPropertyName(
684     napi_env env, napi_value jsObject, const char *propertyName, napi_valuetype expectType)
685 {
686     napi_value value = nullptr;
687     if (IsExistsByPropertyName(env, jsObject, propertyName) == false) {
688         return nullptr;
689     }
690 
691     if (napi_get_named_property(env, jsObject, propertyName, &value) != napi_ok) {
692         return nullptr;
693     }
694 
695     if (!IsTypeForNapiValue(env, value, expectType)) {
696         return nullptr;
697     }
698 
699     return value;
700 }
701 
SetPropertyValueByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,napi_value value)702 bool SetPropertyValueByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, napi_value value)
703 {
704     if (value != nullptr && propertyName != nullptr) {
705         NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, propertyName, value), false);
706         return true;
707     }
708     return false;
709 }
710 
711 /**
712  * @brief Get the native number(int32) from the JSObject of the given property name.
713  *
714  * @param env The environment that the Node-API call is invoked under.
715  * @param jsObject Indicates object passed by JS.
716  * @param propertyName Indicates the name of the property.
717  * @param value Indicates the returned native value.
718  *
719  * @return Return true if successful, else return false.
720  */
UnwrapInt32ByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,int32_t & value)721 bool UnwrapInt32ByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, int32_t &value)
722 {
723     napi_value jsValue = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_number);
724     if (jsValue != nullptr) {
725         return UnwrapInt32FromJS2(env, jsValue, value);
726     } else {
727         return false;
728     }
729 }
730 
731 /**
732  * @brief Get the native array number(int32) from the JSObject of the given property name.
733  *
734  * @param env The environment that the Node-API call is invoked under.
735  * @param jsObject Indicates object passed by JS.
736  * @param propertyName Indicates the name of the property.
737  * @param value Indicates the returned native value.
738  *
739  * @return Return true if successful, else return false.
740  */
UnwrapInt32ArrayByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,std::vector<int32_t> & value)741 bool UnwrapInt32ArrayByPropertyName(
742     napi_env env, napi_value jsObject, const char *propertyName, std::vector<int32_t> &value)
743 {
744     napi_value jsArray = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_object);
745     if (jsArray == nullptr) {
746         return false;
747     }
748 
749     return UnwrapArrayInt32FromJS(env, jsArray, value);
750 }
751 
752 /**
753  * @brief Get the native number(double) from the JSObject of the given property name.
754  *
755  * @param env The environment that the Node-API call is invoked under.
756  * @param jsObject Indicates object passed by JS.
757  * @param propertyName Indicates the name of the property.
758  * @param value Indicates the returned native value.
759  *
760  * @return Return true if successful, else return false.
761  */
UnwrapDoubleByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,double & value)762 bool UnwrapDoubleByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, double &value)
763 {
764     napi_value jsValue = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_number);
765     if (jsValue != nullptr) {
766         return UnwrapDoubleFromJS2(env, jsValue, value);
767     } else {
768         return false;
769     }
770 }
771 
772 /**
773  * @brief Get the native boolean from the JSObject of the given property name.
774  *
775  * @param env The environment that the Node-API call is invoked under.
776  * @param jsObject Indicates object passed by JS.
777  * @param propertyName Indicates the name of the property.
778  * @param value Indicates the returned native value.
779  *
780  * @return Return true if successful, else return false.
781  */
UnwrapBooleanByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,bool & value)782 bool UnwrapBooleanByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, bool &value)
783 {
784     napi_value jsValue = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_boolean);
785     if (jsValue != nullptr) {
786         return UnwrapBoolFromJS2(env, jsValue, value);
787     } else {
788         return false;
789     }
790 }
791 
UnwrapBooleanArrayByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,std::vector<bool> & value)792 bool UnwrapBooleanArrayByPropertyName(
793     napi_env env, napi_value jsObject, const char *propertyName, std::vector<bool> &value)
794 {
795     napi_value jsArray = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_object);
796     if (jsArray == nullptr) {
797         return false;
798     }
799 
800     return UnwrapArrayBoolFromJS(env, jsArray, value);
801 }
802 
803 /**
804  * @brief Get the native string from the JSObject of the given property name.
805  *
806  * @param env The environment that the Node-API call is invoked under.
807  * @param jsObject Indicates object passed by JS.
808  * @param propertyName Indicates the name of the property.
809  * @param value Indicates the returned native value.
810  *
811  * @return Return true if successful, else return false.
812  */
UnwrapStringByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,std::string & value)813 bool UnwrapStringByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, std::string &value)
814 {
815     napi_value jsValue = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_string);
816     if (jsValue != nullptr) {
817         return UnwrapStringFromJS2(env, jsValue, value);
818     } else {
819         return false;
820     }
821 }
822 
UnwrapStringArrayByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,std::vector<std::string> & value)823 bool UnwrapStringArrayByPropertyName(
824     napi_env env, napi_value jsObject, const char *propertyName, std::vector<std::string> &value)
825 {
826     napi_value jsArray = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_object);
827     if (jsArray == nullptr) {
828         return false;
829     }
830 
831     return UnwrapArrayStringFromJS(env, jsArray, value);
832 }
833 
UnwrapComplexArrayByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,ComplexArrayData & value)834 bool UnwrapComplexArrayByPropertyName(
835     napi_env env, napi_value jsObject, const char *propertyName, ComplexArrayData &value)
836 {
837     napi_value jsArray = GetPropertyValueByPropertyName(env, jsObject, propertyName, napi_object);
838     if (jsArray == nullptr) {
839         return false;
840     }
841 
842     return UnwrapArrayComplexFromJS(env, jsArray, value);
843 }
844 
ClearThreadReturnData(ThreadReturnData * data)845 void ClearThreadReturnData(ThreadReturnData *data)
846 {
847     if (data != nullptr) {
848         data->data_type = NVT_NONE;
849         data->int32_value = 0;
850         data->bool_value = false;
851         data->str_value = "";
852         data->double_value = 0.0;
853     }
854 }
855 
GetCallbackErrorValue(napi_env env,int errCode)856 napi_value GetCallbackErrorValue(napi_env env, int errCode)
857 {
858     napi_value jsObject = nullptr;
859     napi_value jsValue = nullptr;
860     NAPI_CALL(env, napi_create_int32(env, errCode, &jsValue));
861     NAPI_CALL(env, napi_create_object(env, &jsObject));
862     NAPI_CALL(env, napi_set_named_property(env, jsObject, "code", jsValue));
863     return jsObject;
864 }
865 
866 /**
867  * @brief Create asynchronous data.
868  *
869  * @param env The environment that the Node-API call is invoked under.
870  *
871  * @return Return a pointer to AsyncPermissionCallbackInfo on success, nullptr on failure
872  */
CreateAsyncJSCallbackInfo(napi_env env)873 AsyncJSCallbackInfo *CreateAsyncJSCallbackInfo(napi_env env)
874 {
875     TAG_LOGI(AAFwkTag::JSNAPI, "called");
876 
877     napi_value global = nullptr;
878     NAPI_CALL(env, napi_get_global(env, &global));
879 
880     napi_value abilityObj = nullptr;
881     NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj));
882 
883     Ability *ability = nullptr;
884     NAPI_CALL(env, napi_get_value_external(env, abilityObj, reinterpret_cast<void **>(&ability)));
885 
886     AsyncJSCallbackInfo *asyncCallbackInfo = new (std::nothrow) AsyncJSCallbackInfo;
887     if (asyncCallbackInfo == nullptr) {
888         TAG_LOGE(AAFwkTag::JSNAPI, "null asyncCallbackInfo");
889         return nullptr;
890     }
891     asyncCallbackInfo->cbInfo.env = env;
892     asyncCallbackInfo->cbInfo.callback = nullptr;
893     asyncCallbackInfo->asyncWork = nullptr;
894     asyncCallbackInfo->deferred = nullptr;
895     asyncCallbackInfo->ability = ability;
896     asyncCallbackInfo->abilityType = AbilityType::UNKNOWN;
897     asyncCallbackInfo->aceCallback = nullptr;
898 
899     if (asyncCallbackInfo != nullptr) {
900         ClearThreadReturnData(&asyncCallbackInfo->native_data);
901     }
902     return asyncCallbackInfo;
903 }
904 
FreeAsyncJSCallbackInfo(AsyncJSCallbackInfo ** asyncCallbackInfo)905 void FreeAsyncJSCallbackInfo(AsyncJSCallbackInfo **asyncCallbackInfo)
906 {
907     if (asyncCallbackInfo == nullptr) {
908         return;
909     }
910     if (*asyncCallbackInfo == nullptr) {
911         return;
912     }
913 
914     if ((*asyncCallbackInfo)->cbInfo.callback != nullptr && (*asyncCallbackInfo)->cbInfo.env != nullptr) {
915         napi_delete_reference((*asyncCallbackInfo)->cbInfo.env, (*asyncCallbackInfo)->cbInfo.callback);
916         (*asyncCallbackInfo)->cbInfo.callback = nullptr;
917         (*asyncCallbackInfo)->cbInfo.env = nullptr;
918     }
919 
920     delete (*asyncCallbackInfo);
921     *asyncCallbackInfo = nullptr;
922 }
923 
924 /**
925  * @brief Convert local data to JS data.
926  *
927  * @param env The environment that the Node-API call is invoked under.
928  * @param data The local data.
929  * @param value the JS data.
930  *
931  * @return The return value from NAPI C++ to JS for the module.
932  */
WrapThreadReturnData(napi_env env,const ThreadReturnData * data,napi_value * value)933 bool WrapThreadReturnData(napi_env env, const ThreadReturnData *data, napi_value *value)
934 {
935     if (data == nullptr || value == nullptr) {
936         return false;
937     }
938 
939     switch (data->data_type) {
940         case NVT_UNDEFINED:
941             NAPI_CALL_BASE(env, napi_get_undefined(env, value), false);
942             break;
943         case NVT_INT32:
944             NAPI_CALL_BASE(env, napi_create_int32(env, data->int32_value, value), false);
945             break;
946         case NVT_BOOL:
947             NAPI_CALL_BASE(env, napi_get_boolean(env, data->bool_value, value), false);
948             break;
949         case NVT_STRING:
950             NAPI_CALL_BASE(env, napi_create_string_utf8(env, data->str_value.c_str(), NAPI_AUTO_LENGTH, value), false);
951             break;
952         default:
953             NAPI_CALL_BASE(env, napi_get_null(env, value), false);
954             break;
955     }
956     return true;
957 }
958 
959 /**
960  * @brief Create asynchronous data.
961  *
962  * @param env The environment that the Node-API call is invoked under.
963  * @param param Parameter list.
964  * @param callback Point to asynchronous processing of data.
965  *
966  * @return Return true successfully, otherwise return false.
967  */
CreateAsyncCallback(napi_env env,napi_value param,AsyncJSCallbackInfo * callback)968 bool CreateAsyncCallback(napi_env env, napi_value param, AsyncJSCallbackInfo *callback)
969 {
970     TAG_LOGI(AAFwkTag::JSNAPI, "called");
971 
972     if (param == nullptr || callback == nullptr) {
973         TAG_LOGI(AAFwkTag::JSNAPI, "null param or callback");
974         return false;
975     }
976 
977     callback->cbInfo.callback = CreateCallbackRefFromJS(env, param);
978     if (callback->cbInfo.callback == nullptr) {
979         TAG_LOGI(AAFwkTag::JSNAPI, "create ref failed");
980         return false;
981     }
982 
983     return true;
984 }
985 
CreateCallbackRefFromJS(napi_env env,napi_value param)986 napi_ref CreateCallbackRefFromJS(napi_env env, napi_value param)
987 {
988     if (env == nullptr || param == nullptr) {
989         TAG_LOGI(AAFwkTag::JSNAPI, "null env or param");
990         return nullptr;
991     }
992 
993     napi_valuetype valueType = napi_undefined;
994     NAPI_CALL(env, napi_typeof(env, param, &valueType));
995 
996     if (valueType != napi_function) {
997         TAG_LOGI(AAFwkTag::JSNAPI, "invalid param");
998         return nullptr;
999     }
1000 
1001     napi_ref callbackRef = nullptr;
1002     NAPI_CALL(env, napi_create_reference(env, param, 1, &callbackRef));
1003     return callbackRef;
1004 }
1005 
1006 /**
1007  * @brief Asynchronous callback processing.
1008  *
1009  * @param env The environment that the Node-API call is invoked under.
1010  * @param asyncCallbackInfo Process data asynchronously.
1011  * @param param other param.
1012  *
1013  * @return Return JS data successfully, otherwise return nullptr.
1014  */
ExecuteAsyncCallbackWork(napi_env env,AsyncJSCallbackInfo * asyncCallbackInfo,const AsyncParamEx * param)1015 napi_value ExecuteAsyncCallbackWork(napi_env env, AsyncJSCallbackInfo *asyncCallbackInfo, const AsyncParamEx *param)
1016 {
1017     TAG_LOGI(AAFwkTag::JSNAPI, "called");
1018     if (asyncCallbackInfo == nullptr || param == nullptr) {
1019         TAG_LOGI(AAFwkTag::JSNAPI, "null asyncCallbackInfo or param");
1020         return nullptr;
1021     }
1022 
1023     napi_value resourceName = nullptr;
1024     NAPI_CALL(env, napi_create_string_latin1(env, param->resource.c_str(), NAPI_AUTO_LENGTH, &resourceName));
1025 
1026     NAPI_CALL(env,
1027         napi_create_async_work(env,
1028             nullptr,
1029             resourceName,
1030             param->execute,
1031             param->complete,
1032             static_cast<void *>(asyncCallbackInfo),
1033             &asyncCallbackInfo->asyncWork));
1034 
1035     NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
1036 
1037     return WrapVoidToJS(env);
1038 }
1039 
1040 /**
1041  * @brief Asynchronous promise processing.
1042  *
1043  * @param env The environment that the Node-API call is invoked under.
1044  * @param asyncCallbackInfo Process data asynchronously.
1045  * @param param other param.
1046  *
1047  * @return Return JS data successfully, otherwise return nullptr.
1048  */
ExecutePromiseCallbackWork(napi_env env,AsyncJSCallbackInfo * asyncCallbackInfo,const AsyncParamEx * param)1049 napi_value ExecutePromiseCallbackWork(napi_env env, AsyncJSCallbackInfo *asyncCallbackInfo, const AsyncParamEx *param)
1050 {
1051     TAG_LOGI(AAFwkTag::JSNAPI, "called");
1052     if (asyncCallbackInfo == nullptr || param == nullptr) {
1053         TAG_LOGI(AAFwkTag::JSNAPI, "null asyncCallbackInfo or param");
1054         return nullptr;
1055     }
1056 
1057     napi_value resourceName = nullptr;
1058     NAPI_CALL(env, napi_create_string_latin1(env, param->resource.c_str(), NAPI_AUTO_LENGTH, &resourceName));
1059 
1060     napi_deferred deferred = nullptr;
1061     napi_value promise = nullptr;
1062     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
1063 
1064     asyncCallbackInfo->deferred = deferred;
1065     NAPI_CALL(env,
1066         napi_create_async_work(env,
1067             nullptr,
1068             resourceName,
1069             param->execute,
1070             param->complete,
1071             static_cast<void *>(asyncCallbackInfo),
1072             &asyncCallbackInfo->asyncWork));
1073 
1074     NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
1075     return promise;
1076 }
1077 
1078 /**
1079  * @brief The callback at the end of the asynchronous callback.
1080  *
1081  * @param env The environment that the Node-API call is invoked under.
1082  * @param data Point to asynchronous processing of data.
1083  */
CompleteAsyncCallbackWork(napi_env env,napi_status status,void * data)1084 void CompleteAsyncCallbackWork(napi_env env, napi_status status, void *data)
1085 {
1086     TAG_LOGI(AAFwkTag::JSNAPI, "called");
1087 
1088     AsyncJSCallbackInfo *asyncCallbackInfo = static_cast<AsyncJSCallbackInfo *>(data);
1089     if (asyncCallbackInfo == nullptr) {
1090         TAG_LOGI(AAFwkTag::JSNAPI, "null asyncCallbackInfo");
1091         return;
1092     }
1093 
1094     napi_value callback = nullptr;
1095     napi_value undefined = nullptr;
1096     napi_get_undefined(env, &undefined);
1097     napi_value callResult = nullptr;
1098     napi_value revParam[ARGS_TWO] = {nullptr};
1099 
1100     revParam[PARAM0] = GetCallbackErrorValue(env, asyncCallbackInfo->error_code);
1101     WrapThreadReturnData(env, &asyncCallbackInfo->native_data, &revParam[PARAM1]);
1102 
1103     if (asyncCallbackInfo->cbInfo.callback != nullptr) {
1104         napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback);
1105         napi_call_function(env, undefined, callback, ARGS_TWO, revParam, &callResult);
1106         napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback);
1107     }
1108 
1109     napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
1110     delete asyncCallbackInfo;
1111     asyncCallbackInfo = nullptr;
1112 }
1113 
CompleteAsyncVoidCallbackWork(napi_env env,napi_status status,void * data)1114 void CompleteAsyncVoidCallbackWork(napi_env env, napi_status status, void *data)
1115 {
1116     TAG_LOGI(AAFwkTag::JSNAPI, "called");
1117     AsyncJSCallbackInfo *asyncCallbackInfo = static_cast<AsyncJSCallbackInfo *>(data);
1118     if (asyncCallbackInfo == nullptr) {
1119         TAG_LOGI(AAFwkTag::JSNAPI, "null asyncCallbackInfo");
1120         return;
1121     }
1122     napi_value callback = nullptr;
1123     napi_value undefined = nullptr;
1124     napi_get_undefined(env, &undefined);
1125     napi_value callResult = nullptr;
1126     napi_value result[ARGS_TWO] = {nullptr};
1127 
1128     if (asyncCallbackInfo->error_code) {
1129         NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, asyncCallbackInfo->error_code, &result[PARAM0]));
1130     }
1131 
1132     if (asyncCallbackInfo->error_code == NAPI_ERR_NO_ERROR) {
1133         result[PARAM1] = WrapVoidToJS(env);
1134     } else {
1135         result[PARAM1] = WrapUndefinedToJS(env);
1136     }
1137     if (asyncCallbackInfo->cbInfo.callback != nullptr) {
1138         napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback);
1139         napi_call_function(env, undefined, callback, ARGS_TWO, result, &callResult);
1140         napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback);
1141     }
1142 
1143     napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
1144     delete asyncCallbackInfo;
1145     asyncCallbackInfo = nullptr;
1146 }
1147 
1148 /**
1149  * @brief The callback at the end of the Promise callback.
1150  *
1151  * @param env The environment that the Node-API call is invoked under.
1152  * @param data Point to asynchronous processing of data.
1153  */
CompletePromiseCallbackWork(napi_env env,napi_status status,void * data)1154 void CompletePromiseCallbackWork(napi_env env, napi_status status, void *data)
1155 {
1156     TAG_LOGI(AAFwkTag::JSNAPI, "called");
1157 
1158     AsyncJSCallbackInfo *asyncCallbackInfo = static_cast<AsyncJSCallbackInfo *>(data);
1159     if (asyncCallbackInfo == nullptr) {
1160         TAG_LOGI(AAFwkTag::JSNAPI, "null asyncCallbackInfo");
1161         return;
1162     }
1163 
1164     napi_value result = nullptr;
1165     if (asyncCallbackInfo->error_code == NAPI_ERR_NO_ERROR) {
1166         WrapThreadReturnData(env, &asyncCallbackInfo->native_data, &result);
1167         napi_resolve_deferred(env, asyncCallbackInfo->deferred, result);
1168     } else {
1169         result = GetCallbackErrorValue(env, asyncCallbackInfo->error_code);
1170         napi_reject_deferred(env, asyncCallbackInfo->deferred, result);
1171     }
1172     napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
1173     delete asyncCallbackInfo;
1174     asyncCallbackInfo = nullptr;
1175 }
1176 
CompletePromiseVoidCallbackWork(napi_env env,napi_status status,void * data)1177 void CompletePromiseVoidCallbackWork(napi_env env, napi_status status, void *data)
1178 {
1179     TAG_LOGI(AAFwkTag::JSNAPI, "called");
1180 
1181     AsyncJSCallbackInfo *asyncCallbackInfo = static_cast<AsyncJSCallbackInfo *>(data);
1182     if (asyncCallbackInfo == nullptr) {
1183         TAG_LOGI(AAFwkTag::JSNAPI, "null asyncCallbackInfo");
1184         return;
1185     }
1186     napi_value result = nullptr;
1187     if (asyncCallbackInfo->error_code == NAPI_ERR_NO_ERROR) {
1188         result = WrapVoidToJS(env);
1189         napi_resolve_deferred(env, asyncCallbackInfo->deferred, result);
1190     } else {
1191         result = GetCallbackErrorValue(env, asyncCallbackInfo->error_code);
1192         napi_reject_deferred(env, asyncCallbackInfo->deferred, result);
1193     }
1194     napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
1195     delete asyncCallbackInfo;
1196     asyncCallbackInfo = nullptr;
1197 }
1198 
ConvertU8Vector(napi_env env,napi_value jsValue)1199 std::vector<uint8_t> ConvertU8Vector(napi_env env, napi_value jsValue)
1200 {
1201     bool isTypedArray = false;
1202     if (napi_is_typedarray(env, jsValue, &isTypedArray) != napi_ok || !isTypedArray) {
1203         return {};
1204     }
1205 
1206     napi_typedarray_type type;
1207     size_t length = 0;
1208     napi_value buffer = nullptr;
1209     size_t offset = 0;
1210     NAPI_CALL_BASE(env, napi_get_typedarray_info(env, jsValue, &type, &length, nullptr, &buffer, &offset), {});
1211     if (type != napi_uint8_array) {
1212         return {};
1213     }
1214     uint8_t *data = nullptr;
1215     size_t total = 0;
1216     NAPI_CALL_BASE(env, napi_get_arraybuffer_info(env, buffer, reinterpret_cast<void **>(&data), &total), {});
1217     length = std::min<size_t>(length, total - offset);
1218     std::vector<uint8_t> result(sizeof(uint8_t) + length);
1219     int retCode = memcpy_s(result.data(), result.size(), &data[offset], length);
1220     if (retCode != 0) {
1221         return {};
1222     }
1223     return result;
1224 }
1225 
ConvertStringVector(napi_env env,napi_value jsValue)1226 std::vector<std::string> ConvertStringVector(napi_env env, napi_value jsValue)
1227 {
1228     bool isTypedArray = false;
1229     napi_status status = napi_is_typedarray(env, jsValue, &isTypedArray);
1230     if (status != napi_ok || !isTypedArray) {
1231         TAG_LOGE(AAFwkTag::JSNAPI, "napi_is_typedarray error");
1232         return {};
1233     }
1234 
1235     napi_typedarray_type type;
1236     size_t length = 0;
1237     napi_value buffer = nullptr;
1238     size_t offset = 0;
1239     NAPI_CALL_BASE(env, napi_get_typedarray_info(env, jsValue, &type, &length, nullptr, &buffer, &offset), {});
1240     if (type != napi_uint8_array) {
1241         TAG_LOGE(AAFwkTag::JSNAPI, "null napi_uint8_array");
1242         return {};
1243     }
1244     std::string *data = nullptr;
1245     size_t total = 0;
1246     NAPI_CALL_BASE(env, napi_get_arraybuffer_info(env, buffer, reinterpret_cast<void **>(&data), &total), {});
1247     length = std::min<size_t>(length, total - offset);
1248     std::vector<std::string> result(sizeof(std::string) + length);
1249     int retCode = memcpy_s(result.data(), result.size(), &data[offset], length);
1250     if (retCode != 0) {
1251         return {};
1252     }
1253     return result;
1254 }
1255 }  // namespace AppExecFwk
1256 }  // namespace OHOS
1257