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