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