• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi_utils.h"
17 
18 #include <cstdlib>
19 #include <cstring>
20 #include <initializer_list>
21 #include <memory>
22 #include <algorithm>
23 #include <new>
24 #include <string>
25 #include <vector>
26 
27 #include "securec.h"
28 #include "napi/native_api.h"
29 #include "napi/native_common.h"
30 #include "node_api.h"
31 #include "base_context.h"
32 #include "json/json.h"
33 #include "netstack_log.h"
34 
35 namespace OHOS::NetStack::NapiUtils {
36 static constexpr const char *GLOBAL_JSON = "JSON";
37 
38 static constexpr const char *GLOBAL_JSON_STRINGIFY = "stringify";
39 
40 static constexpr const char *GLOBAL_JSON_PARSE = "parse";
41 
42 static constexpr const char *CODE = "code";
43 
44 static constexpr const char *MSG = "message";
45 
GetValueType(napi_env env,napi_value value)46 napi_valuetype GetValueType(napi_env env, napi_value value)
47 {
48     if (value == nullptr) {
49         return napi_undefined;
50     }
51 
52     napi_valuetype valueType = napi_undefined;
53     NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), napi_undefined);
54     return valueType;
55 }
56 
57 /* named property */
HasNamedProperty(napi_env env,napi_value object,const std::string & propertyName)58 bool HasNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
59 {
60     if (GetValueType(env, object) != napi_object) {
61         return false;
62     }
63 
64     bool hasProperty = false;
65     NAPI_CALL_BASE(env, napi_has_named_property(env, object, propertyName.c_str(), &hasProperty), false);
66     return hasProperty;
67 }
68 
GetNamedProperty(napi_env env,napi_value object,const std::string & propertyName)69 napi_value GetNamedProperty(napi_env env, napi_value object, const std::string &propertyName)
70 {
71     if (GetValueType(env, object) != napi_object) {
72         return GetUndefined(env);
73     }
74 
75     napi_value value = nullptr;
76     NAPI_CALL(env, napi_get_named_property(env, object, propertyName.c_str(), &value));
77     return value;
78 }
79 
SetNamedProperty(napi_env env,napi_value object,const std::string & name,napi_value value)80 void SetNamedProperty(napi_env env, napi_value object, const std::string &name, napi_value value)
81 {
82     if (GetValueType(env, object) != napi_object) {
83         return;
84     }
85 
86     napi_set_named_property(env, object, name.c_str(), value);
87 }
88 
GetPropertyNames(napi_env env,napi_value object)89 std::vector<std::string> GetPropertyNames(napi_env env, napi_value object)
90 {
91     if (GetValueType(env, object) != napi_object) {
92         return {};
93     }
94 
95     std::vector<std::string> ret;
96     napi_value names = nullptr;
97     NAPI_CALL_BASE(env, napi_get_property_names(env, object, &names), ret);
98     uint32_t length = 0;
99     NAPI_CALL_BASE(env, napi_get_array_length(env, names, &length), ret);
100     for (uint32_t index = 0; index < length; ++index) {
101         napi_value name = nullptr;
102         if (napi_get_element(env, names, index, &name) != napi_ok) {
103             continue;
104         }
105         if (GetValueType(env, name) != napi_string) {
106             continue;
107         }
108         ret.emplace_back(GetStringFromValueUtf8(env, name));
109     }
110     return ret;
111 }
112 
113 /* UINT32 */
CreateUint32(napi_env env,uint32_t code)114 napi_value CreateUint32(napi_env env, uint32_t code)
115 {
116     napi_value value = nullptr;
117     if (napi_create_uint32(env, code, &value) != napi_ok) {
118         return nullptr;
119     }
120     return value;
121 }
122 
123 /* UINT64 */
CreateUint64(napi_env env,uint64_t code)124 napi_value CreateUint64(napi_env env, uint64_t code)
125 {
126     napi_value value = nullptr;
127     if (napi_create_bigint_uint64(env, code, &value) != napi_ok) {
128         return nullptr;
129     }
130     return value;
131 }
132 
GetInt64FromValue(napi_env env,napi_value value)133 int64_t GetInt64FromValue(napi_env env, napi_value value)
134 {
135     if (GetValueType(env, value) != napi_number) {
136         return 0;
137     }
138     int64_t ret = 0;
139     NAPI_CALL_BASE(env, napi_get_value_int64(env, value, &ret), 0);
140     return ret;
141 }
142 
GetInt64Property(napi_env env,napi_value object,const std::string & propertyName)143 int64_t GetInt64Property(napi_env env, napi_value object, const std::string &propertyName)
144 {
145     if (!HasNamedProperty(env, object, propertyName)) {
146         return 0;
147     }
148     napi_value value = GetNamedProperty(env, object, propertyName);
149     return GetInt64FromValue(env, value);
150 }
151 
GetUint32FromValue(napi_env env,napi_value value)152 uint32_t GetUint32FromValue(napi_env env, napi_value value)
153 {
154     if (GetValueType(env, value) != napi_number) {
155         return 0;
156     }
157 
158     uint32_t ret = 0;
159     NAPI_CALL_BASE(env, napi_get_value_uint32(env, value, &ret), 0);
160     return ret;
161 }
162 
GetUint32Property(napi_env env,napi_value object,const std::string & propertyName)163 uint32_t GetUint32Property(napi_env env, napi_value object, const std::string &propertyName)
164 {
165     if (!HasNamedProperty(env, object, propertyName)) {
166         return 0;
167     }
168     napi_value value = GetNamedProperty(env, object, propertyName);
169     return GetUint32FromValue(env, value);
170 }
171 
SetUint32Property(napi_env env,napi_value object,const std::string & name,uint32_t value)172 void SetUint32Property(napi_env env, napi_value object, const std::string &name, uint32_t value)
173 {
174     napi_value jsValue = CreateUint32(env, value);
175     if (GetValueType(env, jsValue) != napi_number) {
176         return;
177     }
178 
179     napi_set_named_property(env, object, name.c_str(), jsValue);
180 }
181 
SetUint64Property(napi_env env,napi_value object,const std::string & name,uint64_t value)182 void SetUint64Property(napi_env env, napi_value object, const std::string &name, uint64_t value)
183 {
184     napi_value jsValue = CreateUint64(env, value);
185     if (GetValueType(env, jsValue) != napi_bigint) {
186         return;
187     }
188 
189     napi_set_named_property(env, object, name.c_str(), jsValue);
190 }
191 
192 /* INT32 */
CreateInt32(napi_env env,int32_t code)193 napi_value CreateInt32(napi_env env, int32_t code)
194 {
195     napi_value value = nullptr;
196     if (napi_create_int32(env, code, &value) != napi_ok) {
197         return nullptr;
198     }
199     return value;
200 }
201 
GetInt32FromValue(napi_env env,napi_value value)202 int32_t GetInt32FromValue(napi_env env, napi_value value)
203 {
204     if (GetValueType(env, value) != napi_number) {
205         return 0;
206     }
207 
208     int32_t ret = 0;
209     NAPI_CALL_BASE(env, napi_get_value_int32(env, value, &ret), 0);
210     return ret;
211 }
212 
GetInt32Property(napi_env env,napi_value object,const std::string & propertyName)213 int32_t GetInt32Property(napi_env env, napi_value object, const std::string &propertyName)
214 {
215     if (!HasNamedProperty(env, object, propertyName)) {
216         return 0;
217     }
218     napi_value value = GetNamedProperty(env, object, propertyName);
219     return GetInt32FromValue(env, value);
220 }
221 
SetInt32Property(napi_env env,napi_value object,const std::string & name,int32_t value)222 void SetInt32Property(napi_env env, napi_value object, const std::string &name, int32_t value)
223 {
224     napi_value jsValue = CreateInt32(env, value);
225     if (GetValueType(env, jsValue) != napi_number) {
226         return;
227     }
228 
229     napi_set_named_property(env, object, name.c_str(), jsValue);
230 }
231 
SetDoubleProperty(napi_env env,napi_value object,const std::string & name,double value)232 void SetDoubleProperty(napi_env env, napi_value object, const std::string &name, double value)
233 {
234     napi_value jsValue;
235     if (napi_create_double(env, value, &jsValue) != napi_ok) {
236         return;
237     }
238     if (GetValueType(env, jsValue) != napi_number) {
239         return;
240     }
241     napi_set_named_property(env, object, name.c_str(), jsValue);
242 }
243 
244 /* String UTF8 */
CreateStringUtf8(napi_env env,const std::string & str)245 napi_value CreateStringUtf8(napi_env env, const std::string &str)
246 {
247     napi_value value = nullptr;
248     if (napi_create_string_utf8(env, str.c_str(), strlen(str.c_str()), &value) != napi_ok) {
249         return nullptr;
250     }
251     return value;
252 }
253 
GetStringFromValueUtf8(napi_env env,napi_value value)254 std::string GetStringFromValueUtf8(napi_env env, napi_value value)
255 {
256     if (GetValueType(env, value) != napi_string) {
257         return {};
258     }
259 
260     std::string result;
261     size_t stringLength = 0;
262     NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, value, nullptr, 0, &stringLength), result);
263     if (stringLength == 0) {
264         return result;
265     }
266 
267     auto deleter = [](char *s) { free(reinterpret_cast<void *>(s)); };
268     std::unique_ptr<char, decltype(deleter)> str(static_cast<char *>(malloc(stringLength + 1)), deleter);
269     if (memset_s(str.get(), stringLength + 1, 0, stringLength + 1) != EOK) {
270         return result;
271     }
272     size_t length = 0;
273     NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, value, str.get(), stringLength + 1, &length), result);
274     if (length > 0) {
275         result.append(str.get(), length);
276     }
277     return result;
278 }
279 
GetStringPropertyUtf8(napi_env env,napi_value object,const std::string & propertyName)280 std::string GetStringPropertyUtf8(napi_env env, napi_value object, const std::string &propertyName)
281 {
282     if (!HasNamedProperty(env, object, propertyName)) {
283         return "";
284     }
285     napi_value value = GetNamedProperty(env, object, propertyName);
286     return GetStringFromValueUtf8(env, value);
287 }
288 
NapiValueToString(napi_env env,napi_value value)289 std::string NapiValueToString(napi_env env, napi_value value)
290 {
291     napi_status status;
292     napi_valuetype valueType;
293     status = napi_typeof(env, value, &valueType);
294     if (status != napi_ok) {
295         return "";
296     }
297     switch (valueType) {
298         case napi_undefined:
299         case napi_null:
300             break;
301         case napi_boolean:
302             bool boolValue;
303             status = napi_get_value_bool(env, value, &boolValue);
304             if (status == napi_ok) {
305                 return boolValue ? "true" : "false";
306             }
307             break;
308         case napi_number:
309             double doubleValue;
310             status = napi_get_value_double(env, value, &doubleValue);
311             if (status == napi_ok) {
312                 if (doubleValue == std::floor(doubleValue)) {
313                     return std::to_string(static_cast<int>(doubleValue));
314                 }
315                 return std::to_string(doubleValue);
316             }
317             break;
318         case napi_string:
319             return GetStringFromValueUtf8(env, value);
320         default:
321             break;
322     }
323     return "";
324 }
325 
SetStringPropertyUtf8(napi_env env,napi_value object,const std::string & name,const std::string & value)326 void SetStringPropertyUtf8(napi_env env, napi_value object, const std::string &name, const std::string &value)
327 {
328     napi_value jsValue = CreateStringUtf8(env, value);
329     if (GetValueType(env, jsValue) != napi_string) {
330         return;
331     }
332     napi_set_named_property(env, object, name.c_str(), jsValue);
333 }
334 
335 /* array buffer */
ValueIsArrayBuffer(napi_env env,napi_value value)336 bool ValueIsArrayBuffer(napi_env env, napi_value value)
337 {
338     if (value == nullptr) {
339         return false;
340     }
341     bool isArrayBuffer = false;
342     NAPI_CALL_BASE(env, napi_is_arraybuffer(env, value, &isArrayBuffer), false);
343     return isArrayBuffer;
344 }
345 
GetInfoFromArrayBufferValue(napi_env env,napi_value value,size_t * length)346 void *GetInfoFromArrayBufferValue(napi_env env, napi_value value, size_t *length)
347 {
348     if (length == nullptr) {
349         return nullptr;
350     }
351 
352     void *data = nullptr;
353     NAPI_CALL(env, napi_get_arraybuffer_info(env, value, &data, length));
354     return data;
355 }
356 
CreateArrayBuffer(napi_env env,size_t length,void ** data)357 napi_value CreateArrayBuffer(napi_env env, size_t length, void **data)
358 {
359     if (length == 0) {
360         return nullptr;
361     }
362     napi_value result = nullptr;
363     NAPI_CALL(env, napi_create_arraybuffer(env, length, data, &result));
364     return result;
365 }
366 
367 /* object */
CreateObject(napi_env env)368 napi_value CreateObject(napi_env env)
369 {
370     napi_value object = nullptr;
371     NAPI_CALL(env, napi_create_object(env, &object));
372     return object;
373 }
374 
375 /* undefined */
GetUndefined(napi_env env)376 napi_value GetUndefined(napi_env env)
377 {
378     napi_value undefined = nullptr;
379     NAPI_CALL(env, napi_get_undefined(env, &undefined));
380     return undefined;
381 }
382 
383 /* function */
CallFunction(napi_env env,napi_value recv,napi_value func,size_t argc,const napi_value * argv)384 napi_value CallFunction(napi_env env, napi_value recv, napi_value func, size_t argc, const napi_value *argv)
385 {
386     napi_value res = nullptr;
387     NAPI_CALL(env, napi_call_function(env, recv, func, argc, argv, &res));
388     return res;
389 }
390 
CreateFunction(napi_env env,const std::string & name,napi_callback func,void * arg)391 napi_value CreateFunction(napi_env env, const std::string &name, napi_callback func, void *arg)
392 {
393     napi_value res = nullptr;
394     NAPI_CALL(env, napi_create_function(env, name.c_str(), strlen(name.c_str()), func, arg, &res));
395     return res;
396 }
397 
398 /* reference */
CreateReference(napi_env env,napi_value callback)399 napi_ref CreateReference(napi_env env, napi_value callback)
400 {
401     napi_ref callbackRef = nullptr;
402     NAPI_CALL(env, napi_create_reference(env, callback, 1, &callbackRef));
403     return callbackRef;
404 }
405 
GetReference(napi_env env,napi_ref callbackRef)406 napi_value GetReference(napi_env env, napi_ref callbackRef)
407 {
408     napi_value callback = nullptr;
409     NAPI_CALL(env, napi_get_reference_value(env, callbackRef, &callback));
410     return callback;
411 }
412 
DeleteReference(napi_env env,napi_ref callbackRef)413 void DeleteReference(napi_env env, napi_ref callbackRef)
414 {
415     (void)napi_delete_reference(env, callbackRef);
416 }
417 
418 /* boolean */
GetBooleanProperty(napi_env env,napi_value object,const std::string & propertyName)419 bool GetBooleanProperty(napi_env env, napi_value object, const std::string &propertyName)
420 {
421     if (!HasNamedProperty(env, object, propertyName)) {
422         return false;
423     }
424     napi_value value = GetNamedProperty(env, object, propertyName);
425     bool ret = false;
426     NAPI_CALL_BASE(env, napi_get_value_bool(env, value, &ret), false);
427     return ret;
428 }
429 
SetBooleanProperty(napi_env env,napi_value object,const std::string & name,bool value)430 void SetBooleanProperty(napi_env env, napi_value object, const std::string &name, bool value)
431 {
432     napi_value jsValue = nullptr;
433     NAPI_CALL_RETURN_VOID(env, napi_get_boolean(env, value, &jsValue));
434     if (GetValueType(env, jsValue) != napi_boolean) {
435         return;
436     }
437 
438     napi_set_named_property(env, object, name.c_str(), jsValue);
439 }
440 
GetBoolean(napi_env env,bool value)441 napi_value GetBoolean(napi_env env, bool value)
442 {
443     napi_value jsValue = nullptr;
444     NAPI_CALL(env, napi_get_boolean(env, value, &jsValue));
445     return jsValue;
446 }
447 
GetBooleanFromValue(napi_env env,napi_value value)448 bool GetBooleanFromValue(napi_env env, napi_value value)
449 {
450     if (GetValueType(env, value) != napi_boolean) {
451         return GetUndefined(env);
452     }
453 
454     bool ret = false;
455     NAPI_CALL_BASE(env, napi_get_value_bool(env, value, &ret), false);
456     return ret;
457 }
458 
459 /* define properties */
DefineProperties(napi_env env,napi_value object,const std::initializer_list<napi_property_descriptor> & properties)460 void DefineProperties(napi_env env, napi_value object,
461                       const std::initializer_list<napi_property_descriptor> &properties)
462 {
463     napi_property_descriptor descriptors[properties.size()];
464     std::copy(properties.begin(), properties.end(), descriptors);
465 
466     (void)napi_define_properties(env, object, properties.size(), descriptors);
467 }
468 
469 /* array */
CreateArray(napi_env env,size_t length)470 napi_value CreateArray(napi_env env, size_t length)
471 {
472     if (length == 0) {
473         napi_value res = nullptr;
474         NAPI_CALL(env, napi_create_array(env, &res));
475         return res;
476     }
477     napi_value res = nullptr;
478     NAPI_CALL(env, napi_create_array_with_length(env, length, &res));
479     return res;
480 }
481 
SetArrayElement(napi_env env,napi_value array,uint32_t index,napi_value value)482 void SetArrayElement(napi_env env, napi_value array, uint32_t index, napi_value value)
483 {
484     (void)napi_set_element(env, array, index, value);
485 }
486 
IsArray(napi_env env,napi_value value)487 bool IsArray(napi_env env, napi_value value)
488 {
489     bool result = false;
490     NAPI_CALL_BASE(env, napi_is_array(env, value, &result), false);
491     return result;
492 }
493 
SetArrayProperty(napi_env env,napi_value object,const std::string & name,napi_value value)494 void SetArrayProperty(napi_env env, napi_value object, const std::string &name, napi_value value)
495 {
496     if (!IsArray(env, value)) {
497         return;
498     }
499     napi_set_named_property(env, object, name.c_str(), value);
500 }
501 
GetArrayLength(napi_env env,napi_value arr)502 uint32_t GetArrayLength(napi_env env, napi_value arr)
503 {
504     uint32_t arrayLength = 0;
505     NAPI_CALL_BASE(env, napi_get_array_length(env, arr, &arrayLength), 0);
506     return arrayLength;
507 }
508 
GetArrayElement(napi_env env,napi_value arr,uint32_t index)509 napi_value GetArrayElement(napi_env env, napi_value arr, uint32_t index)
510 {
511     napi_value elementValue = nullptr;
512     NAPI_CALL(env, napi_get_element(env, arr, index, &elementValue));
513     return elementValue;
514 }
515 
516 /* JSON */
JsonStringify(napi_env env,napi_value object)517 napi_value JsonStringify(napi_env env, napi_value object)
518 {
519     napi_value undefined = GetUndefined(env);
520 
521     if (GetValueType(env, object) != napi_object) {
522         return undefined;
523     }
524 
525     napi_value global = nullptr;
526     NAPI_CALL_BASE(env, napi_get_global(env, &global), undefined);
527     napi_value json = nullptr;
528     NAPI_CALL_BASE(env, napi_get_named_property(env, global, GLOBAL_JSON, &json), undefined);
529     napi_value stringify = nullptr;
530     NAPI_CALL_BASE(env, napi_get_named_property(env, json, GLOBAL_JSON_STRINGIFY, &stringify), undefined);
531     if (GetValueType(env, stringify) != napi_function) {
532         return undefined;
533     }
534 
535     napi_value res = nullptr;
536     napi_value argv[1] = {object};
537     NAPI_CALL_BASE(env, napi_call_function(env, json, stringify, 1, argv, &res), undefined);
538     return res;
539 }
540 
JsonParse(napi_env env,const std::string & inStr)541 napi_value JsonParse(napi_env env, const std::string &inStr)
542 {
543     napi_value undefined = GetUndefined(env);
544     JSONCPP_STRING err;
545     Json::Value valueJson;
546     Json::CharReaderBuilder readerBuilder;
547     std::unique_ptr<Json::CharReader> const jsonReader(readerBuilder.newCharReader());
548     bool ret = jsonReader->parse(inStr.c_str(), inStr.c_str() + inStr.length(), &valueJson, &err);
549     if (!ret || !err.empty()) {
550         return undefined;
551     }
552 
553     auto str = NapiUtils::CreateStringUtf8(env, inStr);
554     if (GetValueType(env, str) != napi_string) {
555         return undefined;
556     }
557 
558     napi_value global = nullptr;
559     NAPI_CALL_BASE(env, napi_get_global(env, &global), undefined);
560     napi_value json = nullptr;
561     NAPI_CALL_BASE(env, napi_get_named_property(env, global, GLOBAL_JSON, &json), undefined);
562     napi_value parse = nullptr;
563     NAPI_CALL_BASE(env, napi_get_named_property(env, json, GLOBAL_JSON_PARSE, &parse), undefined);
564     if (GetValueType(env, parse) != napi_function) {
565         return undefined;
566     }
567 
568     napi_value res = nullptr;
569     napi_value argv[1] = {str};
570     NAPI_CALL_BASE(env, napi_call_function(env, json, parse, 1, argv, &res), undefined);
571     return res;
572 }
573 
574 /* libuv */
CreateUvQueueWork(napi_env env,void * data,void (handler)(uv_work_t *,int status))575 void CreateUvQueueWork(napi_env env, void *data, void(handler)(uv_work_t *, int status))
576 {
577     uv_loop_s *loop = nullptr;
578     NAPI_CALL_RETURN_VOID(env, napi_get_uv_event_loop(env, &loop));
579 
580     auto work = new uv_work_t;
581     work->data = data;
582 
583     int ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *) {}, handler, uv_qos_default);
584     if (ret != 0) {
585         NETSTACK_LOGE("uv_queue_work_with_qos error = %{public}d, manual delete", ret);
586         delete static_cast<UvWorkWrapper *>(work->data);
587         delete work;
588     }
589 }
590 
591 /* scope */
OpenScope(napi_env env)592 napi_handle_scope OpenScope(napi_env env)
593 {
594     napi_handle_scope scope = nullptr;
595     NAPI_CALL(env, napi_open_handle_scope(env, &scope));
596     return scope;
597 }
598 
CloseScope(napi_env env,napi_handle_scope scope)599 void CloseScope(napi_env env, napi_handle_scope scope)
600 {
601     (void)napi_close_handle_scope(env, scope);
602 }
603 
CreateUvQueueWorkEnhanced(napi_env env,void * data,void (* handler)(napi_env env,napi_status status,void * data))604 void CreateUvQueueWorkEnhanced(napi_env env, void *data, void (*handler)(napi_env env, napi_status status, void *data))
605 {
606     uv_loop_s *loop = nullptr;
607     NAPI_CALL_RETURN_VOID(env, napi_get_uv_event_loop(env, &loop));
608 
609     if (loop == nullptr) {
610         return;
611     }
612 
613     class WorkData {
614     public:
615         WorkData() = delete;
616 
617         WorkData(napi_env env, void *data, void (*handler)(napi_env env, napi_status status, void *data))
618             : env_(env), data_(data), handler_(handler)
619         {
620         }
621 
622         napi_env env_;
623         void *data_;
624         void (*handler_)(napi_env env, napi_status status, void *data);
625     };
626 
627     auto workData = new WorkData(env, data, handler);
628 
629     auto work = new (std::nothrow) uv_work_t;
630     if (work == nullptr) {
631         return;
632     }
633     work->data = reinterpret_cast<void *>(workData);
634 
635     auto callback = [](uv_work_t *work, int status) {
636         auto workData = static_cast<WorkData *>(work->data);
637         if (!workData) {
638             delete work;
639             return;
640         }
641 
642         if (!workData->env_ || !workData->data_ || !workData->handler_) {
643             delete workData;
644             delete work;
645             return;
646         }
647 
648         napi_env env = workData->env_;
649         auto closeScope = [env](napi_handle_scope scope) { NapiUtils::CloseScope(env, scope); };
650         std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scope(NapiUtils::OpenScope(env), closeScope);
651 
652         workData->handler_(workData->env_, static_cast<napi_status>(status), workData->data_);
653 
654         delete workData;
655         delete work;
656     };
657 
658     int ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *) {}, callback, uv_qos_default);
659     if (ret != 0) {
660         NETSTACK_LOGE("uv_queue_work_with_qos error = %{public}d, manual release", ret);
661         delete static_cast<WorkData *>(work->data);
662         delete work;
663     }
664 }
665 
666 /* error */
CreateErrorMessage(napi_env env,int32_t errorCode,const std::string & errorMessage)667 napi_value CreateErrorMessage(napi_env env, int32_t errorCode, const std::string &errorMessage)
668 {
669     napi_value result = nullptr;
670     result = CreateObject(env);
671     SetNamedProperty(env, result, CODE, CreateInt32(env, errorCode));
672     SetNamedProperty(env, result, MSG, CreateStringUtf8(env, errorMessage));
673     return result;
674 }
675 
GetGlobal(napi_env env)676 napi_value GetGlobal(napi_env env)
677 {
678     napi_value undefined = GetUndefined(env);
679     napi_value global = nullptr;
680     NAPI_CALL_BASE(env, napi_get_global(env, &global), undefined);
681     return global;
682 }
683 } // namespace OHOS::NetStack::NapiUtils
684