1 /*
2 * Copyright (c) 2021-2022 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 "js_plugin_util.h"
16
17 #include <cinttypes>
18 #include <cstring>
19
20 #include "native_value.h"
21 #include "securec.h"
22
23 #include "core/common/container.h"
24
25 namespace OHOS::Ace::Napi {
26 constexpr int NAPI_ACE_ERR_NO_ERROR = 0;
27 constexpr int ACE_ARGS_TWO = 2;
28 constexpr int ACE_PARAM0 = 0;
29 constexpr int ACE_PARAM1 = 1;
30
31 bool AceToJson(napi_env env, napi_value param, Json::Value& jsonObject);
32 napi_value ParseJsonToKVObject(napi_env env, Json::Value& jsonObject);
33 napi_value ParseJsonItem(napi_env env, Json::Value& item);
34
AceIsTypeForNapiValue(napi_env env,napi_value param,napi_valuetype expectType)35 bool AceIsTypeForNapiValue(napi_env env, napi_value param, napi_valuetype expectType)
36 {
37 napi_valuetype valueType = napi_undefined;
38
39 if (napi_typeof(env, param, &valueType) != napi_ok) {
40 return false;
41 }
42
43 return valueType == expectType;
44 }
45
AceIsArrayForNapiValue(napi_env env,napi_value param,uint32_t & arraySize)46 bool AceIsArrayForNapiValue(napi_env env, napi_value param, uint32_t& arraySize)
47 {
48 bool isArray = false;
49 arraySize = 0;
50
51 if (napi_is_array(env, param, &isArray) != napi_ok || isArray == false) {
52 return false;
53 }
54
55 if (napi_get_array_length(env, param, &arraySize) != napi_ok) {
56 return false;
57 }
58 return true;
59 }
60
AceWrapVoidToJS(napi_env env)61 napi_value AceWrapVoidToJS(napi_env env)
62 {
63 napi_value result = nullptr;
64 NAPI_CALL(env, napi_get_null(env, &result));
65 return result;
66 }
67
AceWrapUndefinedToJS(napi_env env)68 napi_value AceWrapUndefinedToJS(napi_env env)
69 {
70 napi_value result = nullptr;
71 NAPI_CALL(env, napi_get_undefined(env, &result));
72 return result;
73 }
74
AceCreateJSObject(napi_env env)75 napi_value AceCreateJSObject(napi_env env)
76 {
77 napi_value result = nullptr;
78 NAPI_CALL(env, napi_create_object(env, &result));
79 return result;
80 }
81
AceWrapInt32ToJS(napi_env env,int32_t value)82 napi_value AceWrapInt32ToJS(napi_env env, int32_t value)
83 {
84 napi_value result = nullptr;
85 NAPI_CALL(env, napi_create_int32(env, value, &result));
86 return result;
87 }
88
AceUnwrapInt32FromJS(napi_env env,napi_value param,int defaultValue)89 int AceUnwrapInt32FromJS(napi_env env, napi_value param, int defaultValue)
90 {
91 int value = defaultValue;
92 if (napi_get_value_int32(env, param, &value) == napi_ok) {
93 return value;
94 } else {
95 return defaultValue;
96 }
97 }
98
AceUnwrapInt32FromJS2(napi_env env,napi_value param,int & value)99 bool AceUnwrapInt32FromJS2(napi_env env, napi_value param, int& value)
100 {
101 bool result = false;
102 if (napi_get_value_int32(env, param, &value) == napi_ok) {
103 result = true;
104 }
105 return result;
106 }
107
AceWrapLongToJS(napi_env env,int64_t value)108 napi_value AceWrapLongToJS(napi_env env, int64_t value)
109 {
110 napi_value result = nullptr;
111 NAPI_CALL(env, napi_create_int32(env, value, &result));
112 return result;
113 }
114
AceUnwrapLongFromJS(napi_env env,napi_value param,int64_t defaultValue)115 int64_t AceUnwrapLongFromJS(napi_env env, napi_value param, int64_t defaultValue)
116 {
117 int value = 0;
118 if (napi_get_value_int32(env, param, &value) == napi_ok) {
119 return value;
120 } else {
121 return defaultValue;
122 }
123 }
124
AceUnwrapLongFromJS2(napi_env env,napi_value param,int64_t & value)125 bool AceUnwrapLongFromJS2(napi_env env, napi_value param, int64_t& value)
126 {
127 bool result = false;
128 int natValue = 0;
129 if (napi_get_value_int32(env, param, &natValue) == napi_ok) {
130 value = natValue;
131 result = true;
132 }
133 return result;
134 }
135
AceWrapInt64ToJS(napi_env env,int64_t value)136 napi_value AceWrapInt64ToJS(napi_env env, int64_t value)
137 {
138 napi_value result = nullptr;
139 NAPI_CALL(env, napi_create_int64(env, value, &result));
140 return result;
141 }
142
AceUnwrapInt64FromJS(napi_env env,napi_value param,int64_t defaultValue)143 int64_t AceUnwrapInt64FromJS(napi_env env, napi_value param, int64_t defaultValue)
144 {
145 int64_t value = defaultValue;
146 if (napi_get_value_int64(env, param, &value) == napi_ok) {
147 return value;
148 } else {
149 return defaultValue;
150 }
151 }
152
AceUnwrapInt64FromJS2(napi_env env,napi_value param,int64_t & value)153 bool AceUnwrapInt64FromJS2(napi_env env, napi_value param, int64_t& value)
154 {
155 bool result = false;
156 if (napi_get_value_int64(env, param, &value) == napi_ok) {
157 result = true;
158 }
159 return result;
160 }
161
AceWrapBoolToJS(napi_env env,bool value)162 napi_value AceWrapBoolToJS(napi_env env, bool value)
163 {
164 napi_value result = nullptr;
165 NAPI_CALL(env, napi_get_boolean(env, value, &result));
166 return result;
167 }
168
AceUnwrapBoolFromJS(napi_env env,napi_value param,bool defaultValue)169 bool AceUnwrapBoolFromJS(napi_env env, napi_value param, bool defaultValue)
170 {
171 bool value = defaultValue;
172 if (napi_get_value_bool(env, param, &value) == napi_ok) {
173 return value;
174 } else {
175 return defaultValue;
176 }
177 }
178
AceUnwrapBoolFromJS2(napi_env env,napi_value param,bool & value)179 bool AceUnwrapBoolFromJS2(napi_env env, napi_value param, bool& value)
180 {
181 bool result = false;
182 if (napi_get_value_bool(env, param, &value) == napi_ok) {
183 result = true;
184 }
185 return result;
186 }
187
AceWrapDoubleToJS(napi_env env,double value)188 napi_value AceWrapDoubleToJS(napi_env env, double value)
189 {
190 napi_value result = nullptr;
191 NAPI_CALL(env, napi_create_double(env, value, &result));
192 return result;
193 }
194
AceUnwrapDoubleFromJS(napi_env env,napi_value param,double defaultValue)195 double AceUnwrapDoubleFromJS(napi_env env, napi_value param, double defaultValue)
196 {
197 double value = defaultValue;
198 if (napi_get_value_double(env, param, &value) == napi_ok) {
199 return value;
200 } else {
201 return defaultValue;
202 }
203 }
204
AceUnwrapDoubleFromJS2(napi_env env,napi_value param,double & value)205 bool AceUnwrapDoubleFromJS2(napi_env env, napi_value param, double& value)
206 {
207 bool result = false;
208 if (napi_get_value_double(env, param, &value) == napi_ok) {
209 result = true;
210 }
211 return result;
212 }
213
AceWrapStringToJS(napi_env env,const std::string & value)214 napi_value AceWrapStringToJS(napi_env env, const std::string& value)
215 {
216 napi_value result = nullptr;
217 NAPI_CALL(env, napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result));
218 return result;
219 }
220
AceUnwrapStringFromJS(napi_env env,napi_value param,const std::string & defaultValue)221 std::string AceUnwrapStringFromJS(napi_env env, napi_value param, const std::string& defaultValue)
222 {
223 size_t size = 0;
224 if (napi_get_value_string_utf8(env, param, nullptr, 0, &size) != napi_ok) {
225 return defaultValue;
226 }
227
228 std::string value("");
229 if (size == 0) {
230 return defaultValue;
231 }
232
233 char* buf = new (std::nothrow) char[size + 1];
234 if (buf == nullptr) {
235 return value;
236 }
237 if (memset_s(buf, size + 1, 0, size + 1) != EOK) {
238 delete[] buf;
239 buf = nullptr;
240 return value;
241 }
242
243 bool rev = napi_get_value_string_utf8(env, param, buf, size + 1, &size) == napi_ok;
244 if (rev) {
245 value = buf;
246 } else {
247 value = defaultValue;
248 }
249
250 delete[] buf;
251 buf = nullptr;
252 return value;
253 }
254
AceUnwrapStringFromJS2(napi_env env,napi_value param,std::string & value)255 bool AceUnwrapStringFromJS2(napi_env env, napi_value param, std::string& value)
256 {
257 value = "";
258 size_t size = 0;
259 if (napi_get_value_string_utf8(env, param, nullptr, 0, &size) != napi_ok) {
260 return false;
261 }
262
263 if (size == 0) {
264 return true;
265 }
266
267 char* buf = new (std::nothrow) char[size + 1];
268 if (buf == nullptr) {
269 return false;
270 }
271 if (memset_s(buf, (size + 1), 0, (size + 1)) != EOK) {
272 delete[] buf;
273 buf = nullptr;
274 return false;
275 }
276
277 bool rev = napi_get_value_string_utf8(env, param, buf, size + 1, &size) == napi_ok;
278 if (rev) {
279 value = buf;
280 }
281 delete[] buf;
282 buf = nullptr;
283 return rev;
284 }
285
AceWrapArrayInt32ToJS(napi_env env,const std::vector<int> & value)286 napi_value AceWrapArrayInt32ToJS(napi_env env, const std::vector<int>& value)
287 {
288 napi_value jsArray = nullptr;
289 napi_value jsValue = nullptr;
290 uint32_t index = 0;
291
292 NAPI_CALL(env, napi_create_array(env, &jsArray));
293 for (uint32_t i = 0; i < value.size(); i++) {
294 jsValue = nullptr;
295 if (napi_create_int32(env, value[i], &jsValue) == napi_ok) {
296 if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) {
297 index++;
298 }
299 }
300 }
301 return jsArray;
302 }
303
AceUnwrapArrayInt32FromJS(napi_env env,napi_value param,std::vector<int> & value)304 bool AceUnwrapArrayInt32FromJS(napi_env env, napi_value param, std::vector<int>& value)
305 {
306 uint32_t arraySize = 0;
307 napi_value jsValue = nullptr;
308 int natValue = 0;
309
310 if (!AceIsArrayForNapiValue(env, param, arraySize)) {
311 return false;
312 }
313
314 value.clear();
315 for (uint32_t i = 0; i < arraySize; i++) {
316 jsValue = nullptr;
317 natValue = 0;
318 if (napi_get_element(env, param, i, &jsValue) != napi_ok) {
319 return false;
320 }
321
322 if (!AceUnwrapInt32FromJS2(env, jsValue, natValue)) {
323 return false;
324 }
325
326 value.push_back(natValue);
327 }
328 return true;
329 }
330
AceWrapArrayLongToJS(napi_env env,const std::vector<int64_t> & value)331 napi_value AceWrapArrayLongToJS(napi_env env, const std::vector<int64_t>& value)
332 {
333 napi_value jsArray = nullptr;
334 napi_value jsValue = nullptr;
335 uint32_t index = 0;
336
337 NAPI_CALL(env, napi_create_array(env, &jsArray));
338 for (uint32_t i = 0; i < value.size(); i++) {
339 jsValue = nullptr;
340 if (napi_create_int32(env, (int)(value[i]), &jsValue) == napi_ok) {
341 if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) {
342 index++;
343 }
344 }
345 }
346 return jsArray;
347 }
348
AceUnwrapArrayLongFromJS(napi_env env,napi_value param,std::vector<int64_t> & value)349 bool AceUnwrapArrayLongFromJS(napi_env env, napi_value param, std::vector<int64_t>& value)
350 {
351 uint32_t arraySize = 0;
352 napi_value jsValue = nullptr;
353 int64_t natValue = 0;
354
355 if (!AceIsArrayForNapiValue(env, param, arraySize)) {
356 return false;
357 }
358
359 value.clear();
360 for (uint32_t i = 0; i < arraySize; i++) {
361 jsValue = nullptr;
362 natValue = 0;
363 if (napi_get_element(env, param, i, &jsValue) != napi_ok) {
364 return false;
365 }
366
367 if (!AceUnwrapLongFromJS2(env, jsValue, natValue)) {
368 return false;
369 }
370
371 value.push_back(natValue);
372 }
373 return true;
374 }
375
AceWrapArrayInt64ToJS(napi_env env,const std::vector<int64_t> & value)376 napi_value AceWrapArrayInt64ToJS(napi_env env, const std::vector<int64_t>& value)
377 {
378 napi_value jsArray = nullptr;
379 napi_value jsValue = nullptr;
380 uint32_t index = 0;
381
382 NAPI_CALL(env, napi_create_array(env, &jsArray));
383 for (uint32_t i = 0; i < value.size(); i++) {
384 jsValue = nullptr;
385 if (napi_create_int64(env, value[i], &jsValue) == napi_ok) {
386 if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) {
387 index++;
388 }
389 }
390 }
391 return jsArray;
392 }
393
AceUnwrapArrayInt64FromJS(napi_env env,napi_value param,std::vector<int64_t> & value)394 bool AceUnwrapArrayInt64FromJS(napi_env env, napi_value param, std::vector<int64_t>& value)
395 {
396 uint32_t arraySize = 0;
397 napi_value jsValue = nullptr;
398 int64_t natValue = 0;
399
400 if (!AceIsArrayForNapiValue(env, param, arraySize)) {
401 return false;
402 }
403
404 value.clear();
405 for (uint32_t i = 0; i < arraySize; i++) {
406 jsValue = nullptr;
407 natValue = 0;
408 if (napi_get_element(env, param, i, &jsValue) != napi_ok) {
409 return false;
410 }
411
412 if (!AceUnwrapInt64FromJS2(env, jsValue, natValue)) {
413 return false;
414 }
415
416 value.push_back(natValue);
417 }
418 return true;
419 }
420
AceWrapArrayDoubleToJS(napi_env env,const std::vector<double> & value)421 napi_value AceWrapArrayDoubleToJS(napi_env env, const std::vector<double>& value)
422 {
423 napi_value jsArray = nullptr;
424 napi_value jsValue = nullptr;
425 uint32_t index = 0;
426
427 NAPI_CALL(env, napi_create_array(env, &jsArray));
428 for (uint32_t i = 0; i < value.size(); i++) {
429 jsValue = nullptr;
430 if (napi_create_double(env, value[i], &jsValue) == napi_ok) {
431 if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) {
432 index++;
433 }
434 }
435 }
436 return jsArray;
437 }
438
AceUnwrapArrayDoubleFromJS(napi_env env,napi_value param,std::vector<double> & value)439 bool AceUnwrapArrayDoubleFromJS(napi_env env, napi_value param, std::vector<double>& value)
440 {
441 uint32_t arraySize = 0;
442 napi_value jsValue = nullptr;
443 double natValue = 0;
444
445 if (!AceIsArrayForNapiValue(env, param, arraySize)) {
446 return false;
447 }
448
449 value.clear();
450 for (uint32_t i = 0; i < arraySize; i++) {
451 jsValue = nullptr;
452 natValue = 0;
453 if (napi_get_element(env, param, i, &jsValue) != napi_ok) {
454 return false;
455 }
456
457 if (!AceUnwrapDoubleFromJS2(env, jsValue, natValue)) {
458 return false;
459 }
460
461 value.push_back(natValue);
462 }
463 return true;
464 }
465
AceWrapArrayBoolToJS(napi_env env,const std::vector<bool> & value)466 napi_value AceWrapArrayBoolToJS(napi_env env, const std::vector<bool>& value)
467 {
468 napi_value jsArray = nullptr;
469 napi_value jsValue = nullptr;
470 uint32_t index = 0;
471
472 NAPI_CALL(env, napi_create_array(env, &jsArray));
473 for (uint32_t i = 0; i < value.size(); i++) {
474 jsValue = nullptr;
475 if (napi_get_boolean(env, value[i], &jsValue) == napi_ok) {
476 if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) {
477 index++;
478 }
479 }
480 }
481 return jsArray;
482 }
483
AceUnwrapArrayBoolFromJS(napi_env env,napi_value param,std::vector<bool> & value)484 bool AceUnwrapArrayBoolFromJS(napi_env env, napi_value param, std::vector<bool>& value)
485 {
486 uint32_t arraySize = 0;
487 napi_value jsValue = nullptr;
488 bool natValue = 0;
489
490 if (!AceIsArrayForNapiValue(env, param, arraySize)) {
491 return false;
492 }
493
494 value.clear();
495 for (uint32_t i = 0; i < arraySize; i++) {
496 jsValue = nullptr;
497 natValue = 0;
498 if (napi_get_element(env, param, i, &jsValue) != napi_ok) {
499 return false;
500 }
501
502 if (!AceUnwrapBoolFromJS2(env, jsValue, natValue)) {
503 return false;
504 }
505
506 value.push_back(natValue);
507 }
508 return true;
509 }
510
AceWrapArrayStringToJS(napi_env env,const std::vector<std::string> & value)511 napi_value AceWrapArrayStringToJS(napi_env env, const std::vector<std::string>& value)
512 {
513 napi_value jsArray = nullptr;
514 napi_value jsValue = nullptr;
515 uint32_t index = 0;
516
517 NAPI_CALL(env, napi_create_array(env, &jsArray));
518 for (uint32_t i = 0; i < value.size(); i++) {
519 jsValue = nullptr;
520 if (napi_create_string_utf8(env, value[i].c_str(), NAPI_AUTO_LENGTH, &jsValue) == napi_ok) {
521 if (napi_set_element(env, jsArray, index, jsValue) == napi_ok) {
522 index++;
523 }
524 }
525 }
526 return jsArray;
527 }
528
AceUnwrapArrayStringFromJS(napi_env env,napi_value param,std::vector<std::string> & value)529 bool AceUnwrapArrayStringFromJS(napi_env env, napi_value param, std::vector<std::string>& value)
530 {
531 uint32_t arraySize = 0;
532 napi_value jsValue = nullptr;
533 std::string natValue("");
534
535 if (!AceIsArrayForNapiValue(env, param, arraySize)) {
536 return false;
537 }
538
539 value.clear();
540 for (uint32_t i = 0; i < arraySize; i++) {
541 jsValue = nullptr;
542 natValue = "";
543 if (napi_get_element(env, param, i, &jsValue) != napi_ok) {
544 return false;
545 }
546
547 if (!AceUnwrapStringFromJS2(env, jsValue, natValue)) {
548 return false;
549 }
550
551 value.push_back(natValue);
552 }
553 return true;
554 }
555
AceKVObjectToString(napi_env env,napi_value param,std::string & value)556 bool AceKVObjectToString(napi_env env, napi_value param, std::string& value)
557 {
558 if (!AceIsTypeForNapiValue(env, param, napi_object)) {
559 return false;
560 }
561
562 napi_value globalValue;
563 napi_get_global(env, &globalValue);
564 napi_value jsonValue;
565 napi_get_named_property(env, globalValue, "JSON", &jsonValue);
566 napi_value stringifyValue;
567 napi_get_named_property(env, jsonValue, "stringify", &stringifyValue);
568 napi_value funcArgv[1] = { param };
569 napi_value returnValue = nullptr;
570 napi_call_function(env, jsonValue, stringifyValue, 1, funcArgv, &returnValue);
571 size_t buffSize = 0;
572 napi_status status = napi_get_value_string_utf8(env, returnValue, nullptr, 0, &buffSize);
573 if (status != napi_ok || buffSize == 0) {
574 return false;
575 }
576 std::unique_ptr<char[]> paramsChar = std::make_unique<char[]>(buffSize + 1);
577 size_t ret = 0;
578 napi_get_value_string_utf8(env, returnValue, paramsChar.get(), buffSize + 1, &ret);
579 value = paramsChar.get();
580 return true;
581 }
582
AceStringToKVObject(napi_env env,const std::string & jsonString)583 napi_value AceStringToKVObject(napi_env env, const std::string& jsonString)
584 {
585 if (jsonString.empty()) {
586 return nullptr;
587 }
588
589 napi_value globalValue;
590 napi_get_global(env, &globalValue);
591 napi_value jsonValue;
592 napi_get_named_property(env, globalValue, "JSON", &jsonValue);
593 napi_value parseValue;
594 napi_get_named_property(env, jsonValue, "parse", &parseValue);
595 napi_value gridInfoNApi;
596 napi_create_string_utf8(env, jsonString.c_str(), NAPI_AUTO_LENGTH, &gridInfoNApi);
597 napi_value funcArgv[1] = { gridInfoNApi };
598 napi_value result;
599 napi_call_function(env, jsonValue, parseValue, 1, funcArgv, &result);
600 napi_valuetype valueType = napi_undefined;
601 napi_typeof(env, result, &valueType);
602 if (valueType != napi_object) {
603 return nullptr;
604 }
605 return result;
606 }
607
AceInitComplexArrayData(ACEComplexArrayData & value)608 void AceInitComplexArrayData(ACEComplexArrayData& value)
609 {
610 value.intList.clear();
611 value.longList.clear();
612 value.boolList.clear();
613 value.doubleList.clear();
614 value.stringList.clear();
615 }
616
AceTranscomplex(ACEComplexArrayData & value)617 void AceTranscomplex(ACEComplexArrayData& value)
618 {
619 if (value.intList.size() > 0) {
620 for (size_t j = 0; j < value.intList.size(); j++) {
621 value.doubleList.push_back(value.intList[j]);
622 }
623 value.intList.clear();
624 }
625 }
626
AceUnwrapNumberComplexFromJS(napi_env env,napi_value jsValue,bool & isDouble,ACEComplexArrayData & value)627 void AceUnwrapNumberComplexFromJS(napi_env env, napi_value jsValue, bool& isDouble, ACEComplexArrayData& value)
628 {
629 int32_t elementInt32 = 0;
630 double elementDouble = 0.0;
631 if (isDouble) {
632 if (napi_get_value_double(env, jsValue, &elementDouble) == napi_ok) {
633 value.doubleList.push_back(elementDouble);
634 }
635 } else {
636 bool isReadValue32 = napi_get_value_int32(env, jsValue, &elementInt32) == napi_ok;
637 bool isReadDouble = napi_get_value_double(env, jsValue, &elementDouble) == napi_ok;
638 if (isReadValue32 && isReadDouble) {
639 if (abs(elementDouble - elementInt32 * 1.0) > 0.0) {
640 isDouble = true;
641 AceTranscomplex(value);
642 value.doubleList.push_back(elementDouble);
643 } else {
644 value.intList.push_back(elementInt32);
645 }
646 } else if (isReadValue32) {
647 value.intList.push_back(elementInt32);
648 } else if (isReadDouble) {
649 isDouble = true;
650 AceTranscomplex(value);
651 value.doubleList.push_back(elementDouble);
652 }
653 }
654 }
655
AceUnwrapArrayComplexFromJS(napi_env env,napi_value param,ACEComplexArrayData & value)656 bool AceUnwrapArrayComplexFromJS(napi_env env, napi_value param, ACEComplexArrayData& value)
657 {
658 uint32_t arraySize = 0;
659 if (!AceIsArrayForNapiValue(env, param, arraySize)) {
660 return false;
661 }
662
663 AceInitComplexArrayData(value);
664 napi_valuetype valueType = napi_undefined;
665 napi_value jsValue = nullptr;
666 bool isDouble = false;
667
668 for (uint32_t i = 0; i < arraySize; i++) {
669 jsValue = nullptr;
670 valueType = napi_undefined;
671 NAPI_CALL_BASE(env, napi_get_element(env, param, i, &jsValue), false);
672 NAPI_CALL_BASE(env, napi_typeof(env, jsValue, &valueType), false);
673 switch (valueType) {
674 case napi_string: {
675 std::string elementValue("");
676 if (AceUnwrapStringFromJS2(env, jsValue, elementValue)) {
677 value.stringList.push_back(elementValue);
678 } else {
679 return false;
680 }
681 break;
682 }
683 case napi_boolean: {
684 bool elementValue = false;
685 NAPI_CALL_BASE(env, napi_get_value_bool(env, jsValue, &elementValue), false);
686 value.boolList.push_back(elementValue);
687 break;
688 }
689 case napi_number:
690 AceUnwrapNumberComplexFromJS(env, jsValue, isDouble, value);
691 break;
692 default:
693 break;
694 }
695 }
696 return true;
697 }
698
AceIsSameFuncFromJS(ACECallbackInfo & left,ACECallbackInfo & right)699 bool AceIsSameFuncFromJS(ACECallbackInfo& left, ACECallbackInfo& right)
700 {
701 if (left.env == nullptr && right.env == nullptr) {
702 return true;
703 }
704 if (left.env != right.env || left.containerId != right.containerId) {
705 return false;
706 }
707 if (left.callback == nullptr && right.callback == nullptr) {
708 return true;
709 }
710
711 bool result = false;
712 napi_value leftFunc = nullptr;
713 napi_value rightFunc = nullptr;
714 napi_get_reference_value(left.env, left.callback, &leftFunc);
715 napi_get_reference_value(right.env, right.callback, &rightFunc);
716 napi_strict_equals(left.env, leftFunc, rightFunc, &result);
717 return result;
718 }
719
720 /**
721 * @brief Indicates the specified attribute exists in the object passed by JS.
722 *
723 * @param env The environment that the Node-API call is invoked under.
724 * @param jsObject Indicates object passed by JS.
725 * @param propertyName Indicates the name of the property.
726 *
727 * @return Returns true if the attribute exists, else returns false.
728 */
AceIsExistsByPropertyName(napi_env env,napi_value jsObject,const char * propertyName)729 bool AceIsExistsByPropertyName(napi_env env, napi_value jsObject, const char* propertyName)
730 {
731 bool result = false;
732 if (napi_has_named_property(env, jsObject, propertyName, &result) == napi_ok) {
733 return result;
734 } else {
735 return false;
736 }
737 }
738
739 /**
740 * @brief Get the JSValue of the specified name from the JS object.
741 *
742 * @param env The environment that the Node-API call is invoked under.
743 * @param jsObject Indicates object passed by JS.
744 * @param propertyName Indicates the name of the property.
745 * @param expectType Indicates expected JS data type.
746 *
747 * @return Return the property value of the specified property name int jsObject on success, otherwise return
748 * nullptr.
749 */
AceGetPropertyValueByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,napi_valuetype expectType)750 napi_value AceGetPropertyValueByPropertyName(
751 napi_env env, napi_value jsObject, const char* propertyName, napi_valuetype expectType)
752 {
753 napi_value value = nullptr;
754 if (AceIsExistsByPropertyName(env, jsObject, propertyName) == false) {
755 return nullptr;
756 }
757
758 if (napi_get_named_property(env, jsObject, propertyName, &value) != napi_ok) {
759 return nullptr;
760 }
761
762 if (!AceIsTypeForNapiValue(env, value, expectType)) {
763 return nullptr;
764 }
765
766 return value;
767 }
768
AceSetPropertyValueByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,napi_value value)769 bool AceSetPropertyValueByPropertyName(napi_env env, napi_value jsObject, const char* propertyName, napi_value value)
770 {
771 if (value != nullptr && propertyName != nullptr) {
772 NAPI_CALL_BASE(env, napi_set_named_property(env, jsObject, propertyName, value), false);
773 return true;
774 }
775 return false;
776 }
777
778 /**
779 * @brief Get the native number(int32) from the JSObject of the given property name.
780 *
781 * @param env The environment that the Node-API call is invoked under.
782 * @param jsObject Indicates object passed by JS.
783 * @param propertyName Indicates the name of the property.
784 * @param value Indicates the returned native value.
785 *
786 * @return Return true if successful, else return false.
787 */
AceUnwrapInt32ByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,int32_t & value)788 bool AceUnwrapInt32ByPropertyName(napi_env env, napi_value jsObject, const char* propertyName, int32_t& value)
789 {
790 napi_value jsValue = AceGetPropertyValueByPropertyName(env, jsObject, propertyName, napi_number);
791 if (jsValue != nullptr) {
792 return AceUnwrapInt32FromJS2(env, jsValue, value);
793 } else {
794 return false;
795 }
796 }
797
798 /**
799 * @brief Get the native number(double) from the JSObject of the given property name.
800 *
801 * @param env The environment that the Node-API call is invoked under.
802 * @param jsObject Indicates object passed by JS.
803 * @param propertyName Indicates the name of the property.
804 * @param value Indicates the returned native value.
805 *
806 * @return Return true if successful, else return false.
807 */
AceUnwrapDoubleByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,double & value)808 bool AceUnwrapDoubleByPropertyName(napi_env env, napi_value jsObject, const char* propertyName, double& value)
809 {
810 napi_value jsValue = AceGetPropertyValueByPropertyName(env, jsObject, propertyName, napi_number);
811 if (jsValue != nullptr) {
812 return AceUnwrapDoubleFromJS2(env, jsValue, value);
813 } else {
814 return false;
815 }
816 }
817
818 /**
819 * @brief Get the native boolean from the JSObject of the given property name.
820 *
821 * @param env The environment that the Node-API call is invoked under.
822 * @param jsObject Indicates object passed by JS.
823 * @param propertyName Indicates the name of the property.
824 * @param value Indicates the returned native value.
825 *
826 * @return Return true if successful, else return false.
827 */
AceUnwrapBooleanByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,bool & value)828 bool AceUnwrapBooleanByPropertyName(napi_env env, napi_value jsObject, const char* propertyName, bool& value)
829 {
830 napi_value jsValue = AceGetPropertyValueByPropertyName(env, jsObject, propertyName, napi_boolean);
831 if (jsValue != nullptr) {
832 return AceUnwrapBoolFromJS2(env, jsValue, value);
833 } else {
834 return false;
835 }
836 }
837
AceUnwrapBooleanArrayByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,std::vector<bool> & value)838 bool AceUnwrapBooleanArrayByPropertyName(
839 napi_env env, napi_value jsObject, const char* propertyName, std::vector<bool>& value)
840 {
841 napi_value jsArray = AceGetPropertyValueByPropertyName(env, jsObject, propertyName, napi_object);
842 if (jsArray == nullptr) {
843 return false;
844 }
845
846 return AceUnwrapArrayBoolFromJS(env, jsArray, value);
847 }
848
849 /**
850 * @brief Get the native string from the JSObject of the given property name.
851 *
852 * @param env The environment that the Node-API call is invoked under.
853 * @param jsObject Indicates object passed by JS.
854 * @param propertyName Indicates the name of the property.
855 * @param value Indicates the returned native value.
856 *
857 * @return Return true if successful, else return false.
858 */
AceUnwrapStringByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,std::string & value)859 bool AceUnwrapStringByPropertyName(napi_env env, napi_value jsObject, const char* propertyName, std::string& value)
860 {
861 napi_value jsValue = AceGetPropertyValueByPropertyName(env, jsObject, propertyName, napi_string);
862 if (jsValue != nullptr) {
863 return AceUnwrapStringFromJS2(env, jsValue, value);
864 } else {
865 return false;
866 }
867 }
868
AceUnwrapStringArrayByPropertyName(napi_env env,napi_value jsObject,const char * propertyName,std::vector<std::string> & value)869 bool AceUnwrapStringArrayByPropertyName(
870 napi_env env, napi_value jsObject, const char* propertyName, std::vector<std::string>& value)
871 {
872 napi_value jsArray = AceGetPropertyValueByPropertyName(env, jsObject, propertyName, napi_object);
873 if (jsArray == nullptr) {
874 return false;
875 }
876
877 return AceUnwrapArrayStringFromJS(env, jsArray, value);
878 }
879
AceClearThreadReturnData(ACEThreadReturnData * data)880 void AceClearThreadReturnData(ACEThreadReturnData* data)
881 {
882 if (data != nullptr) {
883 data->data_type = TACENativeValueType::NVT_NONE;
884 data->int32_value = 0;
885 data->bool_value = false;
886 data->str_value = "";
887 data->double_value = 0.0;
888 }
889 }
890
AceGetCallbackErrorValue(napi_env env,int errCode)891 napi_value AceGetCallbackErrorValue(napi_env env, int errCode)
892 {
893 napi_value jsObject = nullptr;
894 napi_value jsValue = nullptr;
895 NAPI_CALL(env, napi_create_int32(env, errCode, &jsValue));
896 NAPI_CALL(env, napi_create_object(env, &jsObject));
897 NAPI_CALL(env, napi_set_named_property(env, jsObject, "code", jsValue));
898 return jsObject;
899 }
900
901 /**
902 * @brief Create asynchronous data.
903 *
904 * @param env The environment that the Node-API call is invoked under.
905 *
906 * @return Return a pointer to AsyncPermissionCallbackInfo on success, nullptr on failure
907 */
AceCreateAsyncJSCallbackInfo(napi_env env)908 ACEAsyncJSCallbackInfo* AceCreateAsyncJSCallbackInfo(napi_env env)
909 {
910 napi_value global = 0;
911 NAPI_CALL(env, napi_get_global(env, &global));
912
913 napi_value abilityObj = 0;
914 NAPI_CALL(env, napi_get_named_property(env, global, "ability", &abilityObj));
915 Ability* ability = nullptr;
916 napi_valuetype valueType = napi_undefined;
917 NAPI_CALL(env, napi_typeof(env, abilityObj, &valueType));
918 if (valueType == napi_external) {
919 NAPI_CALL(env, napi_get_value_external(env, abilityObj, (void**)&ability));
920 }
921
922 auto containerId = Container::CurrentId();
923 ACEAsyncJSCallbackInfo* asyncCallbackInfo = new (std::nothrow) ACEAsyncJSCallbackInfo {
924 .cbInfo = {
925 .env = env,
926 .callback = nullptr,
927 .containerId = containerId,
928 },
929 .ability = ability,
930 .deferred = nullptr,
931 .onRequestData = nullptr,
932 .onRequestCallbackOK = false,
933 };
934
935 if (asyncCallbackInfo != nullptr) {
936 AceClearThreadReturnData(&asyncCallbackInfo->native_data);
937 }
938 return asyncCallbackInfo;
939 }
940
AceFreeAsyncJSCallbackInfo(ACEAsyncJSCallbackInfo ** asyncCallbackInfo)941 void AceFreeAsyncJSCallbackInfo(ACEAsyncJSCallbackInfo** asyncCallbackInfo)
942 {
943 if (asyncCallbackInfo == nullptr) {
944 return;
945 }
946 if (*asyncCallbackInfo == nullptr) {
947 return;
948 }
949
950 if ((*asyncCallbackInfo)->cbInfo.callback != nullptr && (*asyncCallbackInfo)->cbInfo.env != nullptr) {
951 napi_delete_reference((*asyncCallbackInfo)->cbInfo.env, (*asyncCallbackInfo)->cbInfo.callback);
952 (*asyncCallbackInfo)->cbInfo.callback = nullptr;
953 (*asyncCallbackInfo)->cbInfo.env = nullptr;
954 }
955
956 delete (*asyncCallbackInfo);
957 *asyncCallbackInfo = nullptr;
958 }
959
960 /**
961 * @brief Convert local data to JS data.
962 *
963 * @param env The environment that the Node-API call is invoked under.
964 * @param data The local data.
965 * @param value the JS data.
966 *
967 * @return The return value from NAPI C++ to JS for the module.
968 */
AceWrapThreadReturnData(napi_env env,const ACEThreadReturnData * data,napi_value * value)969 bool AceWrapThreadReturnData(napi_env env, const ACEThreadReturnData* data, napi_value* value)
970 {
971 if (data == nullptr || value == nullptr) {
972 return false;
973 }
974
975 switch (data->data_type) {
976 case TACENativeValueType::NVT_UNDEFINED:
977 NAPI_CALL_BASE(env, napi_get_undefined(env, value), false);
978 break;
979 case TACENativeValueType::NVT_INT32:
980 NAPI_CALL_BASE(env, napi_create_int32(env, data->int32_value, value), false);
981 break;
982 case TACENativeValueType::NVT_BOOL:
983 NAPI_CALL_BASE(env, napi_get_boolean(env, data->bool_value, value), false);
984 break;
985 case TACENativeValueType::NVT_STRING:
986 NAPI_CALL_BASE(env, napi_create_string_utf8(env, data->str_value.c_str(), NAPI_AUTO_LENGTH, value), false);
987 break;
988 default:
989 NAPI_CALL_BASE(env, napi_get_null(env, value), false);
990 break;
991 }
992 return true;
993 }
994
995 /**
996 * @brief Create asynchronous data.
997 *
998 * @param env The environment that the Node-API call is invoked under.
999 * @param param Parameter list.
1000 * @param callback Point to asynchronous processing of data.
1001 *
1002 * @return Return true successfully, otherwise return false.
1003 */
AceCreateAsyncCallback(napi_env env,napi_value param,ACEAsyncJSCallbackInfo * callback)1004 bool AceCreateAsyncCallback(napi_env env, napi_value param, ACEAsyncJSCallbackInfo* callback)
1005 {
1006 if (param == nullptr || callback == nullptr) {
1007 return false;
1008 }
1009
1010 callback->cbInfo.callback = AceCreateCallbackRefFromJS(env, param);
1011 if (callback->cbInfo.callback == nullptr) {
1012 return false;
1013 }
1014
1015 return true;
1016 }
1017
AceCreateCallbackRefFromJS(napi_env env,napi_value param)1018 napi_ref AceCreateCallbackRefFromJS(napi_env env, napi_value param)
1019 {
1020 if (env == nullptr || param == nullptr) {
1021 return nullptr;
1022 }
1023
1024 napi_valuetype valueType = napi_undefined;
1025 NAPI_CALL(env, napi_typeof(env, param, &valueType));
1026
1027 if (valueType != napi_function) {
1028 return nullptr;
1029 }
1030
1031 napi_ref callbackRef = nullptr;
1032 NAPI_CALL(env, napi_create_reference(env, param, 1, &callbackRef));
1033 return callbackRef;
1034 }
1035
1036 /**
1037 * @brief The callback at the end of the asynchronous callback.
1038 *
1039 * @param env The environment that the Node-API call is invoked under.
1040 * @param data Point to asynchronous processing of data.
1041 */
AceCompleteAsyncCallbackWork(napi_env env,ACEAsyncJSCallbackInfo * asyncCallbackInfo)1042 void AceCompleteAsyncCallbackWork(napi_env env, ACEAsyncJSCallbackInfo* asyncCallbackInfo)
1043 {
1044 if (asyncCallbackInfo == nullptr) {
1045 return;
1046 }
1047
1048 napi_value callback = 0;
1049 napi_value undefined = 0;
1050 napi_get_undefined(env, &undefined);
1051 napi_value callResult = 0;
1052 napi_value revParam[ACE_ARGS_TWO] = { nullptr };
1053
1054 revParam[ACE_PARAM0] = AceGetCallbackErrorValue(env, asyncCallbackInfo->error_code);
1055 AceWrapThreadReturnData(env, &asyncCallbackInfo->native_data, &revParam[ACE_PARAM1]);
1056
1057 if (asyncCallbackInfo->cbInfo.callback != nullptr) {
1058 napi_get_reference_value(env, asyncCallbackInfo->cbInfo.callback, &callback);
1059 napi_call_function(env, undefined, callback, ACE_ARGS_TWO, revParam, &callResult);
1060 napi_delete_reference(env, asyncCallbackInfo->cbInfo.callback);
1061 }
1062
1063 delete asyncCallbackInfo;
1064 asyncCallbackInfo = nullptr;
1065 }
1066
1067 /**
1068 * @brief The callback at the end of the Promise callback.
1069 *
1070 * @param env The environment that the Node-API call is invoked under.
1071 * @param data Point to asynchronous processing of data.
1072 */
AceCompletePromiseCallbackWork(napi_env env,ACEAsyncJSCallbackInfo * asyncCallbackInfo)1073 void AceCompletePromiseCallbackWork(napi_env env, ACEAsyncJSCallbackInfo* asyncCallbackInfo)
1074 {
1075 if (asyncCallbackInfo == nullptr) {
1076 return;
1077 }
1078
1079 napi_value result = 0;
1080 if (asyncCallbackInfo->error_code == NAPI_ACE_ERR_NO_ERROR) {
1081 AceWrapThreadReturnData(env, &asyncCallbackInfo->native_data, &result);
1082 napi_resolve_deferred(env, asyncCallbackInfo->deferred, result);
1083 } else {
1084 result = AceGetCallbackErrorValue(env, asyncCallbackInfo->error_code);
1085 napi_reject_deferred(env, asyncCallbackInfo->deferred, result);
1086 }
1087 delete asyncCallbackInfo;
1088 asyncCallbackInfo = nullptr;
1089 }
1090
1091 /**
1092 * @brief Set named property to obj by string
1093 *
1094 * @param jsObject Indicates object passed by JS.
1095 * @param propertyName Indicates the name of the object.
1096 * @param propName Indicates the name of the property.
1097 */
AceSetNamedPropertyByString(napi_env env,napi_value jsObject,const char * objName,const char * propName)1098 void AceSetNamedPropertyByString(napi_env env, napi_value jsObject, const char* objName, const char* propName)
1099 {
1100 napi_value prop = nullptr;
1101 napi_create_string_utf8(env, objName, NAPI_AUTO_LENGTH, &prop);
1102 napi_set_named_property(env, jsObject, propName, prop);
1103 }
1104 } // namespace OHOS::Ace::Napi
1105