10fbfc30aSopenharmony_ci/* 20fbfc30aSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 30fbfc30aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 40fbfc30aSopenharmony_ci * you may not use this file except in compliance with the License. 50fbfc30aSopenharmony_ci * You may obtain a copy of the License at 60fbfc30aSopenharmony_ci * 70fbfc30aSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 80fbfc30aSopenharmony_ci * 90fbfc30aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 100fbfc30aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 110fbfc30aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 120fbfc30aSopenharmony_ci * See the License for the specific language governing permissions and 130fbfc30aSopenharmony_ci * limitations under the License. 140fbfc30aSopenharmony_ci */ 150fbfc30aSopenharmony_ci 160fbfc30aSopenharmony_ci#include "napi_queue.h" 170fbfc30aSopenharmony_cinamespace OHOS::CalendarApi { 180fbfc30aSopenharmony_ciContextBase::~ContextBase() 190fbfc30aSopenharmony_ci{ 200fbfc30aSopenharmony_ci LOG_DEBUG("no memory leak after callback or promise[resolved/rejected]"); 210fbfc30aSopenharmony_ci if (env != nullptr) { 220fbfc30aSopenharmony_ci if (callbackRef != nullptr) { 230fbfc30aSopenharmony_ci auto status = napi_delete_reference(env, callbackRef); 240fbfc30aSopenharmony_ci LOG_DEBUG("status:%{public}d", status); 250fbfc30aSopenharmony_ci } 260fbfc30aSopenharmony_ci if (selfRef != nullptr) { 270fbfc30aSopenharmony_ci auto status = napi_delete_reference(env, selfRef); 280fbfc30aSopenharmony_ci LOG_DEBUG("status:%{public}d", status); 290fbfc30aSopenharmony_ci } 300fbfc30aSopenharmony_ci env = nullptr; 310fbfc30aSopenharmony_ci } 320fbfc30aSopenharmony_ci} 330fbfc30aSopenharmony_ci 340fbfc30aSopenharmony_civoid ContextBase::GetCbInfo(napi_env envi, napi_callback_info info, NapiCbInfoParser parse, bool sync) 350fbfc30aSopenharmony_ci{ 360fbfc30aSopenharmony_ci env = envi; 370fbfc30aSopenharmony_ci size_t argc = ARGC_MAX; 380fbfc30aSopenharmony_ci napi_value argv[ARGC_MAX] = { nullptr }; 390fbfc30aSopenharmony_ci status = napi_get_cb_info(env, info, &argc, argv, &self, nullptr); 400fbfc30aSopenharmony_ci CHECK_STATUS_RETURN_VOID(this, " napi_get_cb_info failed!"); 410fbfc30aSopenharmony_ci CHECK_ARGS_RETURN_VOID(this, argc <= ARGC_MAX, " too many arguments!"); 420fbfc30aSopenharmony_ci CHECK_ARGS_RETURN_VOID(this, self != nullptr, " no JavaScript this argument!"); 430fbfc30aSopenharmony_ci if (!sync) { 440fbfc30aSopenharmony_ci napi_create_reference(env, self, 1, &selfRef); 450fbfc30aSopenharmony_ci } 460fbfc30aSopenharmony_ci status = napi_unwrap(env, self, &native); 470fbfc30aSopenharmony_ci CHECK_STATUS_RETURN_VOID(this, " self unwrap failed!"); 480fbfc30aSopenharmony_ci 490fbfc30aSopenharmony_ci if (!sync && (argc > 0)) { 500fbfc30aSopenharmony_ci // get the last arguments :: <callback> 510fbfc30aSopenharmony_ci size_t index = argc - 1; 520fbfc30aSopenharmony_ci napi_valuetype type = napi_undefined; 530fbfc30aSopenharmony_ci napi_status tyst = napi_typeof(env, argv[index], &type); 540fbfc30aSopenharmony_ci if ((tyst == napi_ok) && (type == napi_function)) { 550fbfc30aSopenharmony_ci status = napi_create_reference(env, argv[index], 1, &callbackRef); 560fbfc30aSopenharmony_ci CHECK_STATUS_RETURN_VOID(this, " ref callback failed!"); 570fbfc30aSopenharmony_ci argc = index; 580fbfc30aSopenharmony_ci LOG_DEBUG(" async callback, no promise"); 590fbfc30aSopenharmony_ci } else { 600fbfc30aSopenharmony_ci LOG_DEBUG(" no callback, async pormose"); 610fbfc30aSopenharmony_ci } 620fbfc30aSopenharmony_ci } 630fbfc30aSopenharmony_ci 640fbfc30aSopenharmony_ci if (parse) { 650fbfc30aSopenharmony_ci parse(argc, argv); 660fbfc30aSopenharmony_ci } else { 670fbfc30aSopenharmony_ci CHECK_ARGS_RETURN_VOID(this, argc == 0, " required no arguments!"); 680fbfc30aSopenharmony_ci } 690fbfc30aSopenharmony_ci} 700fbfc30aSopenharmony_ci 710fbfc30aSopenharmony_cinapi_value NapiQueue::AsyncWork(napi_env env, std::shared_ptr<ContextBase> ctxt, const std::string& name, 720fbfc30aSopenharmony_ci NapiAsyncExecute execute, NapiAsyncComplete complete) 730fbfc30aSopenharmony_ci{ 740fbfc30aSopenharmony_ci LOG_DEBUG("name = %{public}s", name.c_str()); 750fbfc30aSopenharmony_ci AsyncContext *aCtx = new AsyncContext; 760fbfc30aSopenharmony_ci aCtx->env = env; 770fbfc30aSopenharmony_ci aCtx->ctx = std::move(ctxt); 780fbfc30aSopenharmony_ci aCtx->execute = std::move(execute); 790fbfc30aSopenharmony_ci aCtx->complete = std::move(complete); 800fbfc30aSopenharmony_ci napi_value promise = nullptr; 810fbfc30aSopenharmony_ci if (aCtx->ctx->callbackRef == nullptr) { 820fbfc30aSopenharmony_ci napi_create_promise(env, &aCtx->deferred, &promise); 830fbfc30aSopenharmony_ci LOG_DEBUG("AsyncWork create deferred promise"); 840fbfc30aSopenharmony_ci } else { 850fbfc30aSopenharmony_ci napi_get_undefined(env, &promise); 860fbfc30aSopenharmony_ci } 870fbfc30aSopenharmony_ci 880fbfc30aSopenharmony_ci napi_value resource = nullptr; 890fbfc30aSopenharmony_ci napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &resource); 900fbfc30aSopenharmony_ci napi_create_async_work( 910fbfc30aSopenharmony_ci env, nullptr, resource, 920fbfc30aSopenharmony_ci [](napi_env env, void* data) { 930fbfc30aSopenharmony_ci CHECK_RETURN_VOID(data != nullptr, "AsyncWork napi_async_execute_callback nullptr"); 940fbfc30aSopenharmony_ci auto actx = reinterpret_cast<AsyncContext*>(data); 950fbfc30aSopenharmony_ci LOG_DEBUG("AsyncWork napi_async_execute_callback ctxt->status=%{public}d", actx->ctx->status); 960fbfc30aSopenharmony_ci if (actx->execute && actx->ctx->status == napi_ok) { 970fbfc30aSopenharmony_ci actx->execute(); 980fbfc30aSopenharmony_ci } 990fbfc30aSopenharmony_ci }, 1000fbfc30aSopenharmony_ci [](napi_env env, napi_status status, void* data) { 1010fbfc30aSopenharmony_ci CHECK_RETURN_VOID(data != nullptr, "AsyncWork napi_async_complete_callback nullptr"); 1020fbfc30aSopenharmony_ci auto actx = reinterpret_cast<AsyncContext*>(data); 1030fbfc30aSopenharmony_ci LOG_DEBUG("AsyncWork napi_async_complete_callback status = %{public}d, ctxt->status = %{public}d", 1040fbfc30aSopenharmony_ci status, actx->ctx->status); 1050fbfc30aSopenharmony_ci if ((status != napi_ok) && (actx->ctx->status == napi_ok)) { 1060fbfc30aSopenharmony_ci actx->ctx->status = status; 1070fbfc30aSopenharmony_ci } 1080fbfc30aSopenharmony_ci napi_value output = nullptr; 1090fbfc30aSopenharmony_ci if ((actx->complete) && (status == napi_ok) && (actx->ctx->status == napi_ok)) { 1100fbfc30aSopenharmony_ci actx->complete(output); 1110fbfc30aSopenharmony_ci } 1120fbfc30aSopenharmony_ci GenerateOutput(*actx, output); 1130fbfc30aSopenharmony_ci delete actx; 1140fbfc30aSopenharmony_ci }, 1150fbfc30aSopenharmony_ci reinterpret_cast<void*>(aCtx), &aCtx->work); 1160fbfc30aSopenharmony_ci auto status = napi_queue_async_work(env, aCtx->work); 1170fbfc30aSopenharmony_ci if (status != napi_ok) { 1180fbfc30aSopenharmony_ci napi_get_undefined(env, &promise); 1190fbfc30aSopenharmony_ci delete aCtx; 1200fbfc30aSopenharmony_ci } 1210fbfc30aSopenharmony_ci return promise; 1220fbfc30aSopenharmony_ci} 1230fbfc30aSopenharmony_ci 1240fbfc30aSopenharmony_civoid NapiQueue::GenerateOutput(AsyncContext &ctx, napi_value output) 1250fbfc30aSopenharmony_ci{ 1260fbfc30aSopenharmony_ci napi_value result[RESULT_ALL] = { nullptr }; 1270fbfc30aSopenharmony_ci if (ctx.ctx->status == napi_ok) { 1280fbfc30aSopenharmony_ci napi_get_undefined(ctx.env, &result[RESULT_ERROR]); 1290fbfc30aSopenharmony_ci if (output == nullptr) { 1300fbfc30aSopenharmony_ci napi_get_undefined(ctx.env, &output); 1310fbfc30aSopenharmony_ci } 1320fbfc30aSopenharmony_ci result[RESULT_DATA] = output; 1330fbfc30aSopenharmony_ci } else { 1340fbfc30aSopenharmony_ci napi_value message = nullptr; 1350fbfc30aSopenharmony_ci napi_create_string_utf8(ctx.env, ctx.ctx->error.c_str(), NAPI_AUTO_LENGTH, &message); 1360fbfc30aSopenharmony_ci napi_create_error(ctx.env, nullptr, message, &result[RESULT_ERROR]); 1370fbfc30aSopenharmony_ci napi_get_undefined(ctx.env, &result[RESULT_DATA]); 1380fbfc30aSopenharmony_ci } 1390fbfc30aSopenharmony_ci if (ctx.deferred != nullptr) { 1400fbfc30aSopenharmony_ci if (ctx.ctx->status == napi_ok) { 1410fbfc30aSopenharmony_ci LOG_DEBUG("GenerateOutput deferred promise resolved"); 1420fbfc30aSopenharmony_ci napi_resolve_deferred(ctx.env, ctx.deferred, result[RESULT_DATA]); 1430fbfc30aSopenharmony_ci } else { 1440fbfc30aSopenharmony_ci LOG_DEBUG("GenerateOutput deferred promise rejected"); 1450fbfc30aSopenharmony_ci napi_reject_deferred(ctx.env, ctx.deferred, result[RESULT_ERROR]); 1460fbfc30aSopenharmony_ci } 1470fbfc30aSopenharmony_ci } else { 1480fbfc30aSopenharmony_ci napi_value callback = nullptr; 1490fbfc30aSopenharmony_ci napi_get_reference_value(ctx.env, ctx.ctx->callbackRef, &callback); 1500fbfc30aSopenharmony_ci napi_value callbackResult = nullptr; 1510fbfc30aSopenharmony_ci LOG_DEBUG("GenerateOutput call callback function"); 1520fbfc30aSopenharmony_ci napi_call_function(ctx.env, nullptr, callback, RESULT_ALL, result, &callbackResult); 1530fbfc30aSopenharmony_ci } 1540fbfc30aSopenharmony_ci} 1550fbfc30aSopenharmony_ci} // namespace OHOS::Calendar