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