summaryrefslogtreecommitdiff
path: root/cli/napi/node_api.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/napi/node_api.rs')
-rw-r--r--cli/napi/node_api.rs1004
1 files changed, 0 insertions, 1004 deletions
diff --git a/cli/napi/node_api.rs b/cli/napi/node_api.rs
deleted file mode 100644
index 2efb71c26..000000000
--- a/cli/napi/node_api.rs
+++ /dev/null
@@ -1,1004 +0,0 @@
-// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-
-#![deny(unsafe_op_in_unsafe_fn)]
-
-use super::util::get_array_buffer_ptr;
-use super::util::make_external_backing_store;
-use super::util::napi_clear_last_error;
-use super::util::napi_set_last_error;
-use super::util::SendPtr;
-use crate::check_arg;
-use crate::check_env;
-use deno_core::parking_lot::Condvar;
-use deno_core::parking_lot::Mutex;
-use deno_core::V8CrossThreadTaskSpawner;
-use deno_runtime::deno_napi::*;
-use napi_sym::napi_sym;
-use std::sync::atomic::AtomicBool;
-use std::sync::atomic::AtomicU8;
-use std::sync::atomic::AtomicUsize;
-use std::sync::atomic::Ordering;
-use std::sync::Arc;
-
-#[napi_sym]
-fn napi_module_register(module: *const NapiModule) -> napi_status {
- MODULE_TO_REGISTER.with(|cell| {
- let mut slot = cell.borrow_mut();
- let prev = slot.replace(module);
- assert!(prev.is_none());
- });
- napi_ok
-}
-
-#[napi_sym]
-fn napi_add_env_cleanup_hook(
- env: *mut Env,
- fun: Option<napi_cleanup_hook>,
- arg: *mut c_void,
-) -> napi_status {
- let env = check_env!(env);
- check_arg!(env, fun);
-
- let fun = fun.unwrap();
-
- env.add_cleanup_hook(fun, arg);
-
- napi_ok
-}
-
-#[napi_sym]
-fn napi_remove_env_cleanup_hook(
- env: *mut Env,
- fun: Option<napi_cleanup_hook>,
- arg: *mut c_void,
-) -> napi_status {
- let env = check_env!(env);
- check_arg!(env, fun);
-
- let fun = fun.unwrap();
-
- env.remove_cleanup_hook(fun, arg);
-
- napi_ok
-}
-
-struct AsyncCleanupHandle {
- env: *mut Env,
- hook: napi_async_cleanup_hook,
- data: *mut c_void,
-}
-
-unsafe extern "C" fn async_cleanup_handler(arg: *mut c_void) {
- unsafe {
- let handle = Box::<AsyncCleanupHandle>::from_raw(arg as _);
- (handle.hook)(arg, handle.data);
- }
-}
-
-#[napi_sym]
-fn napi_add_async_cleanup_hook(
- env: *mut Env,
- hook: Option<napi_async_cleanup_hook>,
- arg: *mut c_void,
- remove_handle: *mut napi_async_cleanup_hook_handle,
-) -> napi_status {
- let env = check_env!(env);
- check_arg!(env, hook);
-
- let hook = hook.unwrap();
-
- let handle = Box::into_raw(Box::new(AsyncCleanupHandle {
- env,
- hook,
- data: arg,
- })) as *mut c_void;
-
- env.add_cleanup_hook(async_cleanup_handler, handle);
-
- if !remove_handle.is_null() {
- unsafe {
- *remove_handle = handle;
- }
- }
-
- napi_clear_last_error(env)
-}
-
-#[napi_sym]
-fn napi_remove_async_cleanup_hook(
- remove_handle: napi_async_cleanup_hook_handle,
-) -> napi_status {
- if remove_handle.is_null() {
- return napi_invalid_arg;
- }
-
- let handle =
- unsafe { Box::<AsyncCleanupHandle>::from_raw(remove_handle as _) };
-
- let env = unsafe { &mut *handle.env };
-
- env.remove_cleanup_hook(async_cleanup_handler, remove_handle);
-
- napi_ok
-}
-
-#[napi_sym]
-fn napi_fatal_exception(env: &mut Env, err: napi_value) -> napi_status {
- check_arg!(env, err);
-
- let report_error = v8::Local::new(&mut env.scope(), &env.report_error);
-
- let this = v8::undefined(&mut env.scope());
- if report_error
- .call(&mut env.scope(), this.into(), &[err.unwrap()])
- .is_none()
- {
- return napi_generic_failure;
- }
-
- napi_ok
-}
-
-#[napi_sym]
-#[allow(clippy::print_stderr)]
-fn napi_fatal_error(
- location: *const c_char,
- location_len: usize,
- message: *const c_char,
- message_len: usize,
-) -> napi_status {
- let location = if location.is_null() {
- None
- } else {
- unsafe {
- Some(if location_len == NAPI_AUTO_LENGTH {
- std::ffi::CStr::from_ptr(location).to_str().unwrap()
- } else {
- let slice = std::slice::from_raw_parts(
- location as *const u8,
- location_len as usize,
- );
- std::str::from_utf8(slice).unwrap()
- })
- }
- };
-
- let message = if message_len == NAPI_AUTO_LENGTH {
- unsafe { std::ffi::CStr::from_ptr(message).to_str().unwrap() }
- } else {
- let slice = unsafe {
- std::slice::from_raw_parts(message as *const u8, message_len as usize)
- };
- std::str::from_utf8(slice).unwrap()
- };
-
- if let Some(location) = location {
- eprintln!("NODE API FATAL ERROR: {} {}", location, message);
- } else {
- eprintln!("NODE API FATAL ERROR: {}", message);
- }
-
- std::process::abort();
-}
-
-#[napi_sym]
-fn napi_open_callback_scope(
- env: *mut Env,
- _resource_object: napi_value,
- _context: napi_value,
- result: *mut napi_callback_scope,
-) -> napi_status {
- let env = check_env!(env);
- check_arg!(env, result);
-
- // we open scope automatically when it's needed
- unsafe {
- *result = std::ptr::null_mut();
- }
-
- napi_clear_last_error(env)
-}
-
-#[napi_sym]
-fn napi_close_callback_scope(
- env: *mut Env,
- scope: napi_callback_scope,
-) -> napi_status {
- let env = check_env!(env);
- // we close scope automatically when it's needed
- assert!(scope.is_null());
- napi_clear_last_error(env)
-}
-
-// NOTE: we don't support "async_hooks::AsyncContext" so these APIs are noops.
-#[napi_sym]
-fn napi_async_init(
- env: *mut Env,
- _async_resource: napi_value,
- _async_resource_name: napi_value,
- result: *mut napi_async_context,
-) -> napi_status {
- let env = check_env!(env);
- unsafe {
- *result = ptr::null_mut();
- }
- napi_clear_last_error(env)
-}
-
-#[napi_sym]
-fn napi_async_destroy(
- env: *mut Env,
- async_context: napi_async_context,
-) -> napi_status {
- let env = check_env!(env);
- assert!(async_context.is_null());
- napi_clear_last_error(env)
-}
-
-#[napi_sym]
-fn napi_make_callback<'s>(
- env: &'s mut Env,
- _async_context: napi_async_context,
- recv: napi_value,
- func: napi_value,
- argc: usize,
- argv: *const napi_value<'s>,
- result: *mut napi_value<'s>,
-) -> napi_status {
- check_arg!(env, recv);
- if argc > 0 {
- check_arg!(env, argv);
- }
-
- let Some(recv) = recv.and_then(|v| v.to_object(&mut env.scope())) else {
- return napi_object_expected;
- };
-
- let Some(func) =
- func.and_then(|v| v8::Local::<v8::Function>::try_from(v).ok())
- else {
- return napi_function_expected;
- };
-
- let args = if argc > 0 {
- unsafe {
- std::slice::from_raw_parts(argv as *mut v8::Local<v8::Value>, argc)
- }
- } else {
- &[]
- };
-
- // TODO: async_context
-
- let Some(v) = func.call(&mut env.scope(), recv.into(), args) else {
- return napi_generic_failure;
- };
-
- unsafe {
- *result = v.into();
- }
-
- napi_ok
-}
-
-#[napi_sym]
-fn napi_create_buffer<'s>(
- env: &'s mut Env,
- length: usize,
- data: *mut *mut c_void,
- result: *mut napi_value<'s>,
-) -> napi_status {
- check_arg!(env, result);
-
- let ab = v8::ArrayBuffer::new(&mut env.scope(), length);
-
- let buffer_constructor =
- v8::Local::new(&mut env.scope(), &env.buffer_constructor);
- let Some(buffer) =
- buffer_constructor.new_instance(&mut env.scope(), &[ab.into()])
- else {
- return napi_generic_failure;
- };
-
- if !data.is_null() {
- unsafe {
- *data = get_array_buffer_ptr(ab);
- }
- }
-
- unsafe {
- *result = buffer.into();
- }
-
- napi_ok
-}
-
-#[napi_sym]
-fn napi_create_external_buffer<'s>(
- env: &'s mut Env,
- length: usize,
- data: *mut c_void,
- finalize_cb: napi_finalize,
- finalize_hint: *mut c_void,
- result: *mut napi_value<'s>,
-) -> napi_status {
- check_arg!(env, result);
-
- let store = make_external_backing_store(
- env,
- data,
- length,
- ptr::null_mut(),
- finalize_cb,
- finalize_hint,
- );
-
- let ab =
- v8::ArrayBuffer::with_backing_store(&mut env.scope(), &store.make_shared());
-
- let buffer_constructor =
- v8::Local::new(&mut env.scope(), &env.buffer_constructor);
- let Some(buffer) =
- buffer_constructor.new_instance(&mut env.scope(), &[ab.into()])
- else {
- return napi_generic_failure;
- };
-
- unsafe {
- *result = buffer.into();
- }
-
- napi_ok
-}
-
-#[napi_sym]
-fn napi_create_buffer_copy<'s>(
- env: &'s mut Env,
- length: usize,
- data: *mut c_void,
- result_data: *mut *mut c_void,
- result: *mut napi_value<'s>,
-) -> napi_status {
- check_arg!(env, result);
-
- let ab = v8::ArrayBuffer::new(&mut env.scope(), length);
-
- let buffer_constructor =
- v8::Local::new(&mut env.scope(), &env.buffer_constructor);
- let Some(buffer) =
- buffer_constructor.new_instance(&mut env.scope(), &[ab.into()])
- else {
- return napi_generic_failure;
- };
-
- let ptr = get_array_buffer_ptr(ab);
- unsafe {
- std::ptr::copy(data, ptr, length);
- }
-
- if !result_data.is_null() {
- unsafe {
- *result_data = ptr;
- }
- }
-
- unsafe {
- *result = buffer.into();
- }
-
- napi_ok
-}
-
-#[napi_sym]
-fn napi_is_buffer(
- env: *mut Env,
- value: napi_value,
- result: *mut bool,
-) -> napi_status {
- let env = check_env!(env);
- check_arg!(env, value);
- check_arg!(env, result);
-
- let buffer_constructor =
- v8::Local::new(&mut env.scope(), &env.buffer_constructor);
-
- let Some(is_buffer) = value
- .unwrap()
- .instance_of(&mut env.scope(), buffer_constructor.into())
- else {
- return napi_set_last_error(env, napi_generic_failure);
- };
-
- unsafe {
- *result = is_buffer;
- }
-
- napi_clear_last_error(env)
-}
-
-#[napi_sym]
-fn napi_get_buffer_info(
- env: *mut Env,
- value: napi_value,
- data: *mut *mut c_void,
- length: *mut usize,
-) -> napi_status {
- let env = check_env!(env);
- check_arg!(env, value);
-
- // NB: Any TypedArray instance seems to be accepted by this function
- // in Node.js.
- let Some(ta) =
- value.and_then(|v| v8::Local::<v8::TypedArray>::try_from(v).ok())
- else {
- return napi_set_last_error(env, napi_invalid_arg);
- };
-
- if !data.is_null() {
- unsafe {
- *data = ta.data();
- }
- }
-
- if !length.is_null() {
- unsafe {
- *length = ta.byte_length();
- }
- }
-
- napi_clear_last_error(env)
-}
-
-#[napi_sym]
-fn napi_get_node_version(
- env: *mut Env,
- result: *mut *const napi_node_version,
-) -> napi_status {
- let env = check_env!(env);
- check_arg!(env, result);
-
- const NODE_VERSION: napi_node_version = napi_node_version {
- major: 20,
- minor: 11,
- patch: 1,
- release: c"Deno".as_ptr(),
- };
-
- unsafe {
- *result = &NODE_VERSION as *const napi_node_version;
- }
-
- napi_clear_last_error(env)
-}
-
-struct AsyncWork {
- state: AtomicU8,
- env: *mut Env,
- _async_resource: v8::Global<v8::Object>,
- _async_resource_name: String,
- execute: napi_async_execute_callback,
- complete: Option<napi_async_complete_callback>,
- data: *mut c_void,
-}
-
-impl AsyncWork {
- const IDLE: u8 = 0;
- const QUEUED: u8 = 1;
- const RUNNING: u8 = 2;
-}
-
-#[napi_sym]
-fn napi_create_async_work(
- env: *mut Env,
- async_resource: napi_value,
- async_resource_name: napi_value,
- execute: Option<napi_async_execute_callback>,
- complete: Option<napi_async_complete_callback>,
- data: *mut c_void,
- result: *mut napi_async_work,
-) -> napi_status {
- let env_ptr = env;
- let env = check_env!(env);
- check_arg!(env, execute);
- check_arg!(env, result);
-
- let resource = if let Some(v) = *async_resource {
- let Some(resource) = v.to_object(&mut env.scope()) else {
- return napi_set_last_error(env, napi_object_expected);
- };
- resource
- } else {
- v8::Object::new(&mut env.scope())
- };
-
- let Some(resource_name) =
- async_resource_name.and_then(|v| v.to_string(&mut env.scope()))
- else {
- return napi_set_last_error(env, napi_string_expected);
- };
-
- let resource_name = resource_name.to_rust_string_lossy(&mut env.scope());
-
- let work = Box::new(AsyncWork {
- state: AtomicU8::new(AsyncWork::IDLE),
- env: env_ptr,
- _async_resource: v8::Global::new(&mut env.scope(), resource),
- _async_resource_name: resource_name,
- execute: execute.unwrap(),
- complete,
- data,
- });
-
- unsafe {
- *result = Box::into_raw(work) as _;
- }
-
- napi_clear_last_error(env)
-}
-
-#[napi_sym]
-fn napi_delete_async_work(env: *mut Env, work: napi_async_work) -> napi_status {
- let env = check_env!(env);
- check_arg!(env, work);
-
- drop(unsafe { Box::<AsyncWork>::from_raw(work as _) });
-
- napi_clear_last_error(env)
-}
-
-#[napi_sym]
-fn napi_get_uv_event_loop(
- env_ptr: *mut Env,
- uv_loop: *mut *mut (),
-) -> napi_status {
- let env = check_env!(env_ptr);
- check_arg!(env, uv_loop);
- unsafe {
- *uv_loop = env_ptr.cast();
- }
- 0
-}
-
-#[napi_sym]
-fn napi_queue_async_work(env: *mut Env, work: napi_async_work) -> napi_status {
- let env = check_env!(env);
- check_arg!(env, work);
-
- let work = unsafe { &*(work as *mut AsyncWork) };
-
- let result =
- work
- .state
- .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |state| {
- // allow queue if idle or if running, but not if already queued.
- if state == AsyncWork::IDLE || state == AsyncWork::RUNNING {
- Some(AsyncWork::QUEUED)
- } else {
- None
- }
- });
-
- if result.is_err() {
- return napi_clear_last_error(env);
- }
-
- let work = SendPtr(work);
-
- env.add_async_work(move || {
- let work = work.take();
- let work = unsafe { &*work };
-
- let state = work.state.compare_exchange(
- AsyncWork::QUEUED,
- AsyncWork::RUNNING,
- Ordering::SeqCst,
- Ordering::SeqCst,
- );
-
- if state.is_ok() {
- unsafe {
- (work.execute)(work.env as _, work.data);
- }
-
- // reset back to idle if its still marked as running
- let _ = work.state.compare_exchange(
- AsyncWork::RUNNING,
- AsyncWork::IDLE,
- Ordering::SeqCst,
- Ordering::Relaxed,
- );
- }
-
- if let Some(complete) = work.complete {
- let status = if state.is_ok() {
- napi_ok
- } else if state == Err(AsyncWork::IDLE) {
- napi_cancelled
- } else {
- napi_generic_failure
- };
-
- unsafe {
- complete(work.env as _, status, work.data);
- }
- }
-
- // `complete` probably deletes this `work`, so don't use it here.
- });
-
- napi_clear_last_error(env)
-}
-
-#[napi_sym]
-fn napi_cancel_async_work(env: *mut Env, work: napi_async_work) -> napi_status {
- let env = check_env!(env);
- check_arg!(env, work);
-
- let work = unsafe { &*(work as *mut AsyncWork) };
-
- let _ = work.state.compare_exchange(
- AsyncWork::QUEUED,
- AsyncWork::IDLE,
- Ordering::SeqCst,
- Ordering::Relaxed,
- );
-
- napi_clear_last_error(env)
-}
-
-extern "C" fn default_call_js_cb(
- env: napi_env,
- js_callback: napi_value,
- _context: *mut c_void,
- _data: *mut c_void,
-) {
- if let Some(js_callback) = *js_callback {
- if let Ok(js_callback) = v8::Local::<v8::Function>::try_from(js_callback) {
- let env = unsafe { &mut *(env as *mut Env) };
- let scope = &mut env.scope();
- let recv = v8::undefined(scope);
- js_callback.call(scope, recv.into(), &[]);
- }
- }
-}
-
-struct TsFn {
- env: *mut Env,
- func: Option<v8::Global<v8::Function>>,
- max_queue_size: usize,
- queue_size: Mutex<usize>,
- queue_cond: Condvar,
- thread_count: AtomicUsize,
- thread_finalize_data: *mut c_void,
- thread_finalize_cb: Option<napi_finalize>,
- context: *mut c_void,
- call_js_cb: napi_threadsafe_function_call_js,
- _resource: v8::Global<v8::Object>,
- _resource_name: String,
- is_closing: AtomicBool,
- is_closed: Arc<AtomicBool>,
- sender: V8CrossThreadTaskSpawner,
- is_ref: AtomicBool,
-}
-
-impl Drop for TsFn {
- fn drop(&mut self) {
- assert!(self
- .is_closed
- .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
- .is_ok());
-
- self.unref();
-
- if let Some(finalizer) = self.thread_finalize_cb {
- unsafe {
- (finalizer)(self.env as _, self.thread_finalize_data, ptr::null_mut());
- }
- }
- }
-}
-
-impl TsFn {
- pub fn acquire(&self) -> napi_status {
- if self.is_closing.load(Ordering::SeqCst) {
- return napi_closing;
- }
- self.thread_count.fetch_add(1, Ordering::Relaxed);
- napi_ok
- }
-
- pub fn release(
- tsfn: *mut TsFn,
- mode: napi_threadsafe_function_release_mode,
- ) -> napi_status {
- let tsfn = unsafe { &mut *tsfn };
-
- let result = tsfn.thread_count.fetch_update(
- Ordering::Relaxed,
- Ordering::Relaxed,
- |x| {
- if x == 0 {
- None
- } else {
- Some(x - 1)
- }
- },
- );
-
- if result.is_err() {
- return napi_invalid_arg;
- }
-
- if (result == Ok(1) || mode == napi_tsfn_abort)
- && tsfn
- .is_closing
- .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
- .is_ok()
- {
- tsfn.queue_cond.notify_all();
- let tsfnptr = SendPtr(tsfn);
- // drop must be queued in order to preserve ordering consistent
- // with Node.js and so that the finalizer runs on the main thread.
- tsfn.sender.spawn(move |_| {
- let tsfn = unsafe { Box::from_raw(tsfnptr.take() as *mut TsFn) };
- drop(tsfn);
- });
- }
-
- napi_ok
- }
-
- pub fn ref_(&self) -> napi_status {
- if self
- .is_ref
- .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
- .is_ok()
- {
- let env = unsafe { &mut *self.env };
- env.threadsafe_function_ref();
- }
- napi_ok
- }
-
- pub fn unref(&self) -> napi_status {
- if self
- .is_ref
- .compare_exchange(true, false, Ordering::SeqCst, Ordering::SeqCst)
- .is_ok()
- {
- let env = unsafe { &mut *self.env };
- env.threadsafe_function_unref();
- }
-
- napi_ok
- }
-
- pub fn call(
- &self,
- data: *mut c_void,
- mode: napi_threadsafe_function_call_mode,
- ) -> napi_status {
- if self.is_closing.load(Ordering::SeqCst) {
- return napi_closing;
- }
-
- if self.max_queue_size > 0 {
- let mut queue_size = self.queue_size.lock();
- while *queue_size >= self.max_queue_size {
- if mode == napi_tsfn_blocking {
- self.queue_cond.wait(&mut queue_size);
-
- if self.is_closing.load(Ordering::SeqCst) {
- return napi_closing;
- }
- } else {
- return napi_queue_full;
- }
- }
- *queue_size += 1;
- }
-
- let is_closed = self.is_closed.clone();
- let tsfn = SendPtr(self);
- let data = SendPtr(data);
- let context = SendPtr(self.context);
- let call_js_cb = self.call_js_cb;
-
- self.sender.spawn(move |scope: &mut v8::HandleScope| {
- let data = data.take();
-
- // if is_closed then tsfn is freed, don't read from it.
- if is_closed.load(Ordering::Relaxed) {
- unsafe {
- call_js_cb(
- std::ptr::null_mut(),
- None::<v8::Local<v8::Value>>.into(),
- context.take() as _,
- data as _,
- );
- }
- } else {
- let tsfn = tsfn.take();
-
- let tsfn = unsafe { &*tsfn };
-
- if tsfn.max_queue_size > 0 {
- let mut queue_size = tsfn.queue_size.lock();
- let size = *queue_size;
- *queue_size -= 1;
- if size == tsfn.max_queue_size {
- tsfn.queue_cond.notify_one();
- }
- }
-
- let func = tsfn.func.as_ref().map(|f| v8::Local::new(scope, f));
-
- unsafe {
- (tsfn.call_js_cb)(
- tsfn.env as _,
- func.into(),
- tsfn.context,
- data as _,
- );
- }
- }
- });
-
- napi_ok
- }
-}
-
-#[napi_sym]
-#[allow(clippy::too_many_arguments)]
-fn napi_create_threadsafe_function(
- env: *mut Env,
- func: napi_value,
- async_resource: napi_value,
- async_resource_name: napi_value,
- max_queue_size: usize,
- initial_thread_count: usize,
- thread_finalize_data: *mut c_void,
- thread_finalize_cb: Option<napi_finalize>,
- context: *mut c_void,
- call_js_cb: Option<napi_threadsafe_function_call_js>,
- result: *mut napi_threadsafe_function,
-) -> napi_status {
- let env = check_env!(env);
- check_arg!(env, async_resource_name);
- if initial_thread_count == 0 {
- return napi_set_last_error(env, napi_invalid_arg);
- }
- check_arg!(env, result);
-
- let func = if let Some(value) = *func {
- let Ok(func) = v8::Local::<v8::Function>::try_from(value) else {
- return napi_set_last_error(env, napi_function_expected);
- };
- Some(v8::Global::new(&mut env.scope(), func))
- } else {
- check_arg!(env, call_js_cb);
- None
- };
-
- let resource = if let Some(v) = *async_resource {
- let Some(resource) = v.to_object(&mut env.scope()) else {
- return napi_set_last_error(env, napi_object_expected);
- };
- resource
- } else {
- v8::Object::new(&mut env.scope())
- };
- let resource = v8::Global::new(&mut env.scope(), resource);
-
- let Some(resource_name) =
- async_resource_name.and_then(|v| v.to_string(&mut env.scope()))
- else {
- return napi_set_last_error(env, napi_string_expected);
- };
- let resource_name = resource_name.to_rust_string_lossy(&mut env.scope());
-
- let mut tsfn = Box::new(TsFn {
- env,
- func,
- max_queue_size,
- queue_size: Mutex::new(0),
- queue_cond: Condvar::new(),
- thread_count: AtomicUsize::new(initial_thread_count),
- thread_finalize_data,
- thread_finalize_cb,
- context,
- call_js_cb: call_js_cb.unwrap_or(default_call_js_cb),
- _resource: resource,
- _resource_name: resource_name,
- is_closing: AtomicBool::new(false),
- is_closed: Arc::new(AtomicBool::new(false)),
- is_ref: AtomicBool::new(false),
- sender: env.async_work_sender.clone(),
- });
-
- tsfn.ref_();
-
- unsafe {
- *result = Box::into_raw(tsfn) as _;
- }
-
- napi_clear_last_error(env)
-}
-
-/// Maybe called from any thread.
-#[napi_sym]
-fn napi_get_threadsafe_function_context(
- func: napi_threadsafe_function,
- result: *mut *const c_void,
-) -> napi_status {
- assert!(!func.is_null());
- let tsfn = unsafe { &*(func as *const TsFn) };
- unsafe {
- *result = tsfn.context;
- }
- napi_ok
-}
-
-#[napi_sym]
-fn napi_call_threadsafe_function(
- func: napi_threadsafe_function,
- data: *mut c_void,
- is_blocking: napi_threadsafe_function_call_mode,
-) -> napi_status {
- assert!(!func.is_null());
- let tsfn = unsafe { &*(func as *mut TsFn) };
- tsfn.call(data, is_blocking)
-}
-
-#[napi_sym]
-fn napi_acquire_threadsafe_function(
- tsfn: napi_threadsafe_function,
-) -> napi_status {
- assert!(!tsfn.is_null());
- let tsfn = unsafe { &*(tsfn as *mut TsFn) };
- tsfn.acquire()
-}
-
-#[napi_sym]
-fn napi_release_threadsafe_function(
- tsfn: napi_threadsafe_function,
- mode: napi_threadsafe_function_release_mode,
-) -> napi_status {
- assert!(!tsfn.is_null());
- TsFn::release(tsfn as _, mode)
-}
-
-#[napi_sym]
-fn napi_unref_threadsafe_function(
- _env: &mut Env,
- func: napi_threadsafe_function,
-) -> napi_status {
- assert!(!func.is_null());
- let tsfn = unsafe { &*(func as *mut TsFn) };
- tsfn.unref()
-}
-
-#[napi_sym]
-fn napi_ref_threadsafe_function(
- _env: &mut Env,
- func: napi_threadsafe_function,
-) -> napi_status {
- assert!(!func.is_null());
- let tsfn = unsafe { &*(func as *mut TsFn) };
- tsfn.ref_()
-}
-
-#[napi_sym]
-fn node_api_get_module_file_name(
- env: *mut Env,
- result: *mut *const c_char,
-) -> napi_status {
- let env = check_env!(env);
- check_arg!(env, result);
-
- unsafe {
- *result = env.shared().filename.as_ptr() as _;
- }
-
- napi_clear_last_error(env)
-}