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