• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Equal(napi_value & callback) const126 bool NapiCallback::Equal(napi_value &callback) const
127 {
128     NapiHandleScope scope(env_);
129     napi_value storedCallback = nullptr;
130     napi_get_reference_value(env_, callbackRef_, &storedCallback);
131 
132     bool isEqual = false;
133     napi_strict_equals(env_, storedCallback, callback, &isEqual);
134     return isEqual;
135 }
136 
NapiPromise(napi_env env)137 NapiPromise::NapiPromise(napi_env env) : env_(env)
138 {
139     auto status = napi_create_promise(env, &deferred_, &promise_);
140     if (status != napi_ok) {
141         HILOGE("napi_create_promise failed, status: %{public}d", status);
142     }
143 }
144 
ResolveOrReject(int errCode,const std::shared_ptr<NapiNativeObject> & object)145 void NapiPromise::ResolveOrReject(int errCode, const std::shared_ptr<NapiNativeObject> &object)
146 {
147     if (object == nullptr) {
148         HILOGE("napi native object is nullptr");
149         return;
150     }
151 
152     if (isResolvedOrRejected_) {
153         HILOGE("napi Resolved Or Rejected");
154         return;
155     }
156 
157     NapiHandleScope scope(env_);
158 
159     if (errCode == BT_NO_ERROR) {
160         napi_value val = object->ToNapiValue(env_);
161         Resolve(val);
162     } else {
163         napi_value code = GetCallbackErrorValue(env_, errCode);
164         Reject(code);
165     }
166     isResolvedOrRejected_ = true;
167 }
168 
Resolve(napi_value resolution)169 void NapiPromise::Resolve(napi_value resolution)
170 {
171     auto status = napi_resolve_deferred(env_, deferred_, resolution);
172     if (status != napi_ok) {
173         HILOGE("napi_resolve_deferred failed, status: %{public}d", status);
174     }
175 }
Reject(napi_value rejection)176 void NapiPromise::Reject(napi_value rejection)
177 {
178     auto status = napi_reject_deferred(env_, deferred_, rejection);
179     if (status != napi_ok) {
180         HILOGE("napi_reject_deferred failed, status: %{public}d", status);
181     }
182 }
GetPromise(void) const183 napi_value NapiPromise::GetPromise(void) const
184 {
185     return promise_;
186 }
187 
NapiHandleScope(napi_env env)188 NapiHandleScope::NapiHandleScope(napi_env env) : env_(env)
189 {
190     napi_status status = napi_open_handle_scope(env_, &scope_);
191     if (status != napi_ok) {
192         HILOGE("napi_open_handle_scope failed, status(%{public}d)", status);
193     }
194 }
195 
~NapiHandleScope()196 NapiHandleScope::~NapiHandleScope()
197 {
198     napi_status status = napi_close_handle_scope(env_, scope_);
199     if (status != napi_ok) {
200         HILOGE("napi_close_handle_scope failed, status(%{public}d)", status);
201     }
202 }
203 
204 }  // namespace Bluetooth
205 }  // namespace OHOS
206