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