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