mirror of
https://github.com/napi-rs/napi-rs.git
synced 2025-12-08 19:56:07 +00:00
feat(napi): introduce AsyncBlock to let user dispose resources after future done (#2338)
This commit is contained in:
parent
00a3c13b42
commit
f705454029
@ -410,6 +410,13 @@ pub fn ty_to_ts_type(
|
||||
Some((rust_ty, false))
|
||||
}
|
||||
});
|
||||
} else if rust_ty == "AsyncBlock" {
|
||||
if let Some(arg) = args.first() {
|
||||
ts_ty = Some((format!("Promise<{}>", arg.0), false));
|
||||
} else {
|
||||
// Not NAPI-RS `AsyncBlock`
|
||||
ts_ty = Some((rust_ty, false));
|
||||
}
|
||||
} else if let Some(&(known_ty, _, _)) = KNOWN_TYPES.get(rust_ty.as_str()) {
|
||||
if rust_ty == "()" && is_return_ty {
|
||||
ts_ty = Some(("void".to_owned(), false));
|
||||
|
||||
@ -347,6 +347,7 @@ impl Drop for Buffer {
|
||||
/// SAFETY: This is undefined behavior, as the JS side may always modify the underlying buffer,
|
||||
/// without synchronization. Also see the docs for the `AsMut` impl.
|
||||
unsafe impl Send for Buffer {}
|
||||
unsafe impl Sync for Buffer {}
|
||||
|
||||
impl Clone for Buffer {
|
||||
fn clone(&self) -> Self {
|
||||
|
||||
@ -6,7 +6,9 @@ use std::{
|
||||
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
use crate::{sys, Error, JsDeferred, JsUnknown, NapiValue, Result};
|
||||
use crate::{
|
||||
bindgen_runtime::ToNapiValue, sys, Env, Error, JsDeferred, JsUnknown, NapiValue, Result,
|
||||
};
|
||||
|
||||
fn create_runtime() -> Option<Runtime> {
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
@ -221,3 +223,55 @@ pub fn execute_tokio_future<
|
||||
|
||||
Ok(promise.0.value)
|
||||
}
|
||||
|
||||
pub struct AsyncBlockBuilder<
|
||||
V: ToNapiValue + Send + 'static,
|
||||
F: Future<Output = Result<V>> + Send + 'static,
|
||||
Dispose: FnOnce(Env) + 'static,
|
||||
> {
|
||||
inner: F,
|
||||
dispose: Option<Dispose>,
|
||||
}
|
||||
|
||||
impl<
|
||||
V: ToNapiValue + Send + 'static,
|
||||
F: Future<Output = Result<V>> + Send + 'static,
|
||||
Dispose: FnOnce(Env),
|
||||
> AsyncBlockBuilder<V, F, Dispose>
|
||||
{
|
||||
pub fn with(inner: F) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
dispose: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_dispose(mut self, dispose: Dispose) -> Self {
|
||||
self.dispose = Some(dispose);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self, env: Env) -> Result<AsyncBlock<V>> {
|
||||
Ok(AsyncBlock {
|
||||
inner: execute_tokio_future(env.0, self.inner, |env, v| unsafe {
|
||||
if let Some(dispose) = self.dispose {
|
||||
let env = Env::from_raw(env);
|
||||
dispose(env);
|
||||
}
|
||||
V::to_napi_value(env, v)
|
||||
})?,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AsyncBlock<T: ToNapiValue + Send + 'static> {
|
||||
inner: sys::napi_value,
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: ToNapiValue + Send + 'static> ToNapiValue for AsyncBlock<T> {
|
||||
unsafe fn to_napi_value(_: napi_sys::napi_env, val: Self) -> Result<napi_sys::napi_value> {
|
||||
Ok(val.inner)
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,6 +335,8 @@ Generated by [AVA](https://avajs.dev).
|
||||
␊
|
||||
export declare function bufferPassThrough(buf: Buffer): Promise<Buffer>␊
|
||||
␊
|
||||
export declare function bufferWithAsyncBlock(buf: Buffer): Promise<number>␊
|
||||
␊
|
||||
export declare function buildThreadsafeFunctionFromFunction(callback: (arg0: number, arg1: number) => number): void␊
|
||||
␊
|
||||
export declare function buildThreadsafeFunctionFromFunctionCalleeHandle(callback: () => void): void␊
|
||||
|
||||
Binary file not shown.
@ -359,29 +359,30 @@ function __napi_rs_initialize_modules(__napiInstance) {
|
||||
__napiInstance.exports['__napi_register__mutate_typed_array_363']?.()
|
||||
__napiInstance.exports['__napi_register__deref_uint8_array_364']?.()
|
||||
__napiInstance.exports['__napi_register__buffer_pass_through_365']?.()
|
||||
__napiInstance.exports['__napi_register__array_buffer_pass_through_366']?.()
|
||||
__napiInstance.exports['__napi_register__accept_slice_367']?.()
|
||||
__napiInstance.exports['__napi_register__accept_arraybuffer_368']?.()
|
||||
__napiInstance.exports['__napi_register__create_arraybuffer_369']?.()
|
||||
__napiInstance.exports['__napi_register__u8_array_to_array_370']?.()
|
||||
__napiInstance.exports['__napi_register__i8_array_to_array_371']?.()
|
||||
__napiInstance.exports['__napi_register__u16_array_to_array_372']?.()
|
||||
__napiInstance.exports['__napi_register__i16_array_to_array_373']?.()
|
||||
__napiInstance.exports['__napi_register__u32_array_to_array_374']?.()
|
||||
__napiInstance.exports['__napi_register__i32_array_to_array_375']?.()
|
||||
__napiInstance.exports['__napi_register__f32_array_to_array_376']?.()
|
||||
__napiInstance.exports['__napi_register__f64_array_to_array_377']?.()
|
||||
__napiInstance.exports['__napi_register__u64_array_to_array_378']?.()
|
||||
__napiInstance.exports['__napi_register__i64_array_to_array_379']?.()
|
||||
__napiInstance.exports['__napi_register__accept_uint8_clamped_slice_380']?.()
|
||||
__napiInstance.exports['__napi_register__accept_uint8_clamped_slice_and_buffer_slice_381']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncBuffer_impl_382']?.()
|
||||
__napiInstance.exports['__napi_register__async_reduce_buffer_383']?.()
|
||||
__napiInstance.exports['__napi_register__async_buffer_to_array_384']?.()
|
||||
__napiInstance.exports['__napi_register__u_init8_array_from_string_385']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncReader_impl_386']?.()
|
||||
__napiInstance.exports['__napi_register__Reader_struct_387']?.()
|
||||
__napiInstance.exports['__napi_register__Reader_impl_389']?.()
|
||||
__napiInstance.exports['__napi_register__buffer_with_async_block_366']?.()
|
||||
__napiInstance.exports['__napi_register__array_buffer_pass_through_367']?.()
|
||||
__napiInstance.exports['__napi_register__accept_slice_368']?.()
|
||||
__napiInstance.exports['__napi_register__accept_arraybuffer_369']?.()
|
||||
__napiInstance.exports['__napi_register__create_arraybuffer_370']?.()
|
||||
__napiInstance.exports['__napi_register__u8_array_to_array_371']?.()
|
||||
__napiInstance.exports['__napi_register__i8_array_to_array_372']?.()
|
||||
__napiInstance.exports['__napi_register__u16_array_to_array_373']?.()
|
||||
__napiInstance.exports['__napi_register__i16_array_to_array_374']?.()
|
||||
__napiInstance.exports['__napi_register__u32_array_to_array_375']?.()
|
||||
__napiInstance.exports['__napi_register__i32_array_to_array_376']?.()
|
||||
__napiInstance.exports['__napi_register__f32_array_to_array_377']?.()
|
||||
__napiInstance.exports['__napi_register__f64_array_to_array_378']?.()
|
||||
__napiInstance.exports['__napi_register__u64_array_to_array_379']?.()
|
||||
__napiInstance.exports['__napi_register__i64_array_to_array_380']?.()
|
||||
__napiInstance.exports['__napi_register__accept_uint8_clamped_slice_381']?.()
|
||||
__napiInstance.exports['__napi_register__accept_uint8_clamped_slice_and_buffer_slice_382']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncBuffer_impl_383']?.()
|
||||
__napiInstance.exports['__napi_register__async_reduce_buffer_384']?.()
|
||||
__napiInstance.exports['__napi_register__async_buffer_to_array_385']?.()
|
||||
__napiInstance.exports['__napi_register__u_init8_array_from_string_386']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncReader_impl_387']?.()
|
||||
__napiInstance.exports['__napi_register__Reader_struct_388']?.()
|
||||
__napiInstance.exports['__napi_register__Reader_impl_390']?.()
|
||||
}
|
||||
export const Animal = __napiModule.exports.Animal
|
||||
export const AnimalWithDefaultConstructor = __napiModule.exports.AnimalWithDefaultConstructor
|
||||
@ -453,6 +454,7 @@ export const bigintGetU64AsString = __napiModule.exports.bigintGetU64AsString
|
||||
export const btreeSetToJs = __napiModule.exports.btreeSetToJs
|
||||
export const btreeSetToRust = __napiModule.exports.btreeSetToRust
|
||||
export const bufferPassThrough = __napiModule.exports.bufferPassThrough
|
||||
export const bufferWithAsyncBlock = __napiModule.exports.bufferWithAsyncBlock
|
||||
export const buildThreadsafeFunctionFromFunction = __napiModule.exports.buildThreadsafeFunctionFromFunction
|
||||
export const buildThreadsafeFunctionFromFunctionCalleeHandle = __napiModule.exports.buildThreadsafeFunctionFromFunctionCalleeHandle
|
||||
export const call0 = __napiModule.exports.call0
|
||||
|
||||
@ -383,29 +383,30 @@ function __napi_rs_initialize_modules(__napiInstance) {
|
||||
__napiInstance.exports['__napi_register__mutate_typed_array_363']?.()
|
||||
__napiInstance.exports['__napi_register__deref_uint8_array_364']?.()
|
||||
__napiInstance.exports['__napi_register__buffer_pass_through_365']?.()
|
||||
__napiInstance.exports['__napi_register__array_buffer_pass_through_366']?.()
|
||||
__napiInstance.exports['__napi_register__accept_slice_367']?.()
|
||||
__napiInstance.exports['__napi_register__accept_arraybuffer_368']?.()
|
||||
__napiInstance.exports['__napi_register__create_arraybuffer_369']?.()
|
||||
__napiInstance.exports['__napi_register__u8_array_to_array_370']?.()
|
||||
__napiInstance.exports['__napi_register__i8_array_to_array_371']?.()
|
||||
__napiInstance.exports['__napi_register__u16_array_to_array_372']?.()
|
||||
__napiInstance.exports['__napi_register__i16_array_to_array_373']?.()
|
||||
__napiInstance.exports['__napi_register__u32_array_to_array_374']?.()
|
||||
__napiInstance.exports['__napi_register__i32_array_to_array_375']?.()
|
||||
__napiInstance.exports['__napi_register__f32_array_to_array_376']?.()
|
||||
__napiInstance.exports['__napi_register__f64_array_to_array_377']?.()
|
||||
__napiInstance.exports['__napi_register__u64_array_to_array_378']?.()
|
||||
__napiInstance.exports['__napi_register__i64_array_to_array_379']?.()
|
||||
__napiInstance.exports['__napi_register__accept_uint8_clamped_slice_380']?.()
|
||||
__napiInstance.exports['__napi_register__accept_uint8_clamped_slice_and_buffer_slice_381']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncBuffer_impl_382']?.()
|
||||
__napiInstance.exports['__napi_register__async_reduce_buffer_383']?.()
|
||||
__napiInstance.exports['__napi_register__async_buffer_to_array_384']?.()
|
||||
__napiInstance.exports['__napi_register__u_init8_array_from_string_385']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncReader_impl_386']?.()
|
||||
__napiInstance.exports['__napi_register__Reader_struct_387']?.()
|
||||
__napiInstance.exports['__napi_register__Reader_impl_389']?.()
|
||||
__napiInstance.exports['__napi_register__buffer_with_async_block_366']?.()
|
||||
__napiInstance.exports['__napi_register__array_buffer_pass_through_367']?.()
|
||||
__napiInstance.exports['__napi_register__accept_slice_368']?.()
|
||||
__napiInstance.exports['__napi_register__accept_arraybuffer_369']?.()
|
||||
__napiInstance.exports['__napi_register__create_arraybuffer_370']?.()
|
||||
__napiInstance.exports['__napi_register__u8_array_to_array_371']?.()
|
||||
__napiInstance.exports['__napi_register__i8_array_to_array_372']?.()
|
||||
__napiInstance.exports['__napi_register__u16_array_to_array_373']?.()
|
||||
__napiInstance.exports['__napi_register__i16_array_to_array_374']?.()
|
||||
__napiInstance.exports['__napi_register__u32_array_to_array_375']?.()
|
||||
__napiInstance.exports['__napi_register__i32_array_to_array_376']?.()
|
||||
__napiInstance.exports['__napi_register__f32_array_to_array_377']?.()
|
||||
__napiInstance.exports['__napi_register__f64_array_to_array_378']?.()
|
||||
__napiInstance.exports['__napi_register__u64_array_to_array_379']?.()
|
||||
__napiInstance.exports['__napi_register__i64_array_to_array_380']?.()
|
||||
__napiInstance.exports['__napi_register__accept_uint8_clamped_slice_381']?.()
|
||||
__napiInstance.exports['__napi_register__accept_uint8_clamped_slice_and_buffer_slice_382']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncBuffer_impl_383']?.()
|
||||
__napiInstance.exports['__napi_register__async_reduce_buffer_384']?.()
|
||||
__napiInstance.exports['__napi_register__async_buffer_to_array_385']?.()
|
||||
__napiInstance.exports['__napi_register__u_init8_array_from_string_386']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncReader_impl_387']?.()
|
||||
__napiInstance.exports['__napi_register__Reader_struct_388']?.()
|
||||
__napiInstance.exports['__napi_register__Reader_impl_390']?.()
|
||||
}
|
||||
module.exports.Animal = __napiModule.exports.Animal
|
||||
module.exports.AnimalWithDefaultConstructor = __napiModule.exports.AnimalWithDefaultConstructor
|
||||
@ -477,6 +478,7 @@ module.exports.bigintGetU64AsString = __napiModule.exports.bigintGetU64AsString
|
||||
module.exports.btreeSetToJs = __napiModule.exports.btreeSetToJs
|
||||
module.exports.btreeSetToRust = __napiModule.exports.btreeSetToRust
|
||||
module.exports.bufferPassThrough = __napiModule.exports.bufferPassThrough
|
||||
module.exports.bufferWithAsyncBlock = __napiModule.exports.bufferWithAsyncBlock
|
||||
module.exports.buildThreadsafeFunctionFromFunction = __napiModule.exports.buildThreadsafeFunctionFromFunction
|
||||
module.exports.buildThreadsafeFunctionFromFunctionCalleeHandle = __napiModule.exports.buildThreadsafeFunctionFromFunctionCalleeHandle
|
||||
module.exports.call0 = __napiModule.exports.call0
|
||||
|
||||
@ -434,6 +434,7 @@ module.exports.bigintGetU64AsString = nativeBinding.bigintGetU64AsString
|
||||
module.exports.btreeSetToJs = nativeBinding.btreeSetToJs
|
||||
module.exports.btreeSetToRust = nativeBinding.btreeSetToRust
|
||||
module.exports.bufferPassThrough = nativeBinding.bufferPassThrough
|
||||
module.exports.bufferWithAsyncBlock = nativeBinding.bufferWithAsyncBlock
|
||||
module.exports.buildThreadsafeFunctionFromFunction = nativeBinding.buildThreadsafeFunctionFromFunction
|
||||
module.exports.buildThreadsafeFunctionFromFunctionCalleeHandle = nativeBinding.buildThreadsafeFunctionFromFunctionCalleeHandle
|
||||
module.exports.call0 = nativeBinding.call0
|
||||
|
||||
@ -325,6 +325,8 @@ export declare function btreeSetToRust(set: Set<string>): void
|
||||
|
||||
export declare function bufferPassThrough(buf: Buffer): Promise<Buffer>
|
||||
|
||||
export declare function bufferWithAsyncBlock(buf: Buffer): Promise<number>
|
||||
|
||||
export declare function buildThreadsafeFunctionFromFunction(callback: (arg0: number, arg1: number) => number): void
|
||||
|
||||
export declare function buildThreadsafeFunctionFromFunctionCalleeHandle(callback: () => void): void
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use napi::{bindgen_prelude::*, JsArrayBuffer};
|
||||
|
||||
#[napi]
|
||||
@ -73,6 +75,16 @@ async fn buffer_pass_through(buf: Buffer) -> Result<Buffer> {
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
#[napi]
|
||||
fn buffer_with_async_block(env: Env, buf: Arc<Buffer>) -> Result<AsyncBlock<u32>> {
|
||||
let buf_to_dispose = buf.clone();
|
||||
AsyncBlockBuilder::with(async move { Ok(buf.len() as u32) })
|
||||
.with_dispose(move |_| {
|
||||
drop(buf_to_dispose);
|
||||
})
|
||||
.build(env)
|
||||
}
|
||||
|
||||
#[napi]
|
||||
async fn array_buffer_pass_through(buf: Uint8Array) -> Result<Uint8Array> {
|
||||
Ok(buf)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user