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     if (samgr == nullptr) {
76         APP_LOGE("GetSystemAbilityManager failed, samgr is nullptr.");
77         return nullptr;
78     }
79     auto remoteObject = samgr->GetSystemAbility(OHOS::DISTRIBUTED_BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
80     return OHOS::iface_cast<IDistributedBms>(remoteObject);
81 }
82 
GetStringFromNAPI(napi_env env,napi_value value)83 static std::string GetStringFromNAPI(napi_env env, napi_value value)
84 {
85     std::string result;
86     size_t size = 0;
87 
88     if (napi_get_value_string_utf8(env, value, nullptr, NAPI_RETURN_ZERO, &size) != napi_ok) {
89         APP_LOGE("can not get string size");
90         return "";
91     }
92     result.reserve(size + NAPI_RETURN_ONE);
93     result.resize(size);
94     if (napi_get_value_string_utf8(env, value, result.data(), (size + NAPI_RETURN_ONE), &size) != napi_ok) {
95         APP_LOGE("can not get string value");
96         return "";
97     }
98     return result;
99 }
100 
ParseString(napi_env env,std::string & param,napi_value args)101 static napi_value ParseString(napi_env env, std::string &param, napi_value args)
102 {
103     napi_status status;
104     napi_valuetype valuetype;
105     NAPI_CALL(env, napi_typeof(env, args, &valuetype));
106     NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type. String expected.");
107     param = GetStringFromNAPI(env, args);
108     APP_LOGD("param=%{public}s.", param.c_str());
109     napi_value result;
110     status = napi_create_int32(env, NAPI_RETURN_ONE, &result);
111     NAPI_ASSERT(env, status == napi_ok, "napi_create_int32 error!");
112     return result;
113 }
114 
ConvertResultCode(int32_t code)115 static int32_t ConvertResultCode(int32_t code)
116 {
117     APP_LOGD("ConvertResultCode resultCode:%{public}d", code);
118     switch (code) {
119         case SUCCESS:
120             return SUCCESS;
121         case ERR_APPEXECFWK_FAILED_GET_REMOTE_PROXY:
122             return ERR_RPC_ERROR;
123         default:
124             break;
125     }
126     return ERR_INNER_ERROR;
127 }
128 
ConvertElementName(napi_env env,napi_value objElementName,const ElementName & elementName)129 static void ConvertElementName(napi_env env, napi_value objElementName, const ElementName &elementName)
130 {
131     napi_value nDeviceId;
132     NAPI_CALL_RETURN_VOID(
133         env, napi_create_string_utf8(env, elementName.GetDeviceID().c_str(), NAPI_AUTO_LENGTH, &nDeviceId));
134     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "deviceId", nDeviceId));
135 
136     napi_value nBundleName;
137     NAPI_CALL_RETURN_VOID(
138         env, napi_create_string_utf8(env, elementName.GetBundleName().c_str(), NAPI_AUTO_LENGTH, &nBundleName));
139     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "bundleName", nBundleName));
140 
141     napi_value nModuleName;
142     NAPI_CALL_RETURN_VOID(
143         env, napi_create_string_utf8(env, elementName.GetModuleName().c_str(), NAPI_AUTO_LENGTH, &nModuleName));
144     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "moduleName", nModuleName));
145 
146     napi_value nAbilityName;
147     NAPI_CALL_RETURN_VOID(
148         env, napi_create_string_utf8(env, elementName.GetAbilityName().c_str(), NAPI_AUTO_LENGTH, &nAbilityName));
149     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objElementName, "abilityName", nAbilityName));
150 }
151 
ConvertRemoteAbilityInfo(napi_env env,napi_value objRemoteAbilityInfo,const RemoteAbilityInfo & remoteAbilityInfo)152 static void ConvertRemoteAbilityInfo(
153     napi_env env, napi_value objRemoteAbilityInfo, const RemoteAbilityInfo &remoteAbilityInfo)
154 {
155     napi_value objElementName;
156     NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objElementName));
157     ConvertElementName(env, objElementName, remoteAbilityInfo.elementName);
158     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRemoteAbilityInfo, "elementName", objElementName));
159 
160     napi_value nLabel;
161     NAPI_CALL_RETURN_VOID(
162         env, napi_create_string_utf8(env, remoteAbilityInfo.label.c_str(), NAPI_AUTO_LENGTH, &nLabel));
163     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRemoteAbilityInfo, "label", nLabel));
164 
165     napi_value nIcon;
166     NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, remoteAbilityInfo.icon.c_str(), NAPI_AUTO_LENGTH, &nIcon));
167     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, objRemoteAbilityInfo, "icon", nIcon));
168 }
169 
ConvertRemoteAbilityInfos(napi_env env,napi_value objRemoteAbilityInfos,const std::vector<RemoteAbilityInfo> & remoteAbilityInfos)170 static void ConvertRemoteAbilityInfos(
171     napi_env env, napi_value objRemoteAbilityInfos, const std::vector<RemoteAbilityInfo> &remoteAbilityInfos)
172 {
173     if (remoteAbilityInfos.size() == 0) {
174         APP_LOGE("ConvertRemoteAbilityInfos remoteAbilityInfos is empty");
175         return;
176     }
177     size_t index = 0;
178     for (const auto &remoteAbilityInfo : remoteAbilityInfos) {
179         APP_LOGD("remoteAbilityInfo bundleName:%{public}s, abilityName:%{public}s, label:%{public}s",
180                  remoteAbilityInfo.elementName.GetBundleName().c_str(),
181                  remoteAbilityInfo.elementName.GetAbilityName().c_str(),
182                  remoteAbilityInfo.label.c_str());
183         napi_value objRemoteAbilityInfo = nullptr;
184         NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &objRemoteAbilityInfo));
185         ConvertRemoteAbilityInfo(env, objRemoteAbilityInfo, remoteAbilityInfo);
186         NAPI_CALL_RETURN_VOID(env, napi_set_element(env, objRemoteAbilityInfos, index, objRemoteAbilityInfo));
187         index++;
188     }
189 }
190 
ParseModuleName(napi_env env,std::string & moduleName,napi_value args)191 static bool ParseModuleName(napi_env env, std::string &moduleName, napi_value args)
192 {
193     napi_status status;
194     napi_valuetype valueType;
195     napi_value prop = nullptr;
196     bool hasKey = false;
197     napi_has_named_property(env, args, "moduleName", &hasKey);
198     if (hasKey) {
199         status = napi_get_named_property(env, args, "moduleName", &prop);
200         napi_typeof(env, prop, &valueType);
201         if ((status == napi_ok) && (valueType == napi_string)) {
202             moduleName = GetStringFromNAPI(env, prop);
203         } else {
204             APP_LOGE("begin to parse ElementName moduleName failed");
205             return false;
206         }
207     }
208     return true;
209 }
210 
ParseElementName(napi_env env,OHOS::AppExecFwk::ElementName & elementName,napi_value args)211 static bool ParseElementName(napi_env env, OHOS::AppExecFwk::ElementName &elementName, napi_value args)
212 {
213     APP_LOGD("begin to parse ElementName");
214     napi_status status;
215     napi_valuetype valueType;
216     NAPI_CALL_BASE(env, napi_typeof(env, args, &valueType), false);
217     if (valueType != napi_object) {
218         APP_LOGE("args not object type");
219         return false;
220     }
221     napi_value prop = nullptr;
222     status = napi_get_named_property(env, args, "deviceId", &prop);
223     napi_typeof(env, prop, &valueType);
224     if (status == napi_ok && valueType == napi_string) {
225         elementName.SetDeviceID(GetStringFromNAPI(env, prop));
226     } else {
227         APP_LOGE("begin to parse ElementName deviceId failed");
228         return false;
229     }
230     prop = nullptr;
231     status = napi_get_named_property(env, args, "bundleName", &prop);
232     napi_typeof(env, prop, &valueType);
233     if (status == napi_ok && valueType == napi_string) {
234         elementName.SetBundleName(GetStringFromNAPI(env, prop));
235     } else {
236         APP_LOGE("begin to parse ElementName bundleName failed");
237         return false;
238     }
239     prop = nullptr;
240     status = napi_get_named_property(env, args, "abilityName", &prop);
241     napi_typeof(env, prop, &valueType);
242     if (status == napi_ok && valueType == napi_string) {
243         elementName.SetAbilityName(GetStringFromNAPI(env, prop));
244     } else {
245         APP_LOGE("begin to parse ElementName abilityName failed");
246         return false;
247     }
248     std::string moduleName;
249     if (!ParseModuleName(env, moduleName, args)) {
250         return false;
251     }
252     elementName.SetModuleName(moduleName);
253     APP_LOGD("parse ElementName end");
254     return true;
255 }
256 
ParseElementNames(napi_env env,std::vector<ElementName> & elementNames,napi_value args)257 static bool ParseElementNames(napi_env env, std::vector<ElementName> &elementNames, napi_value args)
258 {
259     APP_LOGD("begin to parse ElementNames");
260     bool isArray = false;
261     NAPI_CALL_BASE(env, napi_is_array(env, args, &isArray), false);
262     if (!isArray) {
263         APP_LOGE("parseElementNames args not array");
264         return false;
265     }
266     uint32_t arrayLength = 0;
267     NAPI_CALL_BASE(env, napi_get_array_length(env, args, &arrayLength), false);
268     APP_LOGD("arrayLength:%{public}d", arrayLength);
269     for (uint32_t i = 0; i < arrayLength; i++) {
270         napi_value value = nullptr;
271         NAPI_CALL_BASE(env, napi_get_element(env, args, i, &value), false);
272         napi_valuetype valueType = napi_undefined;
273         NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), false);
274         if (valueType != napi_object) {
275             APP_LOGE("array inside not object type");
276             elementNames.clear();
277             return false;
278         }
279         ElementName elementName;
280         if (ParseElementName(env, elementName, value)) {
281             elementNames.push_back(elementName);
282         } else {
283             APP_LOGE("elementNames parse elementName failed");
284             return false;
285         }
286     }
287     return true;
288 }
289 
InnerGetRemoteAbilityInfo(const OHOS::AppExecFwk::ElementName & elementName,const std::string & locale,RemoteAbilityInfo & remoteAbilityInfo)290 static int32_t InnerGetRemoteAbilityInfo(
291     const OHOS::AppExecFwk::ElementName &elementName, const std::string &locale, RemoteAbilityInfo &remoteAbilityInfo)
292 {
293     auto iDistBundleMgr = GetDistributedBundleMgr();
294     if (!iDistBundleMgr) {
295         APP_LOGE("can not get iDistBundleMgr");
296         return ERR_INNER_ERROR;
297     }
298     int32_t result = iDistBundleMgr->GetRemoteAbilityInfo(elementName, locale, remoteAbilityInfo);
299     if (result != 0) {
300         APP_LOGE("InnerGetRemoteAbilityInfo failed");
301     }
302     return ConvertResultCode(result);
303 }
304 
InnerGetRemoteAbilityInfos(const std::vector<ElementName> & elementNames,const std::string & locale,std::vector<RemoteAbilityInfo> & remoteAbilityInfos)305 static int32_t InnerGetRemoteAbilityInfos(const std::vector<ElementName> &elementNames, const std::string &locale,
306     std::vector<RemoteAbilityInfo> &remoteAbilityInfos)
307 {
308     if (elementNames.size() == 0) {
309         APP_LOGE("InnerGetRemoteAbilityInfos elementNames is empty");
310         return ERR_INVALID_PARAM;
311     }
312     auto iDistBundleMgr = GetDistributedBundleMgr();
313     if (!iDistBundleMgr) {
314         APP_LOGE("can not get iDistBundleMgr");
315         return ERR_INNER_ERROR;
316     }
317     int32_t result = iDistBundleMgr->GetRemoteAbilityInfos(elementNames, locale, remoteAbilityInfos);
318     if (result != 0) {
319         APP_LOGE("InnerGetRemoteAbilityInfo failed");
320     }
321     return ConvertResultCode(result);
322 }
323 
GetRemoteAbilityInfo(napi_env env,napi_callback_info info)324 napi_value GetRemoteAbilityInfo(napi_env env, napi_callback_info info)
325 {
326     size_t requireArgc = ARGS_SIZE_ONE;
327     size_t argc = ARGS_SIZE_THREE;
328     napi_value argv[ARGS_SIZE_THREE] = { 0 };
329     napi_value thisArg = nullptr;
330     void *data = nullptr;
331 
332     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisArg, &data));
333     NAPI_ASSERT(env, argc >= requireArgc, "requires 1 parameter");
334 
335     ElementNameInfo *asyncCallbackInfo = new (std::nothrow) ElementNameInfo(env);
336     if (asyncCallbackInfo == nullptr) {
337         return nullptr;
338     }
339     std::unique_ptr<ElementNameInfo> callbackPtr {asyncCallbackInfo};
340     for (size_t i = 0; i < argc; ++i) {
341         napi_valuetype valueType = napi_undefined;
342         NAPI_CALL(env, napi_typeof(env, argv[i], &valueType));
343         if ((i == PARAM0) && (valueType == napi_object)) {
344             if (!ParseElementName(env, asyncCallbackInfo->elementName, argv[i])) {
345                 asyncCallbackInfo->errCode = ERR_INVALID_PARAM;
346             }
347         } else if ((i == PARAM1) && (valueType == napi_string)) {
348             ParseString(env, asyncCallbackInfo->locale, argv[i]);
349         } else if ((i == PARAM1 || i == PARAM2) && (valueType == napi_function)) {
350             NAPI_CALL(env, napi_create_reference(env, argv[i], NAPI_RETURN_ONE, &asyncCallbackInfo->callbackRef));
351             break;
352         } else {
353             asyncCallbackInfo->errCode = ERR_INVALID_PARAM;
354             asyncCallbackInfo->errMssage = "type misMatch";
355         }
356     }
357 
358     napi_value promise = nullptr;
359     if (asyncCallbackInfo->callbackRef == nullptr) {
360         NAPI_CALL(env, napi_create_promise(env, &asyncCallbackInfo->deferred, &promise));
361     } else {
362         NAPI_CALL(env, napi_get_undefined(env, &promise));
363     }
364     napi_value resource = nullptr;
365     NAPI_CALL(env, napi_create_string_utf8(env, "getRemoteAbilityInfo", NAPI_AUTO_LENGTH, &resource));
366     NAPI_CALL(env, napi_create_async_work(
367         env, nullptr, resource,
368         [](napi_env env, void* data) {
369             ElementNameInfo* asyncCallbackInfo = reinterpret_cast<ElementNameInfo *>(data);
370             if (!asyncCallbackInfo->errCode) {
371                 asyncCallbackInfo->errCode =
372                     InnerGetRemoteAbilityInfo(asyncCallbackInfo->elementName,
373                                               asyncCallbackInfo->locale,
374                                               asyncCallbackInfo->remoteAbilityInfo);
375             }
376         },
377         [](napi_env env, napi_status status, void* data) {
378             ElementNameInfo* asyncCallbackInfo = reinterpret_cast<ElementNameInfo *>(data);
379             std::unique_ptr<ElementNameInfo> callbackPtr {asyncCallbackInfo};
380             napi_value result[2] = { 0 };
381             if (asyncCallbackInfo->errCode) {
382                 napi_create_int32(env, asyncCallbackInfo->errCode, &result[0]);
383             } else {
384                 napi_create_uint32(env, 0, &result[0]);
385                 NAPI_CALL_RETURN_VOID(env, napi_create_object(env, &result[1]));
386                 ConvertRemoteAbilityInfo(env, result[1], asyncCallbackInfo->remoteAbilityInfo);
387             }
388             if (asyncCallbackInfo->callbackRef) {
389                 napi_value callback = nullptr;
390                 napi_value placeHolder = nullptr;
391                 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->callbackRef, &callback));
392                 napi_call_function(env, nullptr, callback, sizeof(result) / sizeof(result[0]), result, &placeHolder);
393             } else {
394                 if (asyncCallbackInfo->errCode) {
395                     NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, asyncCallbackInfo->deferred, result[0]));
396                 } else {
397                     NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, asyncCallbackInfo->deferred, result[1]));
398                 }
399             }
400         },
401         reinterpret_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
402     NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
403     callbackPtr.release();
404     return promise;
405 }
406 
GetRemoteAbilityInfos(napi_env env,napi_callback_info info)407 napi_value GetRemoteAbilityInfos(napi_env env, napi_callback_info info)
408 {
409     size_t requireArgc = ARGS_SIZE_ONE;
410     size_t argc = ARGS_SIZE_THREE;
411     napi_value argv[ARGS_SIZE_THREE] = { 0 };
412     napi_value thisArg = nullptr;
413     void *data = nullptr;
414 
415     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisArg, &data));
416     NAPI_ASSERT(env, argc >= requireArgc, "requires 1 parameter");
417 
418     ElementNameInfos *asyncCallbackInfo = new (std::nothrow) ElementNameInfos(env);
419     if (asyncCallbackInfo == nullptr) {
420         return nullptr;
421     }
422     std::unique_ptr<ElementNameInfos> callbackPtr {asyncCallbackInfo};
423     for (size_t i = 0; i < argc; ++i) {
424         napi_valuetype valueType = napi_undefined;
425         napi_typeof(env, argv[i], &valueType);
426         if (i == PARAM0) {
427             if (!ParseElementNames(env, asyncCallbackInfo->elementNames, argv[i])) {
428                 asyncCallbackInfo->errCode = ERR_INVALID_PARAM;
429             }
430             if (static_cast<int32_t>(asyncCallbackInfo->elementNames.size()) > GET_REMOTE_ABILITY_INFO_MAX_SIZE) {
431                 APP_LOGE("InnerGetRemoteAbilityInfos elementNames more than max");
432                 asyncCallbackInfo->errCode = ERR_PARAMETERS_MORE_THAN_MAX;
433             }
434         } else if ((i == PARAM1) && (valueType == napi_string)) {
435             ParseString(env, asyncCallbackInfo->locale, argv[i]);
436         } else if ((i == PARAM1 || i == PARAM2) && (valueType == napi_function)) {
437             NAPI_CALL(env, napi_create_reference(env, argv[i], NAPI_RETURN_ONE, &asyncCallbackInfo->callbackRef));
438             break;
439         } else {
440             asyncCallbackInfo->errCode = ERR_INVALID_PARAM;
441             asyncCallbackInfo->errMssage = "type misMatch";
442         }
443     }
444 
445     napi_value promise = nullptr;
446     if (asyncCallbackInfo->callbackRef == nullptr) {
447         NAPI_CALL(env, napi_create_promise(env, &asyncCallbackInfo->deferred, &promise));
448     } else {
449         NAPI_CALL(env, napi_get_undefined(env, &promise));
450     }
451     napi_value resource = nullptr;
452     NAPI_CALL(env, napi_create_string_utf8(env, "getRemoteAbilityInfos", NAPI_AUTO_LENGTH, &resource));
453     NAPI_CALL(env, napi_create_async_work(
454         env, nullptr, resource,
455         [](napi_env env, void* data) {
456             ElementNameInfos* asyncCallbackInfo = reinterpret_cast<ElementNameInfos *>(data);
457             if (!asyncCallbackInfo->errCode) {
458                 asyncCallbackInfo->errCode =
459                     InnerGetRemoteAbilityInfos(asyncCallbackInfo->elementNames,
460                                                asyncCallbackInfo->locale,
461                                                asyncCallbackInfo->remoteAbilityInfos);
462             }
463         },
464         [](napi_env env, napi_status status, void* data) {
465             ElementNameInfos* asyncCallbackInfo = reinterpret_cast<ElementNameInfos *>(data);
466             std::unique_ptr<ElementNameInfos> callbackPtr {asyncCallbackInfo};
467             napi_value result[2] = { 0 };
468             if (asyncCallbackInfo->errCode) {
469                 napi_create_int32(env, asyncCallbackInfo->errCode, &result[0]);
470             } else {
471                 napi_create_uint32(env, 0, &result[0]);
472                 NAPI_CALL_RETURN_VOID(env, napi_create_array(env, &result[1]));
473                 ConvertRemoteAbilityInfos(env, result[1], asyncCallbackInfo->remoteAbilityInfos);
474             }
475             if (asyncCallbackInfo->callbackRef) {
476                 napi_value callback = nullptr;
477                 napi_value placeHolder = nullptr;
478                 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, asyncCallbackInfo->callbackRef, &callback));
479                 napi_call_function(env, nullptr, callback, sizeof(result) / sizeof(result[0]), result, &placeHolder);
480             } else {
481                 if (asyncCallbackInfo->errCode) {
482                     napi_reject_deferred(env, asyncCallbackInfo->deferred, result[0]);
483                 } else {
484                     napi_resolve_deferred(env, asyncCallbackInfo->deferred, result[1]);
485                 }
486             }
487         },
488         reinterpret_cast<void*>(asyncCallbackInfo), &asyncCallbackInfo->asyncWork));
489     NAPI_CALL(env, napi_queue_async_work(env, asyncCallbackInfo->asyncWork));
490     callbackPtr.release();
491     return promise;
492 }
493 }
494 }