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