1 /*
2 * Copyright (C) 2023 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_async_callback.h"
17 #include "bluetooth_errorcode.h"
18 #include "bluetooth_log.h"
19
20 namespace OHOS {
21 namespace Bluetooth {
CallFunction(int errCode,const std::shared_ptr<NapiNativeObject> & object)22 void NapiAsyncCallback::CallFunction(int errCode, const std::shared_ptr<NapiNativeObject> &object)
23 {
24 if (callback == nullptr && promise == nullptr) {
25 HILOGE("callback & promise is nullptr");
26 return;
27 }
28 if (object == nullptr) {
29 HILOGE("napi native object is nullptr");
30 return;
31 }
32
33 if (callback) {
34 callback->CallFunction(errCode, object);
35 return;
36 }
37 if (promise) {
38 promise->ResolveOrReject(errCode, object);
39 }
40 }
41
GetRet(void)42 napi_value NapiAsyncCallback::GetRet(void)
43 {
44 if (promise) {
45 return promise->GetPromise();
46 }
47 return NapiGetUndefinedRet(env);
48 }
49
NapiCallback(napi_env env,napi_value callback)50 NapiCallback::NapiCallback(napi_env env, napi_value callback) : env_(env)
51 {
52 auto status = napi_create_reference(env, callback, 1, &callbackRef_);
53 if (status != napi_ok) {
54 HILOGE("napi_create_reference failed, status: %{public}d", status);
55 }
56 }
~NapiCallback()57 NapiCallback::~NapiCallback()
58 {
59 auto status = napi_delete_reference(env_, callbackRef_);
60 if (status != napi_ok) {
61 HILOGE("napi_delete_reference failed, status: %{public}d", status);
62 }
63 }
64
65 namespace {
NapiCallFunction(napi_env env,napi_ref callbackRef,napi_value * argv,size_t argc)66 void NapiCallFunction(napi_env env, napi_ref callbackRef, napi_value *argv, size_t argc)
67 {
68 napi_value undefined = nullptr;
69 napi_value callRet = nullptr;
70 napi_value callback = nullptr;
71 auto status = napi_get_reference_value(env, callbackRef, &callback);
72 if (status != napi_ok) {
73 HILOGE("napi_get_reference_value failed, status: %{public}d", status);
74 return;
75 }
76
77 status = napi_call_function(env, undefined, callback, argc, argv, &callRet);
78 if (status != napi_ok) {
79 HILOGE("napi_call_function failed, status: %{public}d", status);
80 }
81
82 // Check whether the JS application triggers an exception in callback. If it is, clear it.
83 bool isExist = false;
84 status = napi_is_exception_pending(env, &isExist);
85 HILOGD("napi_is_exception_pending status: %{public}d, isExist: %{public}d", status, isExist);
86 if (isExist) {
87 HILOGI("Clear JS application's exception");
88 napi_value exception = nullptr;
89 status = napi_get_and_clear_last_exception(env, &exception);
90 HILOGD("napi_get_and_clear_last_exception status: %{public}d, exception: %{public}p", status, exception);
91 }
92 }
93 } // namespace {}
94
CallFunction(const std::shared_ptr<NapiNativeObject> & object)95 void NapiCallback::CallFunction(const std::shared_ptr<NapiNativeObject> &object)
96 {
97 if (object == nullptr) {
98 HILOGE("napi native object is nullptr");
99 return;
100 }
101
102 NapiHandleScope scope(env_);
103 napi_value val = object->ToNapiValue(env_);
104 NapiCallFunction(env_, callbackRef_, &val, ARGS_SIZE_ONE);
105 }
106
CallFunction(int errCode,const std::shared_ptr<NapiNativeObject> & object)107 void NapiCallback::CallFunction(int errCode, const std::shared_ptr<NapiNativeObject> &object)
108 {
109 if (object == nullptr) {
110 HILOGE("napi native object is nullptr");
111 return;
112 }
113
114 NapiHandleScope scope(env_);
115 napi_value code = GetCallbackErrorValue(env_, errCode);
116 napi_value val = object->ToNapiValue(env_);
117 napi_value argv[ARGS_SIZE_TWO] = {code, val};
118 NapiCallFunction(env_, callbackRef_, argv, ARGS_SIZE_TWO);
119 }
120
GetNapiEnv(void)121 napi_env NapiCallback::GetNapiEnv(void)
122 {
123 return env_;
124 }
125
NapiPromise(napi_env env)126 NapiPromise::NapiPromise(napi_env env) : env_(env)
127 {
128 auto status = napi_create_promise(env, &deferred_, &promise_);
129 if (status != napi_ok) {
130 HILOGE("napi_create_promise failed, status: %{public}d", status);
131 }
132 }
133
ResolveOrReject(int errCode,const std::shared_ptr<NapiNativeObject> & object)134 void NapiPromise::ResolveOrReject(int errCode, const std::shared_ptr<NapiNativeObject> &object)
135 {
136 if (object == nullptr) {
137 HILOGE("napi native object is nullptr");
138 return;
139 }
140
141 NapiHandleScope scope(env_);
142
143 if (errCode == BT_NO_ERROR) {
144 napi_value val = object->ToNapiValue(env_);
145 Resolve(val);
146 } else {
147 napi_value code = GetCallbackErrorValue(env_, errCode);
148 Reject(code);
149 }
150 }
151
Resolve(napi_value resolution)152 void NapiPromise::Resolve(napi_value resolution)
153 {
154 auto status = napi_resolve_deferred(env_, deferred_, resolution);
155 if (status != napi_ok) {
156 HILOGE("napi_resolve_deferred failed, status: %{public}d", status);
157 }
158 }
Reject(napi_value rejection)159 void NapiPromise::Reject(napi_value rejection)
160 {
161 auto status = napi_reject_deferred(env_, deferred_, rejection);
162 if (status != napi_ok) {
163 HILOGE("napi_reject_deferred failed, status: %{public}d", status);
164 }
165 }
GetPromise(void) const166 napi_value NapiPromise::GetPromise(void) const
167 {
168 return promise_;
169 }
170
NapiHandleScope(napi_env env)171 NapiHandleScope::NapiHandleScope(napi_env env) : env_(env)
172 {
173 napi_status status = napi_open_handle_scope(env_, &scope_);
174 if (status != napi_ok) {
175 HILOGE("napi_open_handle_scope failed, status(%{public}d)", status);
176 }
177 }
178
~NapiHandleScope()179 NapiHandleScope::~NapiHandleScope()
180 {
181 napi_status status = napi_close_handle_scope(env_, scope_);
182 if (status != napi_ok) {
183 HILOGE("napi_close_handle_scope failed, status(%{public}d)", status);
184 }
185 }
186
187 } // namespace Bluetooth
188 } // namespace OHOS
189