• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "distributed_bundle_mgr.h"
16 
17 #include <string>
18 
19 #include "app_log_wrapper.h"
20 #include "appexecfwk_errors.h"
21 #include "bundle_constants.h"
22 #include "distributed_bms_interface.h"
23 #include "distributed_bms_proxy.h"
24 #include "if_system_ability_manager.h"
25 #include "ipc_skeleton.h"
26 #include "iservice_registry.h"
27 #include "napi/native_api.h"
28 #include "napi/native_node_api.h"
29 #include "securec.h"
30 #include "system_ability_definition.h"
31 
32 namespace OHOS {
33 namespace AppExecFwk {
34 using namespace OHOS;
35 using namespace OHOS::AppExecFwk;
36 
37 namespace {
38 constexpr size_t ARGS_SIZE_ONE = 1;
39 constexpr size_t ARGS_SIZE_THREE = 3;
40 constexpr int32_t PARAM0 = 0;
41 constexpr int32_t PARAM1 = 1;
42 constexpr int32_t PARAM2 = 2;
43 constexpr int32_t NAPI_RETURN_ZERO = 0;
44 constexpr int32_t NAPI_RETURN_ONE = 1;
45 constexpr int32_t GET_REMOTE_ABILITY_INFO_MAX_SIZE = 10;
46 enum GetRemoteAbilityInfoErrorCode : int32_t {
47     SUCCESS = 0,
48     ERR_INNER_ERROR,
49     ERR_INVALID_PARAM,
50     ERR_PARAMETERS_MORE_THAN_MAX,
51     ERR_RPC_ERROR,
52 };
53 }
54 
AsyncWorkData(napi_env napiEnv)55 AsyncWorkData::AsyncWorkData(napi_env napiEnv) : env(napiEnv) {}
56 
~AsyncWorkData()57 AsyncWorkData::~AsyncWorkData()
58 {
59     if (callbackRef) {
60         APP_LOGD("AsyncWorkData::~AsyncWorkData delete callbackRef");
61         napi_delete_reference(env, callbackRef);
62         callbackRef = nullptr;
63     }
64     if (asyncWork) {
65         APP_LOGD("AsyncWorkData::~AsyncWorkData delete asyncWork");
66         napi_delete_async_work(env, asyncWork);
67         asyncWork = nullptr;
68     }
69 }
70 
GetDistributedBundleMgr()71 static OHOS::sptr<OHOS::AppExecFwk::IDistributedBms> GetDistributedBundleMgr()
72 {
73     APP_LOGI("GetDistributedBundleMgr");
74     auto samgr = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
75     // OHOS::sptr<OHOS::IRemoteObject> remoteObject;
76     auto remoteObject = samgr->GetSystemAbility(OHOS::DISTRIBUTED_BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
77     return OHOS::iface_cast<IDistributedBms>(remoteObject);
78 }
79 
GetStringFromNAPI(napi_env env,napi_value value)80 static std::string GetStringFromNAPI(napi_env env, napi_value value)
81 {
82     std::string result;
83     size_t size = 0;
84 
85     if (napi_get_value_string_utf8(env, value, nullptr, NAPI_RETURN_ZERO, &size) != napi_ok) {
86         APP_LOGE("can not get string size");
87         return "";
88     }
89     result.reserve(size + NAPI_RETURN_ONE);
90     result.resize(size);
91     if (napi_get_value_string_utf8(env, value, result.data(), (size + NAPI_RETURN_ONE), &size) != napi_ok) {
92         APP_LOGE("can not get string value");
93         return "";
94     }
95     return result;
96 }
97 
ParseString(napi_env env,std::string & param,napi_value args)98 static napi_value ParseString(napi_env env, std::string &param, napi_value args)
99 {
100     napi_status status;
101     napi_valuetype valuetype;
102     NAPI_CALL(env, napi_typeof(env, args, &valuetype));
103     NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type. String expected.");
104     param = GetStringFromNAPI(env, args);
105     APP_LOGD("param=%{public}s.", param.c_str());
106     napi_value result;
107     status = napi_create_int32(env, NAPI_RETURN_ONE, &result);
108     NAPI_ASSERT(env, status == napi_ok, "napi_create_int32 error!");
109     return result;
110 }
111 
ConvertResultCode(int32_t code)112 static int32_t ConvertResultCode(int32_t code)
113 {
114     APP_LOGD("ConvertResultCode resultCode:%{public}d", code);
115     switch (code) {
116         case SUCCESS:
117             return SUCCESS;
118         case ERR_APPEXECFWK_FAILED_GET_REMOTE_PROXY:
119             return ERR_RPC_ERROR;
120         default:
121             break;
122     }
123     return ERR_INNER_ERROR;
124 }
125 
ConvertElementName(napi_env env,napi_value objElementName,const ElementName & elementName)126 static void ConvertElementName(napi_env env, napi_value objElementName, const ElementName &elementName)
127 {
128     napi_value nDeviceId;
129     NAPI_CALL_RETURN_VOID(
130         env, napi_create_string_utf8(env, elementName.GetDeviceID().c_str(), NAPI_AUTO_LENGTH, &nDeviceId));
131     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "deviceId", nDeviceId));
132 
133     napi_value nBundleName;
134     NAPI_CALL_RETURN_VOID(
135         env, napi_create_string_utf8(env, elementName.GetBundleName().c_str(), NAPI_AUTO_LENGTH, &nBundleName));
136     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "bundleName", nBundleName));
137 
138     napi_value nModuleName;
139     NAPI_CALL_RETURN_VOID(
140         env, napi_create_string_utf8(env, elementName.GetModuleName().c_str(), NAPI_AUTO_LENGTH, &nModuleName));
141     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "moduleName", nModuleName));
142 
143     napi_value nAbilityName;
144     NAPI_CALL_RETURN_VOID(
145         env, napi_create_string_utf8(env, elementName.GetAbilityName().c_str(), NAPI_AUTO_LENGTH, &nAbilityName));
146     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "abilityName", nAbilityName));
147 }
148 
ConvertRemoteAbilityInfo(napi_env env,napi_value objRemoteAbilityInfo,const RemoteAbilityInfo & remoteAbilityInfo)149 static void ConvertRemoteAbilityInfo(
150     napi_env env, napi_value objRemoteAbilityInfo, const RemoteAbilityInfo &remoteAbilityInfo)
151 {
152     napi_value objElementName;
153     NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objElementName));
154     ConvertElementName(env, objElementName, remoteAbilityInfo.elementName);
155     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRemoteAbilityInfo, "elementName", objElementName));
156 
157     napi_value nLabel;
158     NAPI_CALL_RETURN_VOID(
159         env, napi_create_string_utf8(env, remoteAbilityInfo.label.c_str(), NAPI_AUTO_LENGTH, &nLabel));
160     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRemoteAbilityInfo, "label", nLabel));
161 
162     napi_value nIcon;
163     NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, remoteAbilityInfo.icon.c_str(), NAPI_AUTO_LENGTH, &nIcon));
164     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRemoteAbilityInfo, "icon", nIcon));
165 }
166 
ConvertRemoteAbilityInfos(napi_env env,napi_value objRemoteAbilityInfos,const std::vector<RemoteAbilityInfo> & remoteAbilityInfos)167 static void ConvertRemoteAbilityInfos(
168     napi_env env, napi_value objRemoteAbilityInfos, const std::vector<RemoteAbilityInfo> &remoteAbilityInfos)
169 {
170     if (remoteAbilityInfos.size() == 0) {
171         APP_LOGE("ConvertRemoteAbilityInfos remoteAbilityInfos is empty");
172         return;
173     }
174     size_t index = 0;
175     for (const auto &remoteAbilityInfo : remoteAbilityInfos) {
176         APP_LOGD("remoteAbilityInfo bundleName:%{public}s, abilityName:%{public}s, label:%{public}s",
177                  remoteAbilityInfo.elementName.GetBundleName().c_str(),
178                  remoteAbilityInfo.elementName.GetAbilityName().c_str(),
179                  remoteAbilityInfo.label.c_str());
180         napi_value objRemoteAbilityInfo = nullptr;
181         NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objRemoteAbilityInfo));
182         ConvertRemoteAbilityInfo(env, objRemoteAbilityInfo, remoteAbilityInfo);
183         NAPI_CALL_RETURN_VOID(env, napi_set_element(env, objRemoteAbilityInfos, index, objRemoteAbilityInfo));
184         index++;
185     }
186 }
187 
ParseModuleName(napi_env env,std::string & moduleName,napi_value args)188 static bool ParseModuleName(napi_env env, std::string &moduleName, napi_value args)
189 {
190     napi_status status;
191     napi_valuetype valueType;
192     napi_value prop = nullptr;
193     bool hasKey = false;
194     napi_has_named_property(env, args, "moduleName", &hasKey);
195     if (hasKey) {
196         status = napi_get_named_property(env, args, "moduleName", &prop);
197         napi_typeof(env, prop, &valueType);
198         if ((status == napi_ok) && (valueType == napi_string)) {
199             moduleName = GetStringFromNAPI(env, prop);
200         } else {
201             APP_LOGE("begin to parse ElementName moduleName failed");
202             return false;
203         }
204     }
205     return true;
206 }
207 
ParseElementName(napi_env env,OHOS::AppExecFwk::ElementName & elementName,napi_value args)208 static bool ParseElementName(napi_env env, OHOS::AppExecFwk::ElementName &elementName, napi_value args)
209 {
210     APP_LOGD("begin to parse ElementName");
211     napi_status status;
212     napi_valuetype valueType;
213     NAPI_CALL_BASE(env, napi_typeof(env, args, &valueType), false);
214     if (valueType != napi_object) {
215         APP_LOGE("args not object type");
216         return false;
217     }
218     napi_value prop = nullptr;
219     status = napi_get_named_property(env, args, "deviceId", &prop);
220     napi_typeof(env, prop, &valueType);
221     if (status == napi_ok && valueType == napi_string) {
222         elementName.SetDeviceID(GetStringFromNAPI(env, prop));
223     } else {
224         APP_LOGE("begin to parse ElementName deviceId failed");
225         return false;
226     }
227     prop = nullptr;
228     status = napi_get_named_property(env, args, "bundleName", &prop);
229     napi_typeof(env, prop, &valueType);
230     if (status == napi_ok && valueType == napi_string) {
231         elementName.SetBundleName(GetStringFromNAPI(env, prop));
232     } else {
233         APP_LOGE("begin to parse ElementName bundleName failed");
234         return false;
235     }
236     prop = nullptr;
237     status = napi_get_named_property(env, args, "abilityName", &prop);
238     napi_typeof(env, prop, &valueType);
239     if (status == napi_ok && valueType == napi_string) {
240         elementName.SetAbilityName(GetStringFromNAPI(env, prop));
241     } else {
242         APP_LOGE("begin to parse ElementName abilityName failed");
243         return false;
244     }
245     std::string moduleName;
246     if (!ParseModuleName(env, moduleName, args)) {
247         return false;
248     }
249     elementName.SetModuleName(moduleName);
250     APP_LOGD("parse ElementName end");
251     return true;
252 }
253 
ParseElementNames(napi_env env,std::vector<ElementName> & elementNames,napi_value args)254 static bool ParseElementNames(napi_env env, std::vector<ElementName> &elementNames, napi_value args)
255 {
256     APP_LOGD("begin to parse ElementNames");
257     bool isArray = false;
258     NAPI_CALL_BASE(env, napi_is_array(env, args, &isArray), false);
259     if (!isArray) {
260         APP_LOGE("parseElementNames args not array");
261         return false;
262     }
263     uint32_t arrayLength = 0;
264     NAPI_CALL_BASE(env, napi_get_array_length(env, args, &arrayLength), false);
265     APP_LOGD("arrayLength:%{public}d", arrayLength);
266     for (uint32_t i = 0; i < arrayLength; i++) {
267         napi_value value = nullptr;
268         NAPI_CALL_BASE(env, napi_get_element(env, args, i, &value), false);
269         napi_valuetype valueType = napi_undefined;
270         NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), false);
271         if (valueType != napi_object) {
272             APP_LOGE("array inside not object type");
273             elementNames.clear();
274             return false;
275         }
276         ElementName elementName;
277         if (ParseElementName(env, elementName, value)) {
278             elementNames.push_back(elementName);
279         } else {
280             APP_LOGE("elementNames parse elementName failed");
281             return false;
282         }
283     }
284     return true;
285 }
286 
InnerGetRemoteAbilityInfo(const OHOS::AppExecFwk::ElementName & elementName,const std::string & locale,RemoteAbilityInfo & remoteAbilityInfo)287 static int32_t InnerGetRemoteAbilityInfo(
288     const OHOS::AppExecFwk::ElementName &elementName, const std::string &locale, RemoteAbilityInfo &remoteAbilityInfo)
289 {
290     auto iDistBundleMgr = GetDistributedBundleMgr();
291     if (!iDistBundleMgr) {
292         APP_LOGE("can not get iDistBundleMgr");
293         return ERR_INNER_ERROR;
294     }
295     int32_t result = iDistBundleMgr->GetRemoteAbilityInfo(elementName, locale, remoteAbilityInfo);
296     if (result != 0) {
297         APP_LOGE("InnerGetRemoteAbilityInfo failed");
298     }
299     return ConvertResultCode(result);
300 }
301 
InnerGetRemoteAbilityInfos(const std::vector<ElementName> & elementNames,const std::string & locale,std::vector<RemoteAbilityInfo> & remoteAbilityInfos)302 static int32_t InnerGetRemoteAbilityInfos(const std::vector<ElementName> &elementNames, const std::string &locale,
303     std::vector<RemoteAbilityInfo> &remoteAbilityInfos)
304 {
305     if (elementNames.size() == 0) {
306         APP_LOGE("InnerGetRemoteAbilityInfos elementNames is empty");
307         return ERR_INVALID_PARAM;
308     }
309     auto iDistBundleMgr = GetDistributedBundleMgr();
310     if (!iDistBundleMgr) {
311         APP_LOGE("can not get iDistBundleMgr");
312         return ERR_INNER_ERROR;
313     }
314     int32_t result = iDistBundleMgr->GetRemoteAbilityInfos(elementNames, locale, remoteAbilityInfos);
315     if (result != 0) {
316         APP_LOGE("InnerGetRemoteAbilityInfo failed");
317     }
318     return ConvertResultCode(result);
319 }
320 
GetRemoteAbilityInfo(napi_env env,napi_callback_info info)321 napi_value GetRemoteAbilityInfo(napi_env env, napi_callback_info info)
322 {
323     size_t requireArgc = ARGS_SIZE_ONE;
324     size_t argc = ARGS_SIZE_THREE;
325     napi_value argv[ARGS_SIZE_THREE] = { 0 };
326     napi_value thisArg = nullptr;
327     void *data = nullptr;
328 
329     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisArg, &data));
330     NAPI_ASSERT(env, argc >= requireArgc, "requires 1 parameter");
331 
332     ElementNameInfo *asyncCallbackInfo = new (std::nothrow) ElementNameInfo(env);
333     if (asyncCallbackInfo == nullptr) {
334         return nullptr;
335     }
336     std::unique_ptr<ElementNameInfo> callbackPtr {asyncCallbackInfo};
337     for (size_t i = 0; i < argc; ++i) {
338         napi_valuetype valueType = napi_undefined;
339         NAPI_CALL(env, napi_typeof(env, argv[i], &valueType));
340         if ((i == PARAM0) && (valueType == napi_object)) {
341             if (!ParseElementName(env, asyncCallbackInfo->elementName, argv[i])) {
342                 asyncCallbackInfo->errCode = ERR_INVALID_PARAM;
343             }
344         } else if ((i == PARAM1) && (valueType == napi_string)) {
345             ParseString(env, asyncCallbackInfo->locale, argv[i]);
346         } else if ((i == PARAM1 || i == PARAM2) && (valueType == napi_function)) {
347             NAPI_CALL(env, napi_create_reference(env, argv[i], NAPI_RETURN_ONE, &asyncCallbackInfo->callbackRef));
348             break;
349         } else {
350             asyncCallbackInfo->errCode = ERR_INVALID_PARAM;
351             asyncCallbackInfo->errMssage = "type misMatch";
352         }
353     }
354 
355     napi_value promise = nullptr;
356     if (asyncCallbackInfo->callbackRef == nullptr) {
357         NAPI_CALL(env, napi_create_promise(env, &asyncCallbackInfo->deferred, &promise));
358     } else {
359         NAPI_CALL(env, napi_get_undefined(env, &promise));
360     }
361     napi_value resource = nullptr;
362     NAPI_CALL(env, napi_create_string_utf8(env, "getRemoteAbilityInfo", NAPI_AUTO_LENGTH, &resource));
363     NAPI_CALL(env, napi_create_async_work(
364         env, nullptr, resource,
365         [](napi_env env, void* data) {
366             ElementNameInfo* asyncCallbackInfo = reinterpret_cast<ElementNameInfo *>(data);
367             if (!asyncCallbackInfo->errCode) {
368                 asyncCallbackInfo->errCode =
369                     InnerGetRemoteAbilityInfo(asyncCallbackInfo->elementName,
370                                               asyncCallbackInfo->locale,
371                                               asyncCallbackInfo->remoteAbilityInfo);
372             }
373         },
374         [](napi_env env, napi_status status, void* data) {
375             ElementNameInfo* asyncCallbackInfo = reinterpret_cast<ElementNameInfo *>(data);
376             std::unique_ptr<ElementNameInfo> callbackPtr {asyncCallbackInfo};
377             napi_value result[2] = { 0 };
378             if (asyncCallbackInfo->errCode) {
379                 napi_create_int32(env, asyncCallbackInfo->errCode, &result[0]);
380             } else {
381                 napi_create_uint32(env, 0, &result[0]);
382                 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &result[1]));
383                 ConvertRemoteAbilityInfo(env, result[1], asyncCallbackInfo->remoteAbilityInfo);
384             }
385             if (asyncCallbackInfo->callbackRef) {
386                 napi_value callback = nullptr;
387                 napi_value placeHolder = nullptr;
388                 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->callbackRef, &callback));
389                 napi_call_function(env, nullptr, callback, sizeof(result) / sizeof(result[0]), result, &placeHolder);
390             } else {
391                 if (asyncCallbackInfo->errCode) {
392                     NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncCallbackInfo->deferred, result[0]));
393                 } else {
394                     NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncCallbackInfo->deferred, result[1]));
395                 }
396             }
397         },
398         reinterpret_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
399     NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
400     callbackPtr.release();
401     return promise;
402 }
403 
GetRemoteAbilityInfos(napi_env env,napi_callback_info info)404 napi_value GetRemoteAbilityInfos(napi_env env, napi_callback_info info)
405 {
406     size_t requireArgc = ARGS_SIZE_ONE;
407     size_t argc = ARGS_SIZE_THREE;
408     napi_value argv[ARGS_SIZE_THREE] = { 0 };
409     napi_value thisArg = nullptr;
410     void *data = nullptr;
411 
412     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisArg, &data));
413     NAPI_ASSERT(env, argc >= requireArgc, "requires 1 parameter");
414 
415     ElementNameInfos *asyncCallbackInfo = new (std::nothrow) ElementNameInfos(env);
416     if (asyncCallbackInfo == nullptr) {
417         return nullptr;
418     }
419     std::unique_ptr<ElementNameInfos> callbackPtr {asyncCallbackInfo};
420     for (size_t i = 0; i < argc; ++i) {
421         napi_valuetype valueType = napi_undefined;
422         napi_typeof(env, argv[i], &valueType);
423         if (i == PARAM0) {
424             if (!ParseElementNames(env, asyncCallbackInfo->elementNames, argv[i])) {
425                 asyncCallbackInfo->errCode = ERR_INVALID_PARAM;
426             }
427             if (static_cast<int32_t>(asyncCallbackInfo->elementNames.size()) > GET_REMOTE_ABILITY_INFO_MAX_SIZE) {
428                 APP_LOGE("InnerGetRemoteAbilityInfos elementNames more than max");
429                 asyncCallbackInfo->errCode = ERR_PARAMETERS_MORE_THAN_MAX;
430             }
431         } else if ((i == PARAM1) && (valueType == napi_string)) {
432             ParseString(env, asyncCallbackInfo->locale, argv[i]);
433         } else if ((i == PARAM1 || i == PARAM2) && (valueType == napi_function)) {
434             NAPI_CALL(env, napi_create_reference(env, argv[i], NAPI_RETURN_ONE, &asyncCallbackInfo->callbackRef));
435             break;
436         } else {
437             asyncCallbackInfo->errCode = ERR_INVALID_PARAM;
438             asyncCallbackInfo->errMssage = "type misMatch";
439         }
440     }
441 
442     napi_value promise = nullptr;
443     if (asyncCallbackInfo->callbackRef == nullptr) {
444         NAPI_CALL(env, napi_create_promise(env, &asyncCallbackInfo->deferred, &promise));
445     } else {
446         NAPI_CALL(env, napi_get_undefined(env, &promise));
447     }
448     napi_value resource = nullptr;
449     NAPI_CALL(env, napi_create_string_utf8(env, "getRemoteAbilityInfos", NAPI_AUTO_LENGTH, &resource));
450     NAPI_CALL(env, napi_create_async_work(
451         env, nullptr, resource,
452         [](napi_env env, void* data) {
453             ElementNameInfos* asyncCallbackInfo = reinterpret_cast<ElementNameInfos *>(data);
454             if (!asyncCallbackInfo->errCode) {
455                 asyncCallbackInfo->errCode =
456                     InnerGetRemoteAbilityInfos(asyncCallbackInfo->elementNames,
457                                                asyncCallbackInfo->locale,
458                                                asyncCallbackInfo->remoteAbilityInfos);
459             }
460         },
461         [](napi_env env, napi_status status, void* data) {
462             ElementNameInfos* asyncCallbackInfo = reinterpret_cast<ElementNameInfos *>(data);
463             std::unique_ptr<ElementNameInfos> callbackPtr {asyncCallbackInfo};
464             napi_value result[2] = { 0 };
465             if (asyncCallbackInfo->errCode) {
466                 napi_create_int32(env, asyncCallbackInfo->errCode, &result[0]);
467             } else {
468                 napi_create_uint32(env, 0, &result[0]);
469                 NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &result[1]));
470                 ConvertRemoteAbilityInfos(env, result[1], asyncCallbackInfo->remoteAbilityInfos);
471             }
472             if (asyncCallbackInfo->callbackRef) {
473                 napi_value callback = nullptr;
474                 napi_value placeHolder = nullptr;
475                 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->callbackRef, &callback));
476                 napi_call_function(env, nullptr, callback, sizeof(result) / sizeof(result[0]), result, &placeHolder);
477             } else {
478                 if (asyncCallbackInfo->errCode) {
479                     napi_reject_deferred(env, asyncCallbackInfo->deferred, result[0]);
480                 } else {
481                     napi_resolve_deferred(env, asyncCallbackInfo->deferred, result[1]);
482                 }
483             }
484         },
485         reinterpret_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
486     NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
487     callbackPtr.release();
488     return promise;
489 }
490 }
491 }