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