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