• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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