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