• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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 
16 #include "napi_utils.h"
17 
18 #include <atomic>
19 #include <cstring>
20 #include <initializer_list>
21 #include <memory>
22 #include <mutex>
23 #include <queue>
24 #include <unordered_set>
25 #include <unordered_map>
26 
27 #include "netmanager_base_log.h"
28 #include "securec.h"
29 
30 namespace OHOS {
31 namespace NetManagerStandard {
32 namespace NapiUtils {
33 namespace {
34 static constexpr const int MAX_STRING_LENGTH = 65536;
35 constexpr const char *CODE = "code";
36 constexpr const char *MSG = "message";
37 } // namespace
38 
39 static std::unordered_set<napi_env> unorderedSetEnv;
40 static std::recursive_mutex mutexForEnv;
41 
42 class WorkData {
43 public:
44     WorkData() = delete;
45 
WorkData(napi_env env,void * data,void (* handler)(napi_env env,napi_status status,void * data))46     WorkData(napi_env env, void *data, void (*handler)(napi_env env, napi_status status, void *data))
47         : env_(env), data_(data), handler_(handler)
48     {
49     }
50 
51     napi_env env_;
52     void *data_;
53     void (*handler_)(napi_env env, napi_status status, void *data);
54 };
55 
56 struct UvHandlerQueue : public std::queue<UvHandler> {
57     UvHandler Pop();
58     void Push(const UvHandler &handler);
59 
60 private:
61     std::mutex mutex;
62 };
63 
64 static std::mutex g_mutex;
65 static std::unordered_map<uint64_t, std::shared_ptr<UvHandlerQueue>> g_handlerQueueMap;
66 static const char *const HTTP_UV_SYNC_QUEUE_NAME = "NET_CONNECTION_UV_SYNC_QUEUE_NAME";
67 
Pop()68 UvHandler UvHandlerQueue::Pop()
69 {
70     std::lock_guard lock(mutex);
71     if (empty()) {
72         return {};
73     }
74     auto s = front();
75     pop();
76     return s;
77 }
78 
Push(const UvHandler & handler)79 void UvHandlerQueue::Push(const UvHandler &handler)
80 {
81     std::lock_guard lock(mutex);
82     push(handler);
83 }
84 
GetGlobal(napi_env env)85 napi_value GetGlobal(napi_env env)
86 {
87     napi_value undefined = GetUndefined(env);
88     napi_value global = nullptr;
89     NAPI_CALL_BASE(env, napi_get_global(env, &global), undefined);
90     return global;
91 }
92 
CreateUvHandlerQueue(napi_env env)93 uint64_t CreateUvHandlerQueue(napi_env env)
94 {
95     static std::atomic<uint64_t> id = 1; // start from 1
96     uint64_t newId = id++;
97     NETMANAGER_BASE_LOGI("newId = %{public}s, id = %{public}s", std::to_string(newId).c_str(),
98                          std::to_string(id).c_str());
99 
100     auto global = GetGlobal(env);
101     auto queueWrapper = CreateObject(env);
102     SetNamedProperty(env, global, HTTP_UV_SYNC_QUEUE_NAME, queueWrapper);
103     {
104         std::lock_guard lock(g_mutex);
105         g_handlerQueueMap.emplace(newId, std::make_shared<UvHandlerQueue>());
106     }
107     napi_wrap(
108         env, queueWrapper, reinterpret_cast<void *>(newId),
109         [](napi_env env, void *data, void *) {
110             auto id = reinterpret_cast<uint64_t>(data);
111             std::lock_guard lock(g_mutex);
112             g_handlerQueueMap.erase(id);
113         },
114         nullptr, nullptr);
115     auto envWrapper = new (std::nothrow) napi_env;
116     if (envWrapper == nullptr) {
117         return newId;
118     }
119     *envWrapper = env;
120     napi_add_env_cleanup_hook(
121         env,
122         [](void *data) {
123             auto envWrapper = reinterpret_cast<napi_env *>(data);
124             if (envWrapper == nullptr) {
125                 return;
126             }
127             auto env = *envWrapper;
128             delete envWrapper;
129             if (env == nullptr) {
130                 return;
131             }
132             auto queueWrapper = NapiUtils::GetValueFromGlobal(env, HTTP_UV_SYNC_QUEUE_NAME);
133             if (queueWrapper == nullptr) {
134                 return;
135             }
136             void *result = nullptr;
137             napi_remove_wrap(env, queueWrapper, &result);
138             auto id = reinterpret_cast<uint64_t>(result);
139             std::lock_guard lock(g_mutex);
140             g_handlerQueueMap.erase(id);
141         },
142         envWrapper);
143     return newId;
144 }
145 
GetValueFromGlobal(napi_env env,const std::string & className)146 napi_value GetValueFromGlobal(napi_env env, const std::string &className)
147 {
148     auto global = NapiUtils::GetGlobal(env);
149     if (NapiUtils::GetValueType(env, global) == napi_undefined) {
150         return GetUndefined(env);
151     }
152     return NapiUtils::GetNamedProperty(env, global, className);
153 }
154 
MakeUvCallback()155 static uv_after_work_cb MakeUvCallback()
156 {
157     return [](uv_work_t *work, int status) {
158         if (!work) {
159             return;
160         }
161         std::unique_ptr<uv_work_t> workHandle(work);
162 
163         if (!work->data) {
164             return;
165         }
166         auto env = reinterpret_cast<napi_env>(work->data);
167         if (!env) {
168             return;
169         }
170 
171         auto closeScope = [env](napi_handle_scope scope) { NapiUtils::CloseScope(env, scope); };
172         std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scope(NapiUtils::OpenScope(env), closeScope);
173         auto queueWrapper = GetValueFromGlobal(env, HTTP_UV_SYNC_QUEUE_NAME);
174         if (!queueWrapper) {
175             return;
176         }
177         void *theId = nullptr;
178         napi_unwrap(env, queueWrapper, &theId);
179         if (!theId) { // that is why moduleId is started from 1
180             return;
181         }
182         UvHandler handler;
183         {
184             std::lock_guard lock(g_mutex);
185             auto it = g_handlerQueueMap.find(reinterpret_cast<uint64_t>(theId));
186             if (it == g_handlerQueueMap.end()) {
187                 return;
188             }
189             handler = it->second->Pop();
190         }
191         if (handler) {
192             handler(env);
193         }
194     };
195 }
196 
CreateUvQueueWorkByModuleId(napi_env env,const UvHandler & handler,uint64_t id)197 void CreateUvQueueWorkByModuleId(napi_env env, const UvHandler &handler, uint64_t id)
198 {
199     uv_loop_s *loop = nullptr;
200     if (!IsEnvValid(env)) {
201         NETMANAGER_BASE_LOGE("the env is invalid");
202         return;
203     }
204     napi_get_uv_event_loop(env, &loop);
205     if (!loop) {
206         return;
207     }
208     uv_work_t *work = nullptr;
209     {
210         std::lock_guard lock(g_mutex);
211         auto it = g_handlerQueueMap.find(id);
212         if (it == g_handlerQueueMap.end()) {
213             return;
214         }
215         work = new (std::nothrow) uv_work_t;
216         if (work == nullptr) {
217             return;
218         }
219         work->data = env;
220         it->second->Push(handler);
221     }
222 
223     if (work) {
224         int32_t ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *) {}, MakeUvCallback(), uv_qos_default);
225         if (ret != 0) {
226             delete work;
227         }
228     }
229 }
230 
GetValueType(napi_env env,napi_value value)231 napi_valuetype GetValueType(napi_env env, napi_value value)
232 {
233     if (value == nullptr) {
234         return napi_undefined;
235     }
236 
237     napi_valuetype valueType = napi_undefined;
238     NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), napi_undefined);
239     return valueType;
240 }
241 
242 /* named property */
HasNamedProperty(napi_env env,napi_value object,const std::string & propertyName)243 bool HasNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
244 {
245     bool hasProperty = false;
246     NAPI_CALL_BASE(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty), false);
247     return hasProperty;
248 }
249 
GetNamedProperty(napi_env env,napi_value object,const std::string & propertyName)250 napi_value GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
251 {
252     napi_value value = nullptr;
253     NAPI_CALL(env, napi_get_named_property(env, object, propertyName.c_str(), &value));
254     return value;
255 }
256 
SetNamedProperty(napi_env env,napi_value object,const std::string & name,napi_value value)257 void SetNamedProperty(napi_env env, napi_value object, const std::string &name, napi_value value)
258 {
259     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, object, name.c_str(), value));
260 }
261 
GetPropertyNames(napi_env env,napi_value object)262 std::vector<std::string> GetPropertyNames(napi_env env, napi_value object)
263 {
264     std::vector<std::string> ret;
265     napi_value names = nullptr;
266     NAPI_CALL_BASE(env, napi_get_property_names(env, object, &names), ret);
267     uint32_t length = 0;
268     NAPI_CALL_BASE(env, napi_get_array_length(env, names, &length), ret);
269     for (uint32_t index = 0; index < length; ++index) {
270         napi_value name = nullptr;
271         if (napi_get_element(env, names, index, &name) != napi_ok) {
272             continue;
273         }
274         if (GetValueType(env, name) != napi_string) {
275             continue;
276         }
277         ret.emplace_back(GetStringFromValueUtf8(env, name));
278     }
279     return ret;
280 }
281 
282 /* UINT32 */
CreateUint32(napi_env env,uint32_t code)283 napi_value CreateUint32(napi_env env, uint32_t code)
284 {
285     napi_value value = nullptr;
286     if (napi_create_uint32(env, code, &value) != napi_ok) {
287         return nullptr;
288     }
289     return value;
290 }
291 
GetUint32FromValue(napi_env env,napi_value value)292 uint32_t GetUint32FromValue(napi_env env, napi_value value)
293 {
294     uint32_t ret = 0;
295     NAPI_CALL_BASE(env, napi_get_value_uint32(env, value, &ret), 0);
296     return ret;
297 }
298 
GetUint32Property(napi_env env,napi_value object,const std::string & propertyName)299 uint32_t GetUint32Property(napi_env env, napi_value object, const std::string &propertyName)
300 {
301     if (!HasNamedProperty(env, object, propertyName)) {
302         return 0;
303     }
304     napi_value value = GetNamedProperty(env, object, propertyName);
305     return GetUint32FromValue(env, value);
306 }
307 
SetUint32Property(napi_env env,napi_value object,const std::string & name,uint32_t value)308 void SetUint32Property(napi_env env, napi_value object, const std::string &name, uint32_t value)
309 {
310     napi_value jsValue = CreateUint32(env, value);
311     if (GetValueType(env, jsValue) != napi_number) {
312         return;
313     }
314 
315     napi_set_named_property(env, object, name.c_str(), jsValue);
316 }
317 
318 /* INT32 */
CreateInt32(napi_env env,int32_t code)319 napi_value CreateInt32(napi_env env, int32_t code)
320 {
321     napi_value value = nullptr;
322     if (napi_create_int32(env, code, &value) != napi_ok) {
323         return nullptr;
324     }
325     return value;
326 }
327 
GetInt32FromValue(napi_env env,napi_value value)328 int32_t GetInt32FromValue(napi_env env, napi_value value)
329 {
330     int32_t ret = 0;
331     NAPI_CALL_BASE(env, napi_get_value_int32(env, value, &ret), 0);
332     return ret;
333 }
334 
GetInt32Property(napi_env env,napi_value object,const std::string & propertyName)335 int32_t GetInt32Property(napi_env env, napi_value object, const std::string &propertyName)
336 {
337     if (!HasNamedProperty(env, object, propertyName)) {
338         return 0;
339     }
340     napi_value value = GetNamedProperty(env, object, propertyName);
341     return GetInt32FromValue(env, value);
342 }
343 
SetInt32Property(napi_env env,napi_value object,const std::string & name,int32_t value)344 void SetInt32Property(napi_env env, napi_value object, const std::string &name, int32_t value)
345 {
346     napi_value jsValue = CreateInt32(env, value);
347     if (GetValueType(env, jsValue) != napi_number) {
348         return;
349     }
350 
351     napi_set_named_property(env, object, name.c_str(), jsValue);
352 }
353 
354 /* INT64 */
CreateInt64(napi_env env,int64_t code)355 napi_value CreateInt64(napi_env env, int64_t code)
356 {
357     napi_value value = nullptr;
358     if (napi_create_int64(env, code, &value) != napi_ok) {
359         return nullptr;
360     }
361     return value;
362 }
363 
GetInt64Property(napi_env env,napi_value object,const std::string & propertyName)364 int64_t GetInt64Property(napi_env env, napi_value object, const std::string &propertyName)
365 {
366     if (!HasNamedProperty(env, object, propertyName)) {
367         return 0;
368     }
369     napi_value value = GetNamedProperty(env, object, propertyName);
370     return GetInt64FromValue(env, value);
371 }
GetInt64FromValue(napi_env env,napi_value value)372 int64_t GetInt64FromValue(napi_env env, napi_value value)
373 {
374     int64_t ret = 0;
375     NAPI_CALL_BASE(env, napi_get_value_int64(env, value, &ret), 0);
376     return ret;
377 }
SetInt64Property(napi_env env,napi_value object,const std::string & name,int64_t value)378 void SetInt64Property(napi_env env, napi_value object, const std::string &name, int64_t value)
379 {
380     napi_value jsValue = CreateInt64(env, value);
381     if (GetValueType(env, jsValue) != napi_number) {
382         return;
383     }
384 
385     napi_set_named_property(env, object, name.c_str(), jsValue);
386 }
387 
388 /* String UTF8 */
CreateStringUtf8(napi_env env,const std::string & str)389 napi_value CreateStringUtf8(napi_env env, const std::string &str)
390 {
391     napi_value value = nullptr;
392     if (napi_create_string_utf8(env, str.c_str(), strlen(str.c_str()), &value) != napi_ok) {
393         return nullptr;
394     }
395     return value;
396 }
397 
GetStringFromValueUtf8(napi_env env,napi_value value)398 std::string GetStringFromValueUtf8(napi_env env, napi_value value)
399 {
400     std::string result;
401     char str[MAX_STRING_LENGTH] = {0};
402     size_t length = 0;
403     NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, value, str, MAX_STRING_LENGTH, &length), result);
404     if (length > MAX_STRING_LENGTH) {
405         result.append(str, MAX_STRING_LENGTH);
406         return result;
407     }
408     if (length > 0) {
409         return result.append(str, length);
410     }
411     return result;
412 }
413 
GetSecureDataFromValueUtf8(napi_env env,napi_value value)414 SecureData GetSecureDataFromValueUtf8(napi_env env, napi_value value)
415 {
416     SecureData result;
417     char str[MAX_STRING_LENGTH] = {0};
418     size_t length = 0;
419     NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, value, str, MAX_STRING_LENGTH, &length), result);
420     if (length > 0) {
421         result.append(str, length);
422     }
423     return result;
424 }
425 
GetStringPropertyUtf8(napi_env env,napi_value object,const std::string & propertyName)426 std::string GetStringPropertyUtf8(napi_env env, napi_value object, const std::string &propertyName)
427 {
428     if (!HasNamedProperty(env, object, propertyName)) {
429         return "";
430     }
431     napi_value value = GetNamedProperty(env, object, propertyName);
432     return GetStringFromValueUtf8(env, value);
433 }
434 
GetSecureDataPropertyUtf8(napi_env env,napi_value object,const std::string & propertyName)435 SecureData GetSecureDataPropertyUtf8(napi_env env, napi_value object, const std::string &propertyName)
436 {
437     napi_value value = GetNamedProperty(env, object, propertyName);
438     return GetSecureDataFromValueUtf8(env, value);
439 }
440 
SetStringPropertyUtf8(napi_env env,napi_value object,const std::string & name,const std::string & value)441 void SetStringPropertyUtf8(napi_env env, napi_value object, const std::string &name, const std::string &value)
442 {
443     napi_value jsValue = CreateStringUtf8(env, value);
444     if (GetValueType(env, jsValue) != napi_string) {
445         return;
446     }
447     napi_set_named_property(env, object, name.c_str(), jsValue);
448 }
449 
SetVectorUint8Property(napi_env env,napi_value object,const std::string & name,const std::vector<uint8_t> & value)450 napi_status SetVectorUint8Property(napi_env env, napi_value object, const std::string &name,
451     const std::vector<uint8_t> &value)
452 {
453     napi_value array;
454     napi_status status = napi_create_array_with_length(env, value.size(), &array);
455     if (status != napi_ok) {
456         NETMANAGER_BASE_LOGE("failed to create array! field: %{public}s", name.c_str());
457         return status;
458     }
459 
460     for (size_t i = 0; i < value.size(); ++i) {
461         napi_value ele;
462         napi_status status = napi_create_int32(env, value[i], &ele);
463         if (status != napi_ok) {
464             NETMANAGER_BASE_LOGE("failed to create int32!");
465             return status;
466         }
467         status = napi_set_element(env, array, i, ele);
468         if (status != napi_ok) {
469             NETMANAGER_BASE_LOGE("failed to set element, status: %{public}d!", status);
470             return status;
471         }
472     }
473     if (napi_set_named_property(env, object, name.c_str(), array) != napi_ok) {
474         NETMANAGER_BASE_LOGE("failed to set %{public}s named property!", name.c_str());
475     }
476     return status;
477 }
478 
GetVectorUint8Property(napi_env env,napi_value object,const std::string & propertyName,std::vector<uint8_t> & vec)479 bool GetVectorUint8Property(napi_env env, napi_value object, const std::string &propertyName,
480     std::vector<uint8_t> &vec)
481 {
482     bool hasProperty = false;
483     uint32_t length = 0;
484     NAPI_CALL_BASE(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty), {});
485     napi_value fieldvalue;
486     if (!hasProperty || napi_get_named_property(env, object, propertyName.c_str(), &fieldvalue) != napi_ok) {
487         NETMANAGER_BASE_LOGE("GetVectorUint8Property, no property: %{public}s", propertyName.c_str());
488         return false;
489     }
490     NAPI_CALL_BASE(env, napi_get_array_length(env, fieldvalue, &length), false);
491     vec.reserve(length);
492     for (size_t i = 0; i < length; ++i) {
493         napi_value element;
494         NAPI_CALL_BASE(env, napi_get_element(env, fieldvalue, i, &element), false);
495         int32_t result = 0;
496         NAPI_CALL_BASE(env, napi_get_value_int32(env, element, &result), false);
497         if (result > 0xFF || result < 0) {
498             return napi_invalid_arg;
499         }
500         vec.emplace_back(static_cast<uint8_t>(result));
501     }
502     return true;
503 }
504 
505 /* array buffer */
ValueIsArrayBuffer(napi_env env,napi_value value)506 bool ValueIsArrayBuffer(napi_env env, napi_value value)
507 {
508     bool isArrayBuffer = false;
509     NAPI_CALL_BASE(env, napi_is_arraybuffer(env, value, &isArrayBuffer), false);
510     return isArrayBuffer;
511 }
512 
GetInfoFromArrayBufferValue(napi_env env,napi_value value,size_t * length)513 void *GetInfoFromArrayBufferValue(napi_env env, napi_value value, size_t *length)
514 {
515     if (length == nullptr) {
516         return nullptr;
517     }
518 
519     void *data = nullptr;
520     NAPI_CALL(env, napi_get_arraybuffer_info(env, value, &data, length));
521     return data;
522 }
523 
CreateArrayBuffer(napi_env env,size_t length,void ** data)524 napi_value CreateArrayBuffer(napi_env env, size_t length, void **data)
525 {
526     if (length == 0) {
527         return nullptr;
528     }
529     napi_value result = nullptr;
530     NAPI_CALL(env, napi_create_arraybuffer(env, length, data, &result));
531     return result;
532 }
533 
534 /* object */
CreateObject(napi_env env)535 napi_value CreateObject(napi_env env)
536 {
537     napi_value object = nullptr;
538     NAPI_CALL(env, napi_create_object(env, &object));
539     return object;
540 }
541 
542 /* undefined */
GetUndefined(napi_env env)543 napi_value GetUndefined(napi_env env)
544 {
545     napi_value undefined = nullptr;
546     NAPI_CALL(env, napi_get_undefined(env, &undefined));
547     return undefined;
548 }
549 
550 /* function */
CallFunction(napi_env env,napi_value recv,napi_value func,size_t argc,const napi_value * argv)551 napi_value CallFunction(napi_env env, napi_value recv, napi_value func, size_t argc, const napi_value *argv)
552 {
553     napi_value res = nullptr;
554     NAPI_CALL(env, napi_call_function(env, recv, func, argc, argv, &res));
555     return res;
556 }
557 
CreateFunction(napi_env env,const std::string & name,napi_callback func,void * arg)558 napi_value CreateFunction(napi_env env, const std::string &name, napi_callback func, void *arg)
559 {
560     napi_value res = nullptr;
561     NAPI_CALL(env, napi_create_function(env, name.c_str(), strlen(name.c_str()), func, arg, &res));
562     return res;
563 }
564 
565 /* reference */
CreateReference(napi_env env,napi_value callback)566 napi_ref CreateReference(napi_env env, napi_value callback)
567 {
568     napi_ref callbackRef = nullptr;
569     NAPI_CALL(env, napi_create_reference(env, callback, 1, &callbackRef));
570     return callbackRef;
571 }
572 
GetReference(napi_env env,napi_ref callbackRef)573 napi_value GetReference(napi_env env, napi_ref callbackRef)
574 {
575     napi_value callback = nullptr;
576     NAPI_CALL(env, napi_get_reference_value(env, callbackRef, &callback));
577     return callback;
578 }
579 
DeleteReference(napi_env env,napi_ref callbackRef)580 void DeleteReference(napi_env env, napi_ref callbackRef)
581 {
582     (void)napi_delete_reference(env, callbackRef);
583 }
584 
585 /* boolean */
GetBooleanProperty(napi_env env,napi_value object,const std::string & propertyName)586 bool GetBooleanProperty(napi_env env, napi_value object, const std::string &propertyName)
587 {
588     if (!HasNamedProperty(env, object, propertyName)) {
589         return false;
590     }
591     napi_value value = GetNamedProperty(env, object, propertyName);
592     bool ret = false;
593     NAPI_CALL_BASE(env, napi_get_value_bool(env, value, &ret), false);
594     return ret;
595 }
596 
SetBooleanProperty(napi_env env,napi_value object,const std::string & name,bool value)597 void SetBooleanProperty(napi_env env, napi_value object, const std::string &name, bool value)
598 {
599     napi_value jsValue = nullptr;
600     NAPI_CALL_RETURN_VOID(env, napi_get_boolean(env, value, &jsValue));
601     if (GetValueType(env, jsValue) != napi_boolean) {
602         return;
603     }
604 
605     napi_set_named_property(env, object, name.c_str(), jsValue);
606 }
607 
GetBoolean(napi_env env,bool value)608 napi_value GetBoolean(napi_env env, bool value)
609 {
610     napi_value jsValue = nullptr;
611     NAPI_CALL(env, napi_get_boolean(env, value, &jsValue));
612     return jsValue;
613 }
614 
GetBooleanValue(napi_env env,napi_value value)615 bool GetBooleanValue(napi_env env, napi_value value)
616 {
617     bool ret = false;
618     NAPI_CALL_BASE(env, napi_get_value_bool(env, value, &ret), 0);
619     return ret;
620 }
621 
622 /* define properties */
DefineProperties(napi_env env,napi_value object,const std::initializer_list<napi_property_descriptor> & properties)623 void DefineProperties(napi_env env, napi_value object,
624                       const std::initializer_list<napi_property_descriptor> &properties)
625 {
626     napi_property_descriptor descriptors[properties.size()];
627     std::copy(properties.begin(), properties.end(), descriptors);
628 
629     (void)napi_define_properties(env, object, properties.size(), descriptors);
630 }
631 
632 /* array */
CreateArray(napi_env env,size_t length)633 napi_value CreateArray(napi_env env, size_t length)
634 {
635     if (length == 0) {
636         napi_value res = nullptr;
637         NAPI_CALL(env, napi_create_array(env, &res));
638         return res;
639     }
640     napi_value res = nullptr;
641     NAPI_CALL(env, napi_create_array_with_length(env, length, &res));
642     return res;
643 }
644 
SetArrayElement(napi_env env,napi_value array,uint32_t index,napi_value value)645 void SetArrayElement(napi_env env, napi_value array, uint32_t index, napi_value value)
646 {
647     (void)napi_set_element(env, array, index, value);
648 }
649 
IsArray(napi_env env,napi_value value)650 bool IsArray(napi_env env, napi_value value)
651 {
652     bool result = false;
653     NAPI_CALL_BASE(env, napi_is_array(env, value, &result), false);
654     return result;
655 }
656 
GetArrayLength(napi_env env,napi_value arr)657 uint32_t GetArrayLength(napi_env env, napi_value arr)
658 {
659     uint32_t arrayLength = 0;
660     NAPI_CALL_BASE(env, napi_get_array_length(env, arr, &arrayLength), 0);
661     return arrayLength;
662 }
663 
GetArrayElement(napi_env env,napi_value arr,uint32_t index)664 napi_value GetArrayElement(napi_env env, napi_value arr, uint32_t index)
665 {
666     napi_value elementValue = nullptr;
667     NAPI_CALL(env, napi_get_element(env, arr, index, &elementValue));
668     return elementValue;
669 }
670 
671 /* libuv */
CreateUvQueueWork(napi_env env,void * data,void (handler)(uv_work_t *,int status))672 void CreateUvQueueWork(napi_env env, void *data, void(handler)(uv_work_t *, int status))
673 {
674     uv_loop_s *loop = nullptr;
675     if (!IsEnvValid(env)) {
676         NETMANAGER_BASE_LOGE("the env is invalid");
677         return;
678     }
679     napi_get_uv_event_loop(env, &loop);
680     if (!loop) {
681         NETMANAGER_BASE_LOGE("napi get uv event loop is null");
682         return;
683     }
684     auto work = new uv_work_t;
685     work->data = data;
686 
687     int32_t ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *) {}, handler, uv_qos_default);
688     if (ret != 0) {
689         delete work;
690     }
691 }
692 
693 /* scope */
OpenScope(napi_env env)694 napi_handle_scope OpenScope(napi_env env)
695 {
696     napi_handle_scope scope = nullptr;
697     NAPI_CALL(env, napi_open_handle_scope(env, &scope));
698     return scope;
699 }
700 
CloseScope(napi_env env,napi_handle_scope scope)701 void CloseScope(napi_env env, napi_handle_scope scope)
702 {
703     (void)napi_close_handle_scope(env, scope);
704 }
705 
CreateEnumConstructor(napi_env env,napi_callback_info info)706 napi_value CreateEnumConstructor(napi_env env, napi_callback_info info)
707 {
708     napi_value thisArg = nullptr;
709     void *data = nullptr;
710     napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
711     napi_value global = nullptr;
712     napi_get_global(env, &global);
713     return thisArg;
714 }
715 
716 /* error */
CreateErrorMessage(napi_env env,int32_t errorCode,const std::string & errorMessage)717 napi_value CreateErrorMessage(napi_env env, int32_t errorCode, const std::string &errorMessage)
718 {
719     napi_value result = CreateObject(env);
720     SetNamedProperty(env, result, CODE, CreateInt32(env, errorCode));
721     SetNamedProperty(env, result, MSG, CreateStringUtf8(env, errorMessage));
722     return result;
723 }
724 
HookForEnvCleanup(void * data)725 void HookForEnvCleanup(void *data)
726 {
727     std::lock_guard<std::recursive_mutex> lock(mutexForEnv);
728     auto envWrapper = reinterpret_cast<napi_env *>(data);
729     if (envWrapper == nullptr) {
730         return;
731     }
732     auto env = *envWrapper;
733     delete envWrapper;
734     if (env == nullptr) {
735         return;
736     }
737     auto pos = unorderedSetEnv.find(env);
738     if (pos == unorderedSetEnv.end()) {
739         NETMANAGER_BASE_LOGE("The env is not in the unordered set");
740         return;
741     }
742     NETMANAGER_BASE_LOGD("env clean up, erase from the unordered set");
743     unorderedSetEnv.erase(pos);
744 }
745 
SetEnvValid(napi_env env)746 void SetEnvValid(napi_env env)
747 {
748     std::lock_guard<std::recursive_mutex> lock(mutexForEnv);
749     unorderedSetEnv.emplace(env);
750 }
751 
IsEnvValid(napi_env env)752 bool IsEnvValid(napi_env env)
753 {
754     std::lock_guard<std::recursive_mutex> lock(mutexForEnv);
755     auto pos = unorderedSetEnv.find(env);
756     if (pos == unorderedSetEnv.end()) {
757         return false;
758     }
759     return true;
760 }
761 } // namespace NapiUtils
762 } // namespace NetManagerStandard
763 } // namespace OHOS
764