133eb0b6dSopenharmony_ci/* 233eb0b6dSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 333eb0b6dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 433eb0b6dSopenharmony_ci * you may not use this file except in compliance with the License. 533eb0b6dSopenharmony_ci * You may obtain a copy of the License at 633eb0b6dSopenharmony_ci * 733eb0b6dSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 833eb0b6dSopenharmony_ci * 933eb0b6dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1033eb0b6dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1133eb0b6dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1233eb0b6dSopenharmony_ci * See the License for the specific language governing permissions and 1333eb0b6dSopenharmony_ci * limitations under the License. 1433eb0b6dSopenharmony_ci */ 1533eb0b6dSopenharmony_ci 1633eb0b6dSopenharmony_ci#include "ecmascript/napi/include/jsnapi.h" 1733eb0b6dSopenharmony_ci#include "napi/native_node_api.h" 1833eb0b6dSopenharmony_ci#include "native_api_internal.h" 1933eb0b6dSopenharmony_ci#include "native_engine/impl/ark/ark_native_options.h" 2033eb0b6dSopenharmony_ci#include "native_engine/native_async_hook_context.h" 2133eb0b6dSopenharmony_ci#include "native_engine/native_engine.h" 2233eb0b6dSopenharmony_ci#include "native_engine/native_utils.h" 2333eb0b6dSopenharmony_ci#include "utils/log.h" 2433eb0b6dSopenharmony_ci 2533eb0b6dSopenharmony_ciusing panda::Local; 2633eb0b6dSopenharmony_ciusing panda::StringRef; 2733eb0b6dSopenharmony_ci 2833eb0b6dSopenharmony_cistatic constexpr int32_t MAX_THREAD_SAFE_COUNT = 128; 2933eb0b6dSopenharmony_ci 3033eb0b6dSopenharmony_ciNAPI_EXTERN void napi_module_register(napi_module* mod) 3133eb0b6dSopenharmony_ci{ 3233eb0b6dSopenharmony_ci if (mod == nullptr) { 3333eb0b6dSopenharmony_ci HILOG_ERROR("mod is nullptr"); 3433eb0b6dSopenharmony_ci return; 3533eb0b6dSopenharmony_ci } 3633eb0b6dSopenharmony_ci 3733eb0b6dSopenharmony_ci NativeModuleManager* moduleManager = NativeModuleManager::GetInstance(); 3833eb0b6dSopenharmony_ci NativeModule module; 3933eb0b6dSopenharmony_ci 4033eb0b6dSopenharmony_ci module.version = mod->nm_version; 4133eb0b6dSopenharmony_ci module.fileName = mod->nm_filename; 4233eb0b6dSopenharmony_ci module.name = mod->nm_modname; 4333eb0b6dSopenharmony_ci module.flags = mod->nm_flags; 4433eb0b6dSopenharmony_ci module.registerCallback = (RegisterCallback)mod->nm_register_func; 4533eb0b6dSopenharmony_ci 4633eb0b6dSopenharmony_ci moduleManager->Register(&module); 4733eb0b6dSopenharmony_ci} 4833eb0b6dSopenharmony_ci 4933eb0b6dSopenharmony_ciNAPI_EXTERN void napi_module_with_js_register(napi_module_with_js* mod) 5033eb0b6dSopenharmony_ci{ 5133eb0b6dSopenharmony_ci if (mod == nullptr) { 5233eb0b6dSopenharmony_ci HILOG_ERROR("mod is nullptr"); 5333eb0b6dSopenharmony_ci return; 5433eb0b6dSopenharmony_ci } 5533eb0b6dSopenharmony_ci 5633eb0b6dSopenharmony_ci NativeModuleManager* moduleManager = NativeModuleManager::GetInstance(); 5733eb0b6dSopenharmony_ci NativeModule module; 5833eb0b6dSopenharmony_ci 5933eb0b6dSopenharmony_ci module.version = mod->nm_version; 6033eb0b6dSopenharmony_ci module.fileName = mod->nm_filename; 6133eb0b6dSopenharmony_ci module.name = mod->nm_modname; 6233eb0b6dSopenharmony_ci module.registerCallback = (RegisterCallback)mod->nm_register_func; 6333eb0b6dSopenharmony_ci module.getJSCode = (GetJSCodeCallback)mod->nm_get_js_code; 6433eb0b6dSopenharmony_ci module.getABCCode = (GetJSCodeCallback)mod->nm_get_abc_code; 6533eb0b6dSopenharmony_ci 6633eb0b6dSopenharmony_ci moduleManager->Register(&module); 6733eb0b6dSopenharmony_ci} 6833eb0b6dSopenharmony_ci 6933eb0b6dSopenharmony_ciNAPI_EXTERN NAPI_NO_RETURN void napi_fatal_error(const char* location, 7033eb0b6dSopenharmony_ci size_t location_len, 7133eb0b6dSopenharmony_ci const char* message, 7233eb0b6dSopenharmony_ci size_t message_len) 7333eb0b6dSopenharmony_ci{ 7433eb0b6dSopenharmony_ci (void)location_len; 7533eb0b6dSopenharmony_ci (void)message_len; 7633eb0b6dSopenharmony_ci HILOG_FATAL("FATAL ERROR: %{public}s %{public}s\n", location, message); 7733eb0b6dSopenharmony_ci} 7833eb0b6dSopenharmony_ci 7933eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_create_limit_runtime(napi_env env, napi_env* result_env) 8033eb0b6dSopenharmony_ci{ 8133eb0b6dSopenharmony_ci CHECK_ENV(env); 8233eb0b6dSopenharmony_ci CHECK_ARG(env, result_env); 8333eb0b6dSopenharmony_ci 8433eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 8533eb0b6dSopenharmony_ci 8633eb0b6dSopenharmony_ci auto result = engine->CreateRuntime(true); 8733eb0b6dSopenharmony_ci *result_env = reinterpret_cast<napi_env>(result); 8833eb0b6dSopenharmony_ci 8933eb0b6dSopenharmony_ci return napi_clear_last_error(env); 9033eb0b6dSopenharmony_ci} 9133eb0b6dSopenharmony_ci 9233eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_fatal_exception(napi_env env, napi_value err) 9333eb0b6dSopenharmony_ci{ 9433eb0b6dSopenharmony_ci NAPI_PREAMBLE(env); 9533eb0b6dSopenharmony_ci CHECK_ENV(env); 9633eb0b6dSopenharmony_ci CHECK_ARG(env, err); 9733eb0b6dSopenharmony_ci 9833eb0b6dSopenharmony_ci auto exceptionValue = LocalValueFromJsValue(err); 9933eb0b6dSopenharmony_ci auto ecmaVm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm(); 10033eb0b6dSopenharmony_ci RETURN_STATUS_IF_FALSE(env, exceptionValue->IsError(ecmaVm), napi_invalid_arg); 10133eb0b6dSopenharmony_ci 10233eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 10333eb0b6dSopenharmony_ci engine->TriggerFatalException(exceptionValue); 10433eb0b6dSopenharmony_ci return napi_ok; 10533eb0b6dSopenharmony_ci} 10633eb0b6dSopenharmony_ci 10733eb0b6dSopenharmony_ci// Methods to manage simple async operations 10833eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_create_async_work(napi_env env, 10933eb0b6dSopenharmony_ci napi_value async_resource, 11033eb0b6dSopenharmony_ci napi_value async_resource_name, 11133eb0b6dSopenharmony_ci napi_async_execute_callback execute, 11233eb0b6dSopenharmony_ci napi_async_complete_callback complete, 11333eb0b6dSopenharmony_ci void* data, 11433eb0b6dSopenharmony_ci napi_async_work* result) 11533eb0b6dSopenharmony_ci{ 11633eb0b6dSopenharmony_ci CHECK_ENV(env); 11733eb0b6dSopenharmony_ci CHECK_ARG(env, async_resource_name); 11833eb0b6dSopenharmony_ci CHECK_ARG(env, execute); 11933eb0b6dSopenharmony_ci CHECK_ARG(env, complete); 12033eb0b6dSopenharmony_ci CHECK_ARG(env, result); 12133eb0b6dSopenharmony_ci 12233eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 12333eb0b6dSopenharmony_ci auto ecmaVm = engine->GetEcmaVm(); 12433eb0b6dSopenharmony_ci auto asyncResource = LocalValueFromJsValue(async_resource); 12533eb0b6dSopenharmony_ci auto asyncResourceName = LocalValueFromJsValue(async_resource_name); 12633eb0b6dSopenharmony_ci auto asyncExecute = reinterpret_cast<NativeAsyncExecuteCallback>(execute); 12733eb0b6dSopenharmony_ci auto asyncComplete = reinterpret_cast<NativeAsyncCompleteCallback>(complete); 12833eb0b6dSopenharmony_ci (void)asyncResource; 12933eb0b6dSopenharmony_ci (void)asyncResourceName; 13033eb0b6dSopenharmony_ci char name[64] = {0}; // 64:NAME_BUFFER_SIZE 13133eb0b6dSopenharmony_ci if (!asyncResourceName->IsNull()) { 13233eb0b6dSopenharmony_ci panda::Local<panda::StringRef> nativeString(asyncResourceName); 13333eb0b6dSopenharmony_ci uint32_t copied = nativeString->WriteUtf8(ecmaVm, name, 63, true) - 1; // 63:NAME_BUFFER_SIZE 13433eb0b6dSopenharmony_ci name[copied] = '\0'; 13533eb0b6dSopenharmony_ci } 13633eb0b6dSopenharmony_ci auto asyncWork = new NativeAsyncWork(engine, asyncExecute, asyncComplete, name, data); 13733eb0b6dSopenharmony_ci *result = reinterpret_cast<napi_async_work>(asyncWork); 13833eb0b6dSopenharmony_ci return napi_status::napi_ok; 13933eb0b6dSopenharmony_ci} 14033eb0b6dSopenharmony_ci 14133eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_delete_async_work(napi_env env, napi_async_work work) 14233eb0b6dSopenharmony_ci{ 14333eb0b6dSopenharmony_ci CHECK_ENV(env); 14433eb0b6dSopenharmony_ci CHECK_ARG(env, work); 14533eb0b6dSopenharmony_ci 14633eb0b6dSopenharmony_ci auto asyncWork = reinterpret_cast<NativeAsyncWork*>(work); 14733eb0b6dSopenharmony_ci delete asyncWork; 14833eb0b6dSopenharmony_ci asyncWork = nullptr; 14933eb0b6dSopenharmony_ci 15033eb0b6dSopenharmony_ci return napi_status::napi_ok; 15133eb0b6dSopenharmony_ci} 15233eb0b6dSopenharmony_ci 15333eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_queue_async_work(napi_env env, napi_async_work work) 15433eb0b6dSopenharmony_ci{ 15533eb0b6dSopenharmony_ci CHECK_ENV(env); 15633eb0b6dSopenharmony_ci CHECK_ARG(env, work); 15733eb0b6dSopenharmony_ci 15833eb0b6dSopenharmony_ci auto asyncWork = reinterpret_cast<NativeAsyncWork*>(work); 15933eb0b6dSopenharmony_ci 16033eb0b6dSopenharmony_ci asyncWork->Queue(); 16133eb0b6dSopenharmony_ci return napi_status::napi_ok; 16233eb0b6dSopenharmony_ci} 16333eb0b6dSopenharmony_ci 16433eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_cancel_async_work(napi_env env, napi_async_work work) 16533eb0b6dSopenharmony_ci{ 16633eb0b6dSopenharmony_ci CHECK_ENV(env); 16733eb0b6dSopenharmony_ci CHECK_ARG(env, work); 16833eb0b6dSopenharmony_ci 16933eb0b6dSopenharmony_ci auto asyncWork = reinterpret_cast<NativeAsyncWork*>(work); 17033eb0b6dSopenharmony_ci 17133eb0b6dSopenharmony_ci asyncWork->Cancel(); 17233eb0b6dSopenharmony_ci return napi_status::napi_ok; 17333eb0b6dSopenharmony_ci} 17433eb0b6dSopenharmony_ci 17533eb0b6dSopenharmony_ci// Version management 17633eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_get_node_version(napi_env env, const napi_node_version** version) 17733eb0b6dSopenharmony_ci{ 17833eb0b6dSopenharmony_ci (void)version; 17933eb0b6dSopenharmony_ci return napi_status::napi_ok; 18033eb0b6dSopenharmony_ci} 18133eb0b6dSopenharmony_ci 18233eb0b6dSopenharmony_ci// Return the current libuv event loop for a given environment 18333eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_get_uv_event_loop(napi_env env, struct uv_loop_s** loop) 18433eb0b6dSopenharmony_ci{ 18533eb0b6dSopenharmony_ci CHECK_ENV(env); 18633eb0b6dSopenharmony_ci CHECK_ARG(env, loop); 18733eb0b6dSopenharmony_ci 18833eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 18933eb0b6dSopenharmony_ci if (!NativeEngine::IsAlive(engine)) { 19033eb0b6dSopenharmony_ci HILOG_ERROR("napi_env has been destoryed!"); 19133eb0b6dSopenharmony_ci return napi_status::napi_generic_failure; 19233eb0b6dSopenharmony_ci } 19333eb0b6dSopenharmony_ci *loop = engine->GetUVLoop(); 19433eb0b6dSopenharmony_ci 19533eb0b6dSopenharmony_ci return napi_status::napi_ok; 19633eb0b6dSopenharmony_ci} 19733eb0b6dSopenharmony_ci 19833eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_add_env_cleanup_hook(napi_env env, void (*fun)(void* arg), void* arg) 19933eb0b6dSopenharmony_ci{ 20033eb0b6dSopenharmony_ci CHECK_ENV(env); 20133eb0b6dSopenharmony_ci CHECK_ARG(env, fun); 20233eb0b6dSopenharmony_ci WEAK_CROSS_THREAD_CHECK(env); 20333eb0b6dSopenharmony_ci 20433eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 20533eb0b6dSopenharmony_ci engine->AddCleanupHook(fun, arg); 20633eb0b6dSopenharmony_ci 20733eb0b6dSopenharmony_ci return napi_clear_last_error(env); 20833eb0b6dSopenharmony_ci} 20933eb0b6dSopenharmony_ci 21033eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_remove_env_cleanup_hook(napi_env env, void (*fun)(void* arg), void* arg) 21133eb0b6dSopenharmony_ci{ 21233eb0b6dSopenharmony_ci CHECK_ENV(env); 21333eb0b6dSopenharmony_ci CHECK_ARG(env, fun); 21433eb0b6dSopenharmony_ci WEAK_CROSS_THREAD_CHECK(env); 21533eb0b6dSopenharmony_ci 21633eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 21733eb0b6dSopenharmony_ci engine->RemoveCleanupHook(fun, arg); 21833eb0b6dSopenharmony_ci 21933eb0b6dSopenharmony_ci return napi_clear_last_error(env); 22033eb0b6dSopenharmony_ci} 22133eb0b6dSopenharmony_ci 22233eb0b6dSopenharmony_ciusing CleanupHook = void (*)(void* arg); 22333eb0b6dSopenharmony_ciusing AsyncCleanupHook = void (*)(void* arg, void (*)(void*), void*); 22433eb0b6dSopenharmony_ci 22533eb0b6dSopenharmony_cistruct AsyncCleanupHookInfo final { 22633eb0b6dSopenharmony_ci napi_env env_; 22733eb0b6dSopenharmony_ci AsyncCleanupHook fun_; 22833eb0b6dSopenharmony_ci void* arg_; 22933eb0b6dSopenharmony_ci bool started_ = false; 23033eb0b6dSopenharmony_ci // Use a self-reference to make sure the storage is kept alive while the 23133eb0b6dSopenharmony_ci // cleanup hook is registered but not yet finished. 23233eb0b6dSopenharmony_ci std::shared_ptr<AsyncCleanupHookInfo> self_; 23333eb0b6dSopenharmony_ci}; 23433eb0b6dSopenharmony_ci 23533eb0b6dSopenharmony_ci// Opaque type that is basically an alias for `shared_ptr<AsyncCleanupHookInfo>` 23633eb0b6dSopenharmony_ci// (but not publicly so for easier ABI/API changes). In particular, 23733eb0b6dSopenharmony_ci// std::shared_ptr does not generally maintain a consistent ABI even on a 23833eb0b6dSopenharmony_ci// specific platform. 23933eb0b6dSopenharmony_cistruct ACHHandle final { 24033eb0b6dSopenharmony_ci std::shared_ptr<AsyncCleanupHookInfo> info_; 24133eb0b6dSopenharmony_ci}; 24233eb0b6dSopenharmony_ci 24333eb0b6dSopenharmony_cistruct DeleteACHHandle { 24433eb0b6dSopenharmony_ci void operator()(ACHHandle* handle) const 24533eb0b6dSopenharmony_ci { 24633eb0b6dSopenharmony_ci delete handle; 24733eb0b6dSopenharmony_ci }; 24833eb0b6dSopenharmony_ci}; 24933eb0b6dSopenharmony_ciusing AsyncCleanupHookHandle = std::unique_ptr<ACHHandle, DeleteACHHandle>; 25033eb0b6dSopenharmony_ci 25133eb0b6dSopenharmony_cistatic void FinishAsyncCleanupHook(void* arg) 25233eb0b6dSopenharmony_ci{ 25333eb0b6dSopenharmony_ci HILOG_INFO("%{public}s, start.", __func__); 25433eb0b6dSopenharmony_ci AsyncCleanupHookInfo* info = static_cast<AsyncCleanupHookInfo*>(arg); 25533eb0b6dSopenharmony_ci std::shared_ptr<AsyncCleanupHookInfo> keep_alive = info->self_; 25633eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(info->env_); 25733eb0b6dSopenharmony_ci engine->DecreaseWaitingRequestCounter(); 25833eb0b6dSopenharmony_ci info->self_.reset(); 25933eb0b6dSopenharmony_ci HILOG_INFO("%{public}s, end.", __func__); 26033eb0b6dSopenharmony_ci} 26133eb0b6dSopenharmony_ci 26233eb0b6dSopenharmony_cistatic void RunAsyncCleanupHook(void* arg) 26333eb0b6dSopenharmony_ci{ 26433eb0b6dSopenharmony_ci HILOG_INFO("%{public}s, start.", __func__); 26533eb0b6dSopenharmony_ci AsyncCleanupHookInfo* info = static_cast<AsyncCleanupHookInfo*>(arg); 26633eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(info->env_); 26733eb0b6dSopenharmony_ci engine->IncreaseWaitingRequestCounter(); 26833eb0b6dSopenharmony_ci info->started_ = true; 26933eb0b6dSopenharmony_ci info->fun_(info->arg_, FinishAsyncCleanupHook, info); 27033eb0b6dSopenharmony_ci HILOG_INFO("%{public}s, end.", __func__); 27133eb0b6dSopenharmony_ci} 27233eb0b6dSopenharmony_ci 27333eb0b6dSopenharmony_cistatic AsyncCleanupHookHandle AddEnvironmentCleanupHook(napi_env env, AsyncCleanupHook fun, void* arg) 27433eb0b6dSopenharmony_ci{ 27533eb0b6dSopenharmony_ci HILOG_INFO("%{public}s, start.", __func__); 27633eb0b6dSopenharmony_ci auto info = std::make_shared<AsyncCleanupHookInfo>(); 27733eb0b6dSopenharmony_ci info->env_ = env; 27833eb0b6dSopenharmony_ci info->fun_ = fun; 27933eb0b6dSopenharmony_ci info->arg_ = arg; 28033eb0b6dSopenharmony_ci info->self_ = info; 28133eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 28233eb0b6dSopenharmony_ci engine->AddCleanupHook(RunAsyncCleanupHook, info.get()); 28333eb0b6dSopenharmony_ci HILOG_INFO("%{public}s, end.", __func__); 28433eb0b6dSopenharmony_ci return AsyncCleanupHookHandle(new ACHHandle { info }); 28533eb0b6dSopenharmony_ci} 28633eb0b6dSopenharmony_ci 28733eb0b6dSopenharmony_cistatic void RemoveEnvironmentCleanupHook(AsyncCleanupHookHandle handle) 28833eb0b6dSopenharmony_ci{ 28933eb0b6dSopenharmony_ci if (handle->info_->started_) { 29033eb0b6dSopenharmony_ci return; 29133eb0b6dSopenharmony_ci } 29233eb0b6dSopenharmony_ci handle->info_->self_.reset(); 29333eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(handle->info_->env_); 29433eb0b6dSopenharmony_ci engine->RemoveCleanupHook(RunAsyncCleanupHook, handle->info_.get()); 29533eb0b6dSopenharmony_ci} 29633eb0b6dSopenharmony_ci 29733eb0b6dSopenharmony_cistruct napi_async_cleanup_hook_handle__ { 29833eb0b6dSopenharmony_ci napi_async_cleanup_hook_handle__(napi_env env, napi_async_cleanup_hook user_hook, void* user_data) 29933eb0b6dSopenharmony_ci : env_(env), user_hook_(user_hook), user_data_(user_data) 30033eb0b6dSopenharmony_ci { 30133eb0b6dSopenharmony_ci handle_ = AddEnvironmentCleanupHook(env, Hook, this); 30233eb0b6dSopenharmony_ci } 30333eb0b6dSopenharmony_ci 30433eb0b6dSopenharmony_ci ~napi_async_cleanup_hook_handle__() 30533eb0b6dSopenharmony_ci { 30633eb0b6dSopenharmony_ci RemoveEnvironmentCleanupHook(std::move(handle_)); 30733eb0b6dSopenharmony_ci if (done_cb_ != nullptr) { 30833eb0b6dSopenharmony_ci done_cb_(done_data_); 30933eb0b6dSopenharmony_ci } 31033eb0b6dSopenharmony_ci } 31133eb0b6dSopenharmony_ci 31233eb0b6dSopenharmony_ci static void Hook(void* data, void (*done_cb)(void*), void* done_data) 31333eb0b6dSopenharmony_ci { 31433eb0b6dSopenharmony_ci auto handle = static_cast<napi_async_cleanup_hook_handle__*>(data); 31533eb0b6dSopenharmony_ci handle->done_cb_ = done_cb; 31633eb0b6dSopenharmony_ci handle->done_data_ = done_data; 31733eb0b6dSopenharmony_ci handle->user_hook_(handle, handle->user_data_); 31833eb0b6dSopenharmony_ci } 31933eb0b6dSopenharmony_ci 32033eb0b6dSopenharmony_ci AsyncCleanupHookHandle handle_; 32133eb0b6dSopenharmony_ci napi_env env_ = nullptr; 32233eb0b6dSopenharmony_ci napi_async_cleanup_hook user_hook_ = nullptr; 32333eb0b6dSopenharmony_ci void* user_data_ = nullptr; 32433eb0b6dSopenharmony_ci void (*done_cb_)(void*) = nullptr; 32533eb0b6dSopenharmony_ci void* done_data_ = nullptr; 32633eb0b6dSopenharmony_ci}; 32733eb0b6dSopenharmony_ci 32833eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_add_async_cleanup_hook( 32933eb0b6dSopenharmony_ci napi_env env, napi_async_cleanup_hook hook, void* arg, napi_async_cleanup_hook_handle* remove_handle) 33033eb0b6dSopenharmony_ci{ 33133eb0b6dSopenharmony_ci CHECK_ENV(env); 33233eb0b6dSopenharmony_ci CHECK_ARG(env, hook); 33333eb0b6dSopenharmony_ci CROSS_THREAD_CHECK(env); 33433eb0b6dSopenharmony_ci 33533eb0b6dSopenharmony_ci napi_async_cleanup_hook_handle__* handle = new napi_async_cleanup_hook_handle__(env, hook, arg); 33633eb0b6dSopenharmony_ci 33733eb0b6dSopenharmony_ci if (remove_handle != nullptr) 33833eb0b6dSopenharmony_ci *remove_handle = handle; 33933eb0b6dSopenharmony_ci 34033eb0b6dSopenharmony_ci return napi_clear_last_error(env); 34133eb0b6dSopenharmony_ci} 34233eb0b6dSopenharmony_ci 34333eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_remove_async_cleanup_hook(napi_async_cleanup_hook_handle remove_handle) 34433eb0b6dSopenharmony_ci{ 34533eb0b6dSopenharmony_ci if (remove_handle == nullptr) { 34633eb0b6dSopenharmony_ci return napi_invalid_arg; 34733eb0b6dSopenharmony_ci } 34833eb0b6dSopenharmony_ci 34933eb0b6dSopenharmony_ci delete remove_handle; 35033eb0b6dSopenharmony_ci return napi_ok; 35133eb0b6dSopenharmony_ci} 35233eb0b6dSopenharmony_ci 35333eb0b6dSopenharmony_ci// Methods to manager threadsafe 35433eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_create_threadsafe_function(napi_env env, napi_value func, napi_value async_resource, 35533eb0b6dSopenharmony_ci napi_value async_resource_name, size_t max_queue_size, size_t initial_thread_count, void* thread_finalize_data, 35633eb0b6dSopenharmony_ci napi_finalize thread_finalize_cb, void* context, napi_threadsafe_function_call_js call_js_cb, 35733eb0b6dSopenharmony_ci napi_threadsafe_function* result) 35833eb0b6dSopenharmony_ci{ 35933eb0b6dSopenharmony_ci CHECK_ENV(env); 36033eb0b6dSopenharmony_ci CHECK_ARG(env, async_resource_name); 36133eb0b6dSopenharmony_ci RETURN_STATUS_IF_FALSE(env, max_queue_size >= 0, napi_invalid_arg); 36233eb0b6dSopenharmony_ci RETURN_STATUS_IF_FALSE( 36333eb0b6dSopenharmony_ci env, initial_thread_count > 0 && initial_thread_count <= MAX_THREAD_SAFE_COUNT, napi_invalid_arg); 36433eb0b6dSopenharmony_ci CHECK_ARG(env, result); 36533eb0b6dSopenharmony_ci if (func == nullptr) { 36633eb0b6dSopenharmony_ci CHECK_ARG(env, call_js_cb); 36733eb0b6dSopenharmony_ci } 36833eb0b6dSopenharmony_ci 36933eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 37033eb0b6dSopenharmony_ci auto finalizeCallback = reinterpret_cast<NativeFinalize>(thread_finalize_cb); 37133eb0b6dSopenharmony_ci auto callJsCallback = reinterpret_cast<NativeThreadSafeFunctionCallJs>(call_js_cb); 37233eb0b6dSopenharmony_ci auto safeAsyncWork = engine->CreateSafeAsyncWork(func, async_resource, async_resource_name, max_queue_size, 37333eb0b6dSopenharmony_ci initial_thread_count, thread_finalize_data, finalizeCallback, context, callJsCallback); 37433eb0b6dSopenharmony_ci CHECK_ENV(safeAsyncWork); 37533eb0b6dSopenharmony_ci 37633eb0b6dSopenharmony_ci auto ret = safeAsyncWork->Init(); 37733eb0b6dSopenharmony_ci if (ret) { 37833eb0b6dSopenharmony_ci *result = reinterpret_cast<napi_threadsafe_function>(safeAsyncWork); 37933eb0b6dSopenharmony_ci } else { 38033eb0b6dSopenharmony_ci return napi_status::napi_generic_failure; 38133eb0b6dSopenharmony_ci } 38233eb0b6dSopenharmony_ci 38333eb0b6dSopenharmony_ci return napi_status::napi_ok; 38433eb0b6dSopenharmony_ci} 38533eb0b6dSopenharmony_ci 38633eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_call_threadsafe_function( 38733eb0b6dSopenharmony_ci napi_threadsafe_function func, void* data, napi_threadsafe_function_call_mode is_blocking) 38833eb0b6dSopenharmony_ci{ 38933eb0b6dSopenharmony_ci CHECK_ENV(func); 39033eb0b6dSopenharmony_ci 39133eb0b6dSopenharmony_ci auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func); 39233eb0b6dSopenharmony_ci auto callMode = static_cast<NativeThreadSafeFunctionCallMode>(is_blocking); 39333eb0b6dSopenharmony_ci 39433eb0b6dSopenharmony_ci napi_status status = napi_status::napi_ok; 39533eb0b6dSopenharmony_ci auto code = safeAsyncWork->Send(data, callMode); 39633eb0b6dSopenharmony_ci switch (code) { 39733eb0b6dSopenharmony_ci case SafeAsyncCode::SAFE_ASYNC_OK: 39833eb0b6dSopenharmony_ci status = napi_status::napi_ok; 39933eb0b6dSopenharmony_ci break; 40033eb0b6dSopenharmony_ci case SafeAsyncCode::SAFE_ASYNC_QUEUE_FULL: 40133eb0b6dSopenharmony_ci status = napi_status::napi_queue_full; 40233eb0b6dSopenharmony_ci break; 40333eb0b6dSopenharmony_ci case SafeAsyncCode::SAFE_ASYNC_INVALID_ARGS: 40433eb0b6dSopenharmony_ci status = napi_status::napi_invalid_arg; 40533eb0b6dSopenharmony_ci break; 40633eb0b6dSopenharmony_ci case SafeAsyncCode::SAFE_ASYNC_CLOSED: 40733eb0b6dSopenharmony_ci status = napi_status::napi_closing; 40833eb0b6dSopenharmony_ci break; 40933eb0b6dSopenharmony_ci case SafeAsyncCode::SAFE_ASYNC_FAILED: 41033eb0b6dSopenharmony_ci status = napi_status::napi_generic_failure; 41133eb0b6dSopenharmony_ci break; 41233eb0b6dSopenharmony_ci default: 41333eb0b6dSopenharmony_ci HILOG_FATAL("this branch is unreachable, code is %{public}d", code); 41433eb0b6dSopenharmony_ci break; 41533eb0b6dSopenharmony_ci } 41633eb0b6dSopenharmony_ci 41733eb0b6dSopenharmony_ci return status; 41833eb0b6dSopenharmony_ci} 41933eb0b6dSopenharmony_ci 42033eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_acquire_threadsafe_function(napi_threadsafe_function func) 42133eb0b6dSopenharmony_ci{ 42233eb0b6dSopenharmony_ci CHECK_ENV(func); 42333eb0b6dSopenharmony_ci 42433eb0b6dSopenharmony_ci auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func); 42533eb0b6dSopenharmony_ci 42633eb0b6dSopenharmony_ci auto ret = safeAsyncWork->Acquire(); 42733eb0b6dSopenharmony_ci if (ret != SafeAsyncCode::SAFE_ASYNC_OK) { 42833eb0b6dSopenharmony_ci return napi_status::napi_generic_failure; 42933eb0b6dSopenharmony_ci } 43033eb0b6dSopenharmony_ci 43133eb0b6dSopenharmony_ci return napi_status::napi_ok; 43233eb0b6dSopenharmony_ci} 43333eb0b6dSopenharmony_ci 43433eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_release_threadsafe_function( 43533eb0b6dSopenharmony_ci napi_threadsafe_function func, napi_threadsafe_function_release_mode mode) 43633eb0b6dSopenharmony_ci{ 43733eb0b6dSopenharmony_ci CHECK_ENV(func); 43833eb0b6dSopenharmony_ci 43933eb0b6dSopenharmony_ci auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func); 44033eb0b6dSopenharmony_ci auto releaseMode = static_cast<NativeThreadSafeFunctionReleaseMode>(mode); 44133eb0b6dSopenharmony_ci 44233eb0b6dSopenharmony_ci auto ret = safeAsyncWork->Release(releaseMode); 44333eb0b6dSopenharmony_ci if (ret != SafeAsyncCode::SAFE_ASYNC_OK) { 44433eb0b6dSopenharmony_ci return napi_status::napi_generic_failure; 44533eb0b6dSopenharmony_ci } 44633eb0b6dSopenharmony_ci 44733eb0b6dSopenharmony_ci return napi_status::napi_ok; 44833eb0b6dSopenharmony_ci} 44933eb0b6dSopenharmony_ci 45033eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_get_threadsafe_function_context(napi_threadsafe_function func, void** result) 45133eb0b6dSopenharmony_ci{ 45233eb0b6dSopenharmony_ci CHECK_ENV(func); 45333eb0b6dSopenharmony_ci CHECK_ENV(result); 45433eb0b6dSopenharmony_ci 45533eb0b6dSopenharmony_ci auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func); 45633eb0b6dSopenharmony_ci *result = safeAsyncWork->GetContext(); 45733eb0b6dSopenharmony_ci 45833eb0b6dSopenharmony_ci return napi_status::napi_ok; 45933eb0b6dSopenharmony_ci} 46033eb0b6dSopenharmony_ci 46133eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func) 46233eb0b6dSopenharmony_ci{ 46333eb0b6dSopenharmony_ci CHECK_ENV(env); 46433eb0b6dSopenharmony_ci CHECK_ARG(env, func); 46533eb0b6dSopenharmony_ci 46633eb0b6dSopenharmony_ci auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func); 46733eb0b6dSopenharmony_ci auto ret = safeAsyncWork->Ref(); 46833eb0b6dSopenharmony_ci if (!ret) { 46933eb0b6dSopenharmony_ci return napi_status::napi_generic_failure; 47033eb0b6dSopenharmony_ci } 47133eb0b6dSopenharmony_ci 47233eb0b6dSopenharmony_ci return napi_status::napi_ok; 47333eb0b6dSopenharmony_ci} 47433eb0b6dSopenharmony_ci 47533eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_unref_threadsafe_function(napi_env env, napi_threadsafe_function func) 47633eb0b6dSopenharmony_ci{ 47733eb0b6dSopenharmony_ci CHECK_ENV(env); 47833eb0b6dSopenharmony_ci CHECK_ARG(env, func); 47933eb0b6dSopenharmony_ci 48033eb0b6dSopenharmony_ci auto safeAsyncWork = reinterpret_cast<NativeSafeAsyncWork*>(func); 48133eb0b6dSopenharmony_ci auto ret = safeAsyncWork->Unref(); 48233eb0b6dSopenharmony_ci if (!ret) { 48333eb0b6dSopenharmony_ci return napi_status::napi_generic_failure; 48433eb0b6dSopenharmony_ci } 48533eb0b6dSopenharmony_ci 48633eb0b6dSopenharmony_ci return napi_status::napi_ok; 48733eb0b6dSopenharmony_ci} 48833eb0b6dSopenharmony_ci 48933eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_async_init( 49033eb0b6dSopenharmony_ci napi_env env, napi_value async_resource, napi_value async_resource_name, napi_async_context* result) 49133eb0b6dSopenharmony_ci{ 49233eb0b6dSopenharmony_ci CHECK_ENV(env); 49333eb0b6dSopenharmony_ci CHECK_ARG(env, async_resource_name); 49433eb0b6dSopenharmony_ci CHECK_ARG(env, result); 49533eb0b6dSopenharmony_ci 49633eb0b6dSopenharmony_ci auto ecmaVm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm(); 49733eb0b6dSopenharmony_ci panda::Local<panda::ObjectRef> resource; 49833eb0b6dSopenharmony_ci bool isExternalResource; 49933eb0b6dSopenharmony_ci if (async_resource != nullptr) { 50033eb0b6dSopenharmony_ci auto nativeValue = LocalValueFromJsValue(async_resource); 50133eb0b6dSopenharmony_ci resource = nativeValue->ToObject(ecmaVm); 50233eb0b6dSopenharmony_ci isExternalResource = true; 50333eb0b6dSopenharmony_ci } else { 50433eb0b6dSopenharmony_ci resource = panda::ObjectRef::New(ecmaVm); 50533eb0b6dSopenharmony_ci isExternalResource = false; 50633eb0b6dSopenharmony_ci } 50733eb0b6dSopenharmony_ci 50833eb0b6dSopenharmony_ci auto nativeValue = LocalValueFromJsValue(async_resource_name); 50933eb0b6dSopenharmony_ci auto resourceName = nativeValue->ToString(ecmaVm); 51033eb0b6dSopenharmony_ci 51133eb0b6dSopenharmony_ci auto asyncContext = new NativeAsyncHookContext(reinterpret_cast<NativeEngine*>(env), 51233eb0b6dSopenharmony_ci resource, 51333eb0b6dSopenharmony_ci resourceName, 51433eb0b6dSopenharmony_ci isExternalResource); 51533eb0b6dSopenharmony_ci 51633eb0b6dSopenharmony_ci *result = reinterpret_cast<napi_async_context>(asyncContext); 51733eb0b6dSopenharmony_ci 51833eb0b6dSopenharmony_ci return napi_clear_last_error(env); 51933eb0b6dSopenharmony_ci} 52033eb0b6dSopenharmony_ci 52133eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_async_destroy(napi_env env, napi_async_context async_context) 52233eb0b6dSopenharmony_ci{ 52333eb0b6dSopenharmony_ci CHECK_ENV(env); 52433eb0b6dSopenharmony_ci CHECK_ARG(env, async_context); 52533eb0b6dSopenharmony_ci 52633eb0b6dSopenharmony_ci NativeAsyncHookContext* nativeAsyncContext = reinterpret_cast<NativeAsyncHookContext*>(async_context); 52733eb0b6dSopenharmony_ci 52833eb0b6dSopenharmony_ci delete nativeAsyncContext; 52933eb0b6dSopenharmony_ci 53033eb0b6dSopenharmony_ci return napi_clear_last_error(env); 53133eb0b6dSopenharmony_ci} 53233eb0b6dSopenharmony_ci 53333eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_open_callback_scope( 53433eb0b6dSopenharmony_ci napi_env env, napi_value, napi_async_context async_context_handle, napi_callback_scope* result) 53533eb0b6dSopenharmony_ci{ 53633eb0b6dSopenharmony_ci CHECK_ENV(env); 53733eb0b6dSopenharmony_ci CHECK_ARG(env, result); 53833eb0b6dSopenharmony_ci 53933eb0b6dSopenharmony_ci NativeAsyncHookContext* nodeAsyncContext = reinterpret_cast<NativeAsyncHookContext*>(async_context_handle); 54033eb0b6dSopenharmony_ci 54133eb0b6dSopenharmony_ci *result = reinterpret_cast<napi_callback_scope>(nodeAsyncContext->OpenCallbackScope()); 54233eb0b6dSopenharmony_ci 54333eb0b6dSopenharmony_ci return napi_clear_last_error(env); 54433eb0b6dSopenharmony_ci} 54533eb0b6dSopenharmony_ci 54633eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_close_callback_scope(napi_env env, napi_callback_scope scope) 54733eb0b6dSopenharmony_ci{ 54833eb0b6dSopenharmony_ci CHECK_ENV(env); 54933eb0b6dSopenharmony_ci CHECK_ARG(env, scope); 55033eb0b6dSopenharmony_ci 55133eb0b6dSopenharmony_ci auto ret = NativeAsyncHookContext::CloseCallbackScope(reinterpret_cast<NativeEngine*>(env), 55233eb0b6dSopenharmony_ci reinterpret_cast<NativeCallbackScope*>(scope)); 55333eb0b6dSopenharmony_ci if (ret == CALLBACK_SCOPE_MISMATCH) { 55433eb0b6dSopenharmony_ci return napi_callback_scope_mismatch; 55533eb0b6dSopenharmony_ci } else if (ret != CALLBACK_SCOPE_OK) { 55633eb0b6dSopenharmony_ci return napi_invalid_arg; 55733eb0b6dSopenharmony_ci } 55833eb0b6dSopenharmony_ci 55933eb0b6dSopenharmony_ci return napi_clear_last_error(env); 56033eb0b6dSopenharmony_ci} 56133eb0b6dSopenharmony_ci 56233eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_set_instance_data( 56333eb0b6dSopenharmony_ci napi_env env, void* data, napi_finalize finalize_cb, void* finalize_hint) 56433eb0b6dSopenharmony_ci{ 56533eb0b6dSopenharmony_ci CHECK_ENV(env); 56633eb0b6dSopenharmony_ci CROSS_THREAD_CHECK(env); 56733eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 56833eb0b6dSopenharmony_ci auto callback = reinterpret_cast<NativeFinalize>(finalize_cb); 56933eb0b6dSopenharmony_ci engine->SetInstanceData(data, callback, finalize_hint); 57033eb0b6dSopenharmony_ci return napi_clear_last_error(env); 57133eb0b6dSopenharmony_ci} 57233eb0b6dSopenharmony_ci 57333eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_get_instance_data(napi_env env, void** data) 57433eb0b6dSopenharmony_ci{ 57533eb0b6dSopenharmony_ci CHECK_ENV(env); 57633eb0b6dSopenharmony_ci CHECK_ARG(env, data); 57733eb0b6dSopenharmony_ci CROSS_THREAD_CHECK(env); 57833eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 57933eb0b6dSopenharmony_ci engine->GetInstanceData(data); 58033eb0b6dSopenharmony_ci return napi_clear_last_error(env); 58133eb0b6dSopenharmony_ci} 58233eb0b6dSopenharmony_ci 58333eb0b6dSopenharmony_ciNAPI_EXTERN napi_status node_api_get_module_file_name(napi_env env, const char** result) 58433eb0b6dSopenharmony_ci{ 58533eb0b6dSopenharmony_ci CHECK_ENV(env); 58633eb0b6dSopenharmony_ci CHECK_ARG(env, result); 58733eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 58833eb0b6dSopenharmony_ci *result = engine->GetModuleFileName(); 58933eb0b6dSopenharmony_ci HILOG_INFO("%{public}s, napi called fileName : %{public}s", __func__, *result); 59033eb0b6dSopenharmony_ci return napi_clear_last_error(env); 59133eb0b6dSopenharmony_ci} 59233eb0b6dSopenharmony_ci 59333eb0b6dSopenharmony_ciNAPI_EXTERN napi_status napi_make_callback(napi_env env, 59433eb0b6dSopenharmony_ci napi_async_context async_context, 59533eb0b6dSopenharmony_ci napi_value recv, 59633eb0b6dSopenharmony_ci napi_value func, 59733eb0b6dSopenharmony_ci size_t argc, 59833eb0b6dSopenharmony_ci const napi_value* argv, 59933eb0b6dSopenharmony_ci napi_value* result) 60033eb0b6dSopenharmony_ci{ 60133eb0b6dSopenharmony_ci NAPI_PREAMBLE(env); 60233eb0b6dSopenharmony_ci CHECK_ARG(env, func); 60333eb0b6dSopenharmony_ci CHECK_ARG(env, recv); 60433eb0b6dSopenharmony_ci if (argc > 0) { 60533eb0b6dSopenharmony_ci CHECK_ARG(env, argv); 60633eb0b6dSopenharmony_ci } 60733eb0b6dSopenharmony_ci auto engine = reinterpret_cast<NativeEngine*>(env); 60833eb0b6dSopenharmony_ci auto vm = engine->GetEcmaVm(); 60933eb0b6dSopenharmony_ci RETURN_STATUS_IF_FALSE(env, reinterpret_cast<panda::JSValueRef *>(recv)->IsObject(vm), napi_object_expected); 61033eb0b6dSopenharmony_ci RETURN_STATUS_IF_FALSE(env, reinterpret_cast<panda::JSValueRef *>(func)->IsFunction(vm), napi_function_expected); 61133eb0b6dSopenharmony_ci panda::JSValueRef* Obj = reinterpret_cast<panda::JSValueRef *>(recv); 61233eb0b6dSopenharmony_ci panda::FunctionRef* funRef = reinterpret_cast<panda::FunctionRef *>(func); 61333eb0b6dSopenharmony_ci panda::JSValueRef* callBackRst; 61433eb0b6dSopenharmony_ci if (async_context == nullptr) { 61533eb0b6dSopenharmony_ci callBackRst = MakeCallback(engine, funRef, Obj, 61633eb0b6dSopenharmony_ci argc, reinterpret_cast<panda::JSValueRef* const*>(argv), nullptr); 61733eb0b6dSopenharmony_ci } else { 61833eb0b6dSopenharmony_ci NativeAsyncHookContext* nativeAsyncContext = reinterpret_cast<NativeAsyncHookContext*>(async_context); 61933eb0b6dSopenharmony_ci callBackRst = nativeAsyncContext->MakeCallback(funRef, Obj, 62033eb0b6dSopenharmony_ci reinterpret_cast<panda::JSValueRef* const*>(argv), argc); 62133eb0b6dSopenharmony_ci } 62233eb0b6dSopenharmony_ci if (tryCatch.HasCaught()) { 62333eb0b6dSopenharmony_ci HILOG_ERROR("print exception info: "); 62433eb0b6dSopenharmony_ci panda::JSNApi::PrintExceptionInfo(vm); 62533eb0b6dSopenharmony_ci return napi_set_last_error(env, napi_pending_exception); 62633eb0b6dSopenharmony_ci } 62733eb0b6dSopenharmony_ci if (result) { 62833eb0b6dSopenharmony_ci *result = reinterpret_cast<napi_value>(callBackRst); 62933eb0b6dSopenharmony_ci } 63033eb0b6dSopenharmony_ci return GET_RETURN_STATUS(env); 63133eb0b6dSopenharmony_ci} 632