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 ¶m, 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 }