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