feat(napi-derive): generate ThreadsafeFunction types (#1449)

This commit is contained in:
LongYinan 2023-01-24 14:25:05 +08:00 committed by GitHub
parent 02daa90058
commit e79eb34118
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 5 deletions

View file

@ -180,6 +180,7 @@ static KNOWN_TYPES: Lazy<HashMap<&'static str, (&'static str, bool, bool)>> = La
("Either25", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)), ("Either25", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
("Either26", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)), ("Either26", ("{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}", false, true)),
("external", ("object", false, false)), ("external", ("object", false, false)),
("Promise", ("Promise<{}>", false, false)),
("AbortSignal", ("AbortSignal", false, false)), ("AbortSignal", ("AbortSignal", false, false)),
("JsGlobal", ("typeof global", false, false)), ("JsGlobal", ("typeof global", false, false)),
("External", ("ExternalObject<{}>", false, false)), ("External", ("ExternalObject<{}>", false, false)),
@ -333,11 +334,20 @@ pub fn ty_to_ts_type(ty: &Type, is_return_ty: bool, is_struct_field: bool) -> (S
.with(|c| c.borrow_mut().get(rust_ty.as_str()).cloned()) .with(|c| c.borrow_mut().get(rust_ty.as_str()).cloned())
{ {
ts_ty = Some((t, false)); ts_ty = Some((t, false));
} else if rust_ty == "Promise" { } else if rust_ty == "ThreadsafeFunction" {
ts_ty = Some(( let fatal_tsfn = match args.get(1) {
format!("Promise<{}>", args.first().map(|(arg, _)| arg).unwrap()), Some((arg, _)) => arg == "Fatal",
false, _ => false,
)); };
let first_arg = args.first().map(|(arg, _)| arg).unwrap();
ts_ty = if fatal_tsfn {
Some((format!("(value: {}) => any", first_arg), false))
} else {
Some((
format!("(err: Error | null, value: {}) => any", first_arg),
false,
))
};
} else { } else {
// there should be runtime registered type in else // there should be runtime registered type in else
let type_alias = ALIAS.with(|aliases| { let type_alias = ALIAS.with(|aliases| {

View file

@ -200,6 +200,8 @@ Generated by [AVA](https://avajs.dev).
export function threadsafeFunctionClosureCapture(func: (...args: any[]) => any): void␊ export function threadsafeFunctionClosureCapture(func: (...args: any[]) => any): void␊
export function tsfnCallWithCallback(func: (...args: any[]) => any): void␊ export function tsfnCallWithCallback(func: (...args: any[]) => any): void␊
export function tsfnAsyncCall(func: (...args: any[]) => any): Promise<void> export function tsfnAsyncCall(func: (...args: any[]) => any): Promise<void>
export function acceptThreadsafeFunction(func: (err: Error | null, value: number) => any): void␊
export function acceptThreadsafeFunctionFatal(func: (value: number) => any): void␊
export function getBuffer(): Buffer␊ export function getBuffer(): Buffer␊
export function appendBuffer(buf: Buffer): Buffer␊ export function appendBuffer(buf: Buffer): Buffer␊
export function getEmptyBuffer(): Buffer␊ export function getEmptyBuffer(): Buffer␊

View file

@ -116,6 +116,8 @@ import {
captureErrorInCallback, captureErrorInCallback,
bigintFromI128, bigintFromI128,
bigintFromI64, bigintFromI64,
acceptThreadsafeFunction,
acceptThreadsafeFunctionFatal,
} from '../' } from '../'
test('export const', (t) => { test('export const', (t) => {
@ -792,6 +794,28 @@ Napi4Test('async call ThreadsafeFunction', async (t) => {
) )
}) })
Napi4Test('accept ThreadsafeFunction', async (t) => {
await new Promise<void>((resolve, reject) => {
acceptThreadsafeFunction((err, value) => {
if (err) {
reject(err)
} else {
t.is(value, 1)
resolve()
}
})
})
})
Napi4Test('accept ThreadsafeFunction Fatal', async (t) => {
await new Promise<void>((resolve) => {
acceptThreadsafeFunctionFatal((value) => {
t.is(value, 1)
resolve()
})
})
})
const Napi5Test = Number(process.versions.napi) >= 5 ? test : test.skip const Napi5Test = Number(process.versions.napi) >= 5 ? test : test.skip
Napi5Test('Date test', (t) => { Napi5Test('Date test', (t) => {

View file

@ -190,6 +190,8 @@ export function threadsafeFunctionFatalModeError(cb: (...args: any[]) => any): v
export function threadsafeFunctionClosureCapture(func: (...args: any[]) => any): void export function threadsafeFunctionClosureCapture(func: (...args: any[]) => any): void
export function tsfnCallWithCallback(func: (...args: any[]) => any): void export function tsfnCallWithCallback(func: (...args: any[]) => any): void
export function tsfnAsyncCall(func: (...args: any[]) => any): Promise<void> export function tsfnAsyncCall(func: (...args: any[]) => any): Promise<void>
export function acceptThreadsafeFunction(func: (err: Error | null, value: number) => any): void
export function acceptThreadsafeFunctionFatal(func: (value: number) => any): void
export function getBuffer(): Buffer export function getBuffer(): Buffer
export function appendBuffer(buf: Buffer): Buffer export function appendBuffer(buf: Buffer): Buffer
export function getEmptyBuffer(): Buffer export function getEmptyBuffer(): Buffer

View file

@ -102,3 +102,17 @@ pub fn tsfn_async_call(env: Env, func: JsFunction) -> napi::Result<Object> {
Ok(()) Ok(())
}) })
} }
#[napi]
pub fn accept_threadsafe_function(func: ThreadsafeFunction<u32>) {
thread::spawn(move || {
func.call(Ok(1), ThreadsafeFunctionCallMode::NonBlocking);
});
}
#[napi]
pub fn accept_threadsafe_function_fatal(func: ThreadsafeFunction<u32, ErrorStrategy::Fatal>) {
thread::spawn(move || {
func.call(1, ThreadsafeFunctionCallMode::NonBlocking);
});
}