fix(napi): allow ErrorStrategy to be specified while creating TSFN

This commit is contained in:
LongYinan 2021-11-21 14:49:04 +08:00
parent d7da82e269
commit d1a5f84aa0
No known key found for this signature in database
GPG key ID: C3666B7FC82ADAD7
6 changed files with 30 additions and 9 deletions

View file

@ -120,15 +120,16 @@ impl JsFunction {
} }
#[cfg(feature = "napi4")] #[cfg(feature = "napi4")]
pub fn create_threadsafe_function<T, V, F>( pub fn create_threadsafe_function<T, V, F, ES>(
&self, &self,
max_queue_size: usize, max_queue_size: usize,
callback: F, callback: F,
) -> Result<ThreadsafeFunction<T>> ) -> Result<ThreadsafeFunction<T, ES>>
where where
T: 'static, T: 'static,
V: NapiRaw, V: NapiRaw,
F: 'static + Send + FnMut(ThreadSafeCallContext<T>) -> Result<Vec<V>>, F: 'static + Send + FnMut(ThreadSafeCallContext<T>) -> Result<Vec<V>>,
ES: crate::threadsafe_function::ErrorStrategy::T,
{ {
ThreadsafeFunction::create(self.0.env, self.0.value, max_queue_size, callback) ThreadsafeFunction::create(self.0.env, self.0.value, max_queue_size, callback)
} }

View file

@ -57,6 +57,7 @@ Generated by [AVA](https://avajs.dev).
export function withAbortController(a: number, b: number, signal: AbortSignal): Promise<number> export function withAbortController(a: number, b: number, signal: AbortSignal): Promise<number>
export function callThreadsafeFunction(callback: (...args: any[]) => any): void␊ export function callThreadsafeFunction(callback: (...args: any[]) => any): void␊
export function threadsafeFunctionThrowError(cb: (...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 function getBuffer(): Buffer␊
export class Animal {␊ export class Animal {␊
readonly kind: Kind␊ readonly kind: Kind␊

View file

@ -47,6 +47,7 @@ import {
getNull, getNull,
setSymbolInObj, setSymbolInObj,
createSymbol, createSymbol,
threadsafeFunctionFatalMode,
} from '../' } from '../'
test('export const', (t) => { test('export const', (t) => {
@ -304,6 +305,13 @@ Napi4Test('throw error from thread safe function', async (t) => {
t.is(err.message, 'ThrowFromNative') t.is(err.message, 'ThrowFromNative')
}) })
Napi4Test('throw error from thread safe function fatal mode', async (t) => {
const tsfnFatalMode = new Promise<boolean>((resolve) => {
threadsafeFunctionFatalMode(resolve)
})
t.true(await tsfnFatalMode)
})
Napi4Test('await Promise in rust', async (t) => { Napi4Test('await Promise in rust', async (t) => {
const fx = 20 const fx = 20
const result = await asyncPlus100( const result = await asyncPlus100(

View file

@ -47,6 +47,7 @@ export function withoutAbortController(a: number, b: number): Promise<number>
export function withAbortController(a: number, b: number, signal: AbortSignal): Promise<number> export function withAbortController(a: number, b: number, signal: AbortSignal): Promise<number>
export function callThreadsafeFunction(callback: (...args: any[]) => any): void export function callThreadsafeFunction(callback: (...args: any[]) => any): void
export function threadsafeFunctionThrowError(cb: (...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 function getBuffer(): Buffer
export class Animal { export class Animal {
readonly kind: Kind readonly kind: Kind

View file

@ -2,14 +2,15 @@ use std::thread;
use napi::{ use napi::{
bindgen_prelude::*, bindgen_prelude::*,
threadsafe_function::{ThreadSafeCallContext, ThreadsafeFunctionCallMode}, threadsafe_function::{ErrorStrategy, ThreadsafeFunction, ThreadsafeFunctionCallMode},
}; };
#[napi] #[napi]
pub fn call_threadsafe_function(callback: JsFunction) -> Result<()> { pub fn call_threadsafe_function(callback: JsFunction) -> Result<()> {
let tsfn = callback.create_threadsafe_function(0, |ctx: ThreadSafeCallContext<u32>| { let tsfn: ThreadsafeFunction<u32, ErrorStrategy::CalleeHandled> = callback
ctx.env.create_uint32(ctx.value + 1).map(|v| vec![v]) .create_threadsafe_function(0, |ctx| {
})?; ctx.env.create_uint32(ctx.value + 1).map(|v| vec![v])
})?;
for n in 0..100 { for n in 0..100 {
let tsfn = tsfn.clone(); let tsfn = tsfn.clone();
thread::spawn(move || { thread::spawn(move || {
@ -21,9 +22,8 @@ pub fn call_threadsafe_function(callback: JsFunction) -> Result<()> {
#[napi] #[napi]
pub fn threadsafe_function_throw_error(cb: JsFunction) -> Result<()> { pub fn threadsafe_function_throw_error(cb: JsFunction) -> Result<()> {
let tsfn = cb.create_threadsafe_function(0, |ctx: ThreadSafeCallContext<bool>| { let tsfn: ThreadsafeFunction<bool, ErrorStrategy::CalleeHandled> =
ctx.env.get_boolean(ctx.value).map(|v| vec![v]) cb.create_threadsafe_function(0, |ctx| ctx.env.get_boolean(ctx.value).map(|v| vec![v]))?;
})?;
thread::spawn(move || { thread::spawn(move || {
tsfn.call( tsfn.call(
Err(Error::new( Err(Error::new(
@ -35,3 +35,13 @@ pub fn threadsafe_function_throw_error(cb: JsFunction) -> Result<()> {
}); });
Ok(()) Ok(())
} }
#[napi]
pub fn threadsafe_function_fatal_mode(cb: JsFunction) -> Result<()> {
let tsfn: ThreadsafeFunction<bool, ErrorStrategy::Fatal> =
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(())
}