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