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