Skip to content
Draft
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/host/android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ add_library(node-api-host SHARED
../cpp/RuntimeNodeApi.hpp
../cpp/RuntimeNodeApiAsync.cpp
../cpp/RuntimeNodeApiAsync.hpp
../cpp/ThreadsafeFunction.cpp
../cpp/ThreadsafeFunction.hpp
)

target_include_directories(node-api-host PRIVATE
Expand Down
83 changes: 83 additions & 0 deletions packages/host/cpp/RuntimeNodeApiAsync.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "RuntimeNodeApiAsync.hpp"
#include <ReactCommon/CallInvoker.h>
#include "Logger.hpp"
#include "ThreadsafeFunction.hpp"

struct AsyncJob {
using IdType = uint64_t;
Expand Down Expand Up @@ -187,4 +188,86 @@ napi_status napi_cancel_async_work(
job->state = AsyncJob::State::Cancelled;
return napi_ok;
}

Copy link
Collaborator

@kraenhansen kraenhansen Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if the name of this file needs an update now that it's not "just async work related"? Or of this should go into as separate file? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was also thinking about that, finally I decided to put it there since the threadsafe functions in Node-API are called asynchronously and other implementation often group them together. But I am open to change that I move it to the separate file.

Copy link
Collaborator

@kraenhansen kraenhansen Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong preference either way 👍
If it's a conscious choice, I'm all for that. Just didn't seem that related to me.

napi_status napi_create_threadsafe_function(napi_env env,
napi_value func,
napi_value async_resource,
napi_value async_resource_name,
size_t max_queue_size,
size_t initial_thread_count,
void* thread_finalize_data,
napi_finalize thread_finalize_cb,
void* context,
napi_threadsafe_function_call_js call_js_cb,
napi_threadsafe_function* result) {
const auto function = ThreadSafeFunction::create(getCallInvoker(env),
env,
func,
async_resource,
async_resource_name,
max_queue_size,
initial_thread_count,
thread_finalize_data,
thread_finalize_cb,
context,
call_js_cb);
*result = function->getHandle();
return napi_ok;
}

napi_status napi_get_threadsafe_function_context(
napi_threadsafe_function func, void** result) {
const auto function = ThreadSafeFunction::get(func);
if (!function) {
return napi_invalid_arg;
}
return function->getContext(result);
}

napi_status napi_call_threadsafe_function(napi_threadsafe_function func,
void* data,
napi_threadsafe_function_call_mode is_blocking) {
const auto function = ThreadSafeFunction::get(func);
if (!function) {
return napi_invalid_arg;
}
return function->call(data, is_blocking);
}

napi_status napi_acquire_threadsafe_function(napi_threadsafe_function func) {
const auto function = ThreadSafeFunction::get(func);
if (!function) {
return napi_invalid_arg;
}
return function->acquire();
}

napi_status napi_release_threadsafe_function(
napi_threadsafe_function func, napi_threadsafe_function_release_mode mode) {
const auto function = ThreadSafeFunction::get(func);
if (!function) {
return napi_invalid_arg;
}
return function->release(mode);
}

napi_status napi_unref_threadsafe_function(
node_api_basic_env env, napi_threadsafe_function func) {
const auto function = ThreadSafeFunction::get(func);
if (!function) {
return napi_invalid_arg;
}
// RN has no libuv loop to unref; we only update internal state for parity.
return function->unref();
}

napi_status napi_ref_threadsafe_function(
node_api_basic_env env, napi_threadsafe_function func) {
const auto function = ThreadSafeFunction::get(func);
if (!function) {
return napi_invalid_arg;
}
// RN has no libuv loop to ref; we only update internal state for parity.
return function->ref();
}
} // namespace callstack::nodeapihost
30 changes: 30 additions & 0 deletions packages/host/cpp/RuntimeNodeApiAsync.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,34 @@ napi_status napi_delete_async_work(

napi_status napi_cancel_async_work(
node_api_basic_env env, napi_async_work work);

napi_status napi_create_threadsafe_function(napi_env env,
napi_value func,
napi_value async_resource,
napi_value async_resource_name,
size_t max_queue_size,
size_t initial_thread_count,
void* thread_finalize_data,
napi_finalize thread_finalize_cb,
void* context,
napi_threadsafe_function_call_js call_js_cb,
napi_threadsafe_function* result);

napi_status napi_get_threadsafe_function_context(
napi_threadsafe_function func, void** result);

napi_status napi_call_threadsafe_function(napi_threadsafe_function func,
void* data,
napi_threadsafe_function_call_mode is_blocking);

napi_status napi_acquire_threadsafe_function(napi_threadsafe_function func);

napi_status napi_release_threadsafe_function(
napi_threadsafe_function func, napi_threadsafe_function_release_mode mode);

napi_status napi_unref_threadsafe_function(
node_api_basic_env env, napi_threadsafe_function func);

napi_status napi_ref_threadsafe_function(
node_api_basic_env env, napi_threadsafe_function func);
} // namespace callstack::nodeapihost
Loading
Loading