• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "async_call.h"
17 
18 #include <algorithm>
19 
20 #include "global.h"
21 #include "js_utils.h"
22 
23 namespace OHOS {
24 namespace MiscServices {
25 constexpr size_t ARGC_MAX = 6;
AsyncCall(napi_env env,napi_callback_info info,std::shared_ptr<Context> context,size_t maxParamCount)26 AsyncCall::AsyncCall(napi_env env, napi_callback_info info, std::shared_ptr<Context> context, size_t maxParamCount)
27     : env_(env)
28 {
29     context_ = new AsyncContext();
30     size_t argc = ARGC_MAX;
31     napi_value self = nullptr;
32     napi_value argv[ARGC_MAX] = { nullptr };
33     NAPI_CALL_RETURN_VOID(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
34     napi_valuetype valueType = napi_undefined;
35     argc = std::min(argc, maxParamCount);
36     if (argc > 0) {
37         napi_typeof(env, argv[argc - 1], &valueType);
38         if (valueType == napi_function) {
39             napi_create_reference(env, argv[argc - 1], 1, &context_->callback);
40             argc = argc - 1;
41         }
42     }
43     NAPI_CALL_RETURN_VOID(env, (*context)(env, argc, argv, self));
44     context_->ctx = std::move(context);
45     napi_create_reference(env, self, 1, &context_->self);
46 }
47 
~AsyncCall()48 AsyncCall::~AsyncCall()
49 {
50     if (context_ == nullptr) {
51         return;
52     }
53 
54     DeleteContext(env_, context_);
55 }
56 
Call(napi_env env,Context::ExecAction exec,const std::string & resourceName)57 napi_value AsyncCall::Call(napi_env env, Context::ExecAction exec, const std::string &resourceName)
58 {
59     if (context_ == nullptr) {
60         IMSA_HILOGE("context_ is null");
61         return nullptr;
62     }
63     if (context_->ctx == nullptr) {
64         IMSA_HILOGE("context_->ctx is null");
65         return nullptr;
66     }
67     context_->ctx->exec_ = std::move(exec);
68     napi_value promise = nullptr;
69     if (context_->callback == nullptr) {
70         napi_create_promise(env, &context_->defer, &promise);
71     } else {
72         napi_get_undefined(env, &promise);
73     }
74     napi_async_work work = context_->work;
75     napi_value resource = nullptr;
76     std::string name = "IMF_" + resourceName;
77     napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &resource);
78     napi_create_async_work(env, nullptr, resource, AsyncCall::OnExecute, AsyncCall::OnComplete, context_, &work);
79     context_->work = work;
80     context_ = nullptr;
81     napi_queue_async_work_with_qos(env, work, napi_qos_user_initiated);
82     return promise;
83 }
84 
SyncCall(napi_env env,AsyncCall::Context::ExecAction exec)85 napi_value AsyncCall::SyncCall(napi_env env, AsyncCall::Context::ExecAction exec)
86 {
87     if ((context_ == nullptr) || (context_->ctx == nullptr)) {
88         IMSA_HILOGE("context_ or context_->ctx is null");
89         return nullptr;
90     }
91     context_->ctx->exec_ = std::move(exec);
92     napi_value promise = nullptr;
93     if (context_->callback == nullptr) {
94         napi_create_promise(env, &context_->defer, &promise);
95     } else {
96         napi_get_undefined(env, &promise);
97     }
98     AsyncCall::OnExecute(env, context_);
99     AsyncCall::OnComplete(env, context_->ctx->status_, context_);
100     return promise;
101 }
102 
OnExecute(napi_env env,void * data)103 void AsyncCall::OnExecute(napi_env env, void *data)
104 {
105     AsyncContext *context = reinterpret_cast<AsyncContext *>(data);
106     context->ctx->Exec();
107 }
108 
OnComplete(napi_env env,napi_status status,void * data)109 void AsyncCall::OnComplete(napi_env env, napi_status status, void *data)
110 {
111     AsyncContext *context = reinterpret_cast<AsyncContext *>(data);
112     napi_value output = nullptr;
113     napi_status runStatus = (*context->ctx)(env, &output);
114     napi_value result[ARG_BUTT] = { 0 };
115     IMSA_HILOGE("run the js callback function:status[%{public}d]runStatus[%{public}d]", status, runStatus);
116     if (status == napi_ok && runStatus == napi_ok) {
117         napi_get_undefined(env, &result[ARG_ERROR]);
118         if (output != nullptr) {
119             IMSA_HILOGI("AsyncCall::OnComplete output != nullptr");
120             result[ARG_DATA] = output;
121         } else {
122             IMSA_HILOGI("AsyncCall::OnComplete output == nullptr");
123             napi_get_undefined(env, &result[ARG_DATA]);
124         }
125     } else {
126         result[ARG_ERROR] = JsUtils::ToError(env, context->ctx->errorCode_);
127         napi_get_undefined(env, &result[ARG_DATA]);
128     }
129     if (context->defer != nullptr) {
130         if (status == napi_ok && runStatus == napi_ok) {
131             napi_resolve_deferred(env, context->defer, result[ARG_DATA]);
132         } else {
133             napi_reject_deferred(env, context->defer, result[ARG_ERROR]);
134         }
135     } else {
136         napi_value callback = nullptr;
137         napi_get_reference_value(env, context->callback, &callback);
138         napi_value returnValue;
139         napi_call_function(env, nullptr, callback, ARG_BUTT, result, &returnValue);
140     }
141     DeleteContext(env, context);
142 }
143 
DeleteContext(napi_env env,AsyncContext * context)144 void AsyncCall::DeleteContext(napi_env env, AsyncContext *context)
145 {
146     if (env != nullptr) {
147         napi_delete_reference(env, context->callback);
148         napi_delete_reference(env, context->self);
149         napi_delete_async_work(env, context->work);
150     }
151     delete context;
152 }
153 } // namespace MiscServices
154 } // namespace OHOS
155