diff --git a/crates/napi/src/js_values/function.rs b/crates/napi/src/js_values/function.rs index 360b8d36..e0ba67d8 100644 --- a/crates/napi/src/js_values/function.rs +++ b/crates/napi/src/js_values/function.rs @@ -120,15 +120,16 @@ impl JsFunction { } #[cfg(feature = "napi4")] - pub fn create_threadsafe_function( + pub fn create_threadsafe_function( &self, max_queue_size: usize, callback: F, - ) -> Result> + ) -> Result> where T: 'static, V: NapiRaw, F: 'static + Send + FnMut(ThreadSafeCallContext) -> Result>, + ES: crate::threadsafe_function::ErrorStrategy::T, { ThreadsafeFunction::create(self.0.env, self.0.value, max_queue_size, callback) } diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index 937c2973..d46afc27 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -57,6 +57,7 @@ Generated by [AVA](https://avajs.dev). export function withAbortController(a: number, b: number, signal: AbortSignal): Promise␊ export function callThreadsafeFunction(callback: (...args: any[]) => any): void␊ export function threadsafeFunctionThrowError(cb: (...args: any[]) => any): void␊ + export function threadsafeFunctionFatalMode(cb: (...args: any[]) => any): void␊ export function getBuffer(): Buffer␊ export class Animal {␊ readonly kind: Kind␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index f58e243c..717c6738 100644 Binary files a/examples/napi/__test__/typegen.spec.ts.snap and b/examples/napi/__test__/typegen.spec.ts.snap differ diff --git a/examples/napi/__test__/values.spec.ts b/examples/napi/__test__/values.spec.ts index 6dbf8e47..01a9e92b 100644 --- a/examples/napi/__test__/values.spec.ts +++ b/examples/napi/__test__/values.spec.ts @@ -47,6 +47,7 @@ import { getNull, setSymbolInObj, createSymbol, + threadsafeFunctionFatalMode, } from '../' test('export const', (t) => { @@ -304,6 +305,13 @@ Napi4Test('throw error from thread safe function', async (t) => { t.is(err.message, 'ThrowFromNative') }) +Napi4Test('throw error from thread safe function fatal mode', async (t) => { + const tsfnFatalMode = new Promise((resolve) => { + threadsafeFunctionFatalMode(resolve) + }) + t.true(await tsfnFatalMode) +}) + Napi4Test('await Promise in rust', async (t) => { const fx = 20 const result = await asyncPlus100( diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index 396941f4..d5476cc4 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -47,6 +47,7 @@ export function withoutAbortController(a: number, b: number): Promise export function withAbortController(a: number, b: number, signal: AbortSignal): Promise export function callThreadsafeFunction(callback: (...args: any[]) => any): void export function threadsafeFunctionThrowError(cb: (...args: any[]) => any): void +export function threadsafeFunctionFatalMode(cb: (...args: any[]) => any): void export function getBuffer(): Buffer export class Animal { readonly kind: Kind diff --git a/examples/napi/src/threadsafe_function.rs b/examples/napi/src/threadsafe_function.rs index 2115fd43..9a238b88 100644 --- a/examples/napi/src/threadsafe_function.rs +++ b/examples/napi/src/threadsafe_function.rs @@ -2,14 +2,15 @@ use std::thread; use napi::{ bindgen_prelude::*, - threadsafe_function::{ThreadSafeCallContext, ThreadsafeFunctionCallMode}, + threadsafe_function::{ErrorStrategy, ThreadsafeFunction, ThreadsafeFunctionCallMode}, }; #[napi] pub fn call_threadsafe_function(callback: JsFunction) -> Result<()> { - let tsfn = callback.create_threadsafe_function(0, |ctx: ThreadSafeCallContext| { - ctx.env.create_uint32(ctx.value + 1).map(|v| vec![v]) - })?; + let tsfn: ThreadsafeFunction = callback + .create_threadsafe_function(0, |ctx| { + ctx.env.create_uint32(ctx.value + 1).map(|v| vec![v]) + })?; for n in 0..100 { let tsfn = tsfn.clone(); thread::spawn(move || { @@ -21,9 +22,8 @@ pub fn call_threadsafe_function(callback: JsFunction) -> Result<()> { #[napi] pub fn threadsafe_function_throw_error(cb: JsFunction) -> Result<()> { - let tsfn = cb.create_threadsafe_function(0, |ctx: ThreadSafeCallContext| { - ctx.env.get_boolean(ctx.value).map(|v| vec![v]) - })?; + let tsfn: ThreadsafeFunction = + cb.create_threadsafe_function(0, |ctx| ctx.env.get_boolean(ctx.value).map(|v| vec![v]))?; thread::spawn(move || { tsfn.call( Err(Error::new( @@ -35,3 +35,13 @@ pub fn threadsafe_function_throw_error(cb: JsFunction) -> Result<()> { }); Ok(()) } + +#[napi] +pub fn threadsafe_function_fatal_mode(cb: JsFunction) -> Result<()> { + let tsfn: ThreadsafeFunction = + cb.create_threadsafe_function(0, |ctx| ctx.env.get_boolean(ctx.value).map(|v| vec![v]))?; + thread::spawn(move || { + tsfn.call(true, ThreadsafeFunctionCallMode::Blocking); + }); + Ok(()) +}