1bc03f14fSopenharmony_ci/* 2bc03f14fSopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3bc03f14fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4bc03f14fSopenharmony_ci * you may not use this file except in compliance with the License. 5bc03f14fSopenharmony_ci * You may obtain a copy of the License at 6bc03f14fSopenharmony_ci * 7bc03f14fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8bc03f14fSopenharmony_ci * 9bc03f14fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10bc03f14fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11bc03f14fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12bc03f14fSopenharmony_ci * See the License for the specific language governing permissions and 13bc03f14fSopenharmony_ci * limitations under the License. 14bc03f14fSopenharmony_ci */ 15bc03f14fSopenharmony_ci#define LOG_TAG "PasteBoardAsyncCall" 16bc03f14fSopenharmony_ci#include "async_call.h" 17bc03f14fSopenharmony_ci#include "pasteboard_hilog.h" 18bc03f14fSopenharmony_ci 19bc03f14fSopenharmony_ciusing namespace OHOS::MiscServices; 20bc03f14fSopenharmony_ci 21bc03f14fSopenharmony_cinamespace OHOS::MiscServicesNapi { 22bc03f14fSopenharmony_ciAsyncCall::AsyncCall(napi_env env, napi_callback_info info, std::shared_ptr<Context> context, size_t pos) : env_(env) 23bc03f14fSopenharmony_ci{ 24bc03f14fSopenharmony_ci context_ = new AsyncContext(); 25bc03f14fSopenharmony_ci size_t argc = 6; 26bc03f14fSopenharmony_ci napi_value self = nullptr; 27bc03f14fSopenharmony_ci napi_value argv[6] = { nullptr }; 28bc03f14fSopenharmony_ci NAPI_CALL_RETURN_VOID(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); 29bc03f14fSopenharmony_ci pos = ((pos == ASYNC_DEFAULT_POS) ? (argc - 1) : pos); 30bc03f14fSopenharmony_ci if (pos >= 0 && pos < argc) { 31bc03f14fSopenharmony_ci napi_valuetype valueType = napi_undefined; 32bc03f14fSopenharmony_ci napi_typeof(env, argv[pos], &valueType); 33bc03f14fSopenharmony_ci if (valueType == napi_function) { 34bc03f14fSopenharmony_ci napi_create_reference(env, argv[pos], 1, &context_->callback); 35bc03f14fSopenharmony_ci } 36bc03f14fSopenharmony_ci } 37bc03f14fSopenharmony_ci napi_status status = (*context)(env, argc, argv, self); 38bc03f14fSopenharmony_ci if (status != napi_ok) { 39bc03f14fSopenharmony_ci return; 40bc03f14fSopenharmony_ci } 41bc03f14fSopenharmony_ci context_->ctx = std::move(context); 42bc03f14fSopenharmony_ci napi_create_reference(env, self, 1, &context_->self); 43bc03f14fSopenharmony_ci} 44bc03f14fSopenharmony_ci 45bc03f14fSopenharmony_ciAsyncCall::~AsyncCall() 46bc03f14fSopenharmony_ci{ 47bc03f14fSopenharmony_ci if (context_ == nullptr) { 48bc03f14fSopenharmony_ci return; 49bc03f14fSopenharmony_ci } 50bc03f14fSopenharmony_ci 51bc03f14fSopenharmony_ci DeleteContext(env_, context_); 52bc03f14fSopenharmony_ci} 53bc03f14fSopenharmony_ci 54bc03f14fSopenharmony_cinapi_value AsyncCall::Call(napi_env env, Context::ExecAction exec) 55bc03f14fSopenharmony_ci{ 56bc03f14fSopenharmony_ci if (context_ == nullptr) { 57bc03f14fSopenharmony_ci PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "context_ is null"); 58bc03f14fSopenharmony_ci return nullptr; 59bc03f14fSopenharmony_ci } 60bc03f14fSopenharmony_ci if (context_->ctx == nullptr) { 61bc03f14fSopenharmony_ci PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "context_->ctx is null"); 62bc03f14fSopenharmony_ci return nullptr; 63bc03f14fSopenharmony_ci } 64bc03f14fSopenharmony_ci 65bc03f14fSopenharmony_ci context_->ctx->exec_ = std::move(exec); 66bc03f14fSopenharmony_ci napi_value promise = nullptr; 67bc03f14fSopenharmony_ci if (context_->callback == nullptr) { 68bc03f14fSopenharmony_ci napi_create_promise(env, &context_->defer, &promise); 69bc03f14fSopenharmony_ci } else { 70bc03f14fSopenharmony_ci napi_get_undefined(env, &promise); 71bc03f14fSopenharmony_ci } 72bc03f14fSopenharmony_ci napi_async_work work = context_->work; 73bc03f14fSopenharmony_ci napi_value resource = nullptr; 74bc03f14fSopenharmony_ci napi_create_string_utf8(env, LOG_TAG, NAPI_AUTO_LENGTH, &resource); 75bc03f14fSopenharmony_ci napi_create_async_work(env, nullptr, resource, AsyncCall::OnExecute, AsyncCall::OnComplete, context_, &work); 76bc03f14fSopenharmony_ci context_->work = work; 77bc03f14fSopenharmony_ci context_ = nullptr; 78bc03f14fSopenharmony_ci napi_queue_async_work_with_qos(env, work, napi_qos_user_initiated); 79bc03f14fSopenharmony_ci PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "async call exec"); 80bc03f14fSopenharmony_ci return promise; 81bc03f14fSopenharmony_ci} 82bc03f14fSopenharmony_ci 83bc03f14fSopenharmony_cinapi_value AsyncCall::SyncCall(napi_env env, AsyncCall::Context::ExecAction exec) 84bc03f14fSopenharmony_ci{ 85bc03f14fSopenharmony_ci if ((context_ == nullptr) || (context_->ctx == nullptr)) { 86bc03f14fSopenharmony_ci PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "context_ or context_->ctx is null"); 87bc03f14fSopenharmony_ci return nullptr; 88bc03f14fSopenharmony_ci } 89bc03f14fSopenharmony_ci context_->ctx->exec_ = std::move(exec); 90bc03f14fSopenharmony_ci napi_value promise = nullptr; 91bc03f14fSopenharmony_ci if (context_->callback == nullptr) { 92bc03f14fSopenharmony_ci napi_create_promise(env, &context_->defer, &promise); 93bc03f14fSopenharmony_ci } else { 94bc03f14fSopenharmony_ci napi_get_undefined(env, &promise); 95bc03f14fSopenharmony_ci } 96bc03f14fSopenharmony_ci AsyncCall::OnExecute(env, context_); 97bc03f14fSopenharmony_ci AsyncCall::OnComplete(env, napi_ok, context_); 98bc03f14fSopenharmony_ci return promise; 99bc03f14fSopenharmony_ci} 100bc03f14fSopenharmony_ci 101bc03f14fSopenharmony_civoid AsyncCall::OnExecute(napi_env env, void *data) 102bc03f14fSopenharmony_ci{ 103bc03f14fSopenharmony_ci AsyncContext *context = reinterpret_cast<AsyncContext *>(data); 104bc03f14fSopenharmony_ci context->ctx->Exec(); 105bc03f14fSopenharmony_ci} 106bc03f14fSopenharmony_ci 107bc03f14fSopenharmony_civoid AsyncCall::OnComplete(napi_env env, napi_status status, void *data) 108bc03f14fSopenharmony_ci{ 109bc03f14fSopenharmony_ci AsyncContext *context = reinterpret_cast<AsyncContext *>(data); 110bc03f14fSopenharmony_ci napi_value output = nullptr; 111bc03f14fSopenharmony_ci napi_status runStatus = (*context->ctx)(env, &output); 112bc03f14fSopenharmony_ci napi_value result[ARG_BUTT] = { 0 }; 113bc03f14fSopenharmony_ci PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, 114bc03f14fSopenharmony_ci "run the js callback function:status[%{public}d]runStatus[%{public}d]", status, runStatus); 115bc03f14fSopenharmony_ci if (status == napi_ok && runStatus == napi_ok) { 116bc03f14fSopenharmony_ci napi_get_undefined(env, &result[ARG_ERROR]); 117bc03f14fSopenharmony_ci if (output != nullptr) { 118bc03f14fSopenharmony_ci result[ARG_DATA] = output; 119bc03f14fSopenharmony_ci } else { 120bc03f14fSopenharmony_ci PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "AsyncCall::OnComplete output == nullptr"); 121bc03f14fSopenharmony_ci napi_get_undefined(env, &result[ARG_DATA]); 122bc03f14fSopenharmony_ci } 123bc03f14fSopenharmony_ci } else { 124bc03f14fSopenharmony_ci napi_value errCode = nullptr; 125bc03f14fSopenharmony_ci napi_value message = nullptr; 126bc03f14fSopenharmony_ci std::string errMsg("async call failed"); 127bc03f14fSopenharmony_ci if (context->ctx->errCode_ != 0) { 128bc03f14fSopenharmony_ci napi_create_string_utf8(env, std::to_string(context->ctx->errCode_).c_str(), NAPI_AUTO_LENGTH, &errCode); 129bc03f14fSopenharmony_ci } 130bc03f14fSopenharmony_ci if (!context->ctx->errMsg_.empty()) { 131bc03f14fSopenharmony_ci errMsg = context->ctx->errMsg_; 132bc03f14fSopenharmony_ci } 133bc03f14fSopenharmony_ci napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message); 134bc03f14fSopenharmony_ci napi_create_error(env, errCode, message, &result[ARG_ERROR]); 135bc03f14fSopenharmony_ci napi_get_undefined(env, &result[ARG_DATA]); 136bc03f14fSopenharmony_ci } 137bc03f14fSopenharmony_ci if (context->defer != nullptr) { 138bc03f14fSopenharmony_ci // promise 139bc03f14fSopenharmony_ci if (status == napi_ok && runStatus == napi_ok) { 140bc03f14fSopenharmony_ci napi_resolve_deferred(env, context->defer, result[ARG_DATA]); 141bc03f14fSopenharmony_ci } else { 142bc03f14fSopenharmony_ci napi_reject_deferred(env, context->defer, result[ARG_ERROR]); 143bc03f14fSopenharmony_ci } 144bc03f14fSopenharmony_ci } else { 145bc03f14fSopenharmony_ci // callback 146bc03f14fSopenharmony_ci PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "Callback to do!"); 147bc03f14fSopenharmony_ci napi_value callback = nullptr; 148bc03f14fSopenharmony_ci napi_get_reference_value(env, context->callback, &callback); 149bc03f14fSopenharmony_ci napi_value returnValue; 150bc03f14fSopenharmony_ci napi_call_function(env, nullptr, callback, ARG_BUTT, result, &returnValue); 151bc03f14fSopenharmony_ci } 152bc03f14fSopenharmony_ci DeleteContext(env, context); 153bc03f14fSopenharmony_ci} 154bc03f14fSopenharmony_civoid AsyncCall::DeleteContext(napi_env env, AsyncContext *context) 155bc03f14fSopenharmony_ci{ 156bc03f14fSopenharmony_ci if (env != nullptr) { 157bc03f14fSopenharmony_ci napi_delete_reference(env, context->callback); 158bc03f14fSopenharmony_ci napi_delete_reference(env, context->self); 159bc03f14fSopenharmony_ci napi_delete_async_work(env, context->work); 160bc03f14fSopenharmony_ci } 161bc03f14fSopenharmony_ci delete context; 162bc03f14fSopenharmony_ci} 163bc03f14fSopenharmony_ci} // namespace OHOS::MiscServicesNapi