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