diff --git a/crates/backend/src/codegen/fn.rs b/crates/backend/src/codegen/fn.rs index bccc47e3..f3139ecc 100644 --- a/crates/backend/src/codegen/fn.rs +++ b/crates/backend/src/codegen/fn.rs @@ -92,12 +92,10 @@ impl TryToTokens for NapiFn { }; let native_call = if !self.is_async { quote! { - napi::bindgen_prelude::within_runtime_if_available(move || { - let #receiver_ret_name = { - #receiver(#(#arg_names),*) - }; - #ret - }) + let #receiver_ret_name = { + #receiver(#(#arg_names),*) + }; + #ret } } else { let call = if self.is_ret_result { @@ -127,6 +125,7 @@ impl TryToTokens for NapiFn { let function_call_inner = quote! { napi::bindgen_prelude::CallbackInfo::<#args_len>::new(env, cb, None, #use_after_async).and_then(|mut cb| { + let __wrapped_env = napi::bindgen_prelude::Env::from(env); #build_ref_container #(#arg_conversions)* #native_call @@ -253,7 +252,7 @@ impl NapiFn { match &arg.kind { NapiFnArgKind::PatType(path) => { if &path.ty.to_token_stream().to_string() == "Env" { - args.push(quote! { napi::bindgen_prelude::Env::from(env) }); + args.push(quote! { __wrapped_env }); skipped_arg_count += 1; } else { let is_in_class = self.parent.is_some(); @@ -357,6 +356,11 @@ impl NapiFn { if arg_type.is_ref() { refs.push(make_ref(quote! { cb.get_arg(#i) })); } + if arg_type == NapiArgType::Env { + args.push(quote! { &__wrapped_env }); + skipped_arg_count += 1; + continue; + } arg_conversions.push(arg_conversion); args.push(quote! { #ident }); } @@ -454,6 +458,13 @@ impl NapiFn { } } } else { + if let syn::Type::Path(ele) = &**elem { + if let Some(syn::PathSegment { ident, .. }) = ele.path.segments.last() { + if ident == "Env" { + return Ok((quote! {}, NapiArgType::Env)); + } + } + } quote! { let #arg_name = { #type_check @@ -702,6 +713,7 @@ enum NapiArgType { Ref, MutRef, Value, + Env, } impl NapiArgType { diff --git a/crates/backend/src/typegen/fn.rs b/crates/backend/src/typegen/fn.rs index 4f96f47e..92d01f23 100644 --- a/crates/backend/src/typegen/fn.rs +++ b/crates/backend/src/typegen/fn.rs @@ -185,6 +185,15 @@ impl NapiFn { if ty_string == "Env" { return None; } + if let syn::Type::Reference(syn::TypeReference { elem, .. }) = &*path.ty { + if let syn::Type::Path(path) = elem.as_ref() { + if let Some(PathSegment { ident, .. }) = path.path.segments.last() { + if ident == "Env" { + return None; + } + } + } + } if let syn::Type::Path(path) = path.ty.as_ref() { if let Some(PathSegment { ident, arguments }) = path.path.segments.last() { if ident == "Reference" || ident == "WeakReference" { diff --git a/crates/macro/src/parser/mod.rs b/crates/macro/src/parser/mod.rs index a00d596f..383c0de1 100644 --- a/crates/macro/src/parser/mod.rs +++ b/crates/macro/src/parser/mod.rs @@ -1203,8 +1203,6 @@ impl ConvertToAST for syn::ItemEnum { }); } - self.attrs.push(parse_quote!(#[derive(Copy, Clone)])); - let variants = match opts.string_enum() { Some(case) => { let case = case.map(|c| Ok::(match c.0.as_str() { diff --git a/crates/napi/src/bindgen_runtime/js_values/buffer.rs b/crates/napi/src/bindgen_runtime/js_values/buffer.rs index 2cc6bdf3..2304287c 100644 --- a/crates/napi/src/bindgen_runtime/js_values/buffer.rs +++ b/crates/napi/src/bindgen_runtime/js_values/buffer.rs @@ -11,7 +11,7 @@ use std::sync::Mutex; #[cfg(all(feature = "napi4", not(feature = "noop"), not(target_family = "wasm")))] use crate::bindgen_prelude::{CUSTOM_GC_TSFN, CUSTOM_GC_TSFN_DESTROYED, THREADS_CAN_ACCESS_ENV}; -use crate::{bindgen_prelude::*, check_status, sys, Result, ValueType}; +use crate::{bindgen_prelude::*, check_status, env::EMPTY_VEC, sys, Result, ValueType}; #[cfg(all(debug_assertions, not(windows)))] thread_local! { @@ -26,6 +26,150 @@ pub struct BufferSlice<'scope> { raw_value: sys::napi_value, } +impl<'scope> BufferSlice<'scope> { + /// Create a new `BufferSlice` from a `Vec`. + /// + /// While this is still a fully-supported data structure, in most cases using a `Uint8Array` will suffice. + pub fn from_data>>(env: &Env, data: D) -> Result { + let mut buf = ptr::null_mut(); + let mut data = data.into(); + let inner_ptr = data.as_mut_ptr(); + #[cfg(all(debug_assertions, not(windows)))] + { + let is_existed = BUFFER_DATA.with(|buffer_data| { + let buffer = buffer_data.lock().expect("Unlock buffer data failed"); + buffer.contains(&inner_ptr) + }); + if is_existed { + panic!("Share the same data between different buffers is not allowed, see: https://github.com/nodejs/node/issues/32463#issuecomment-631974747"); + } + } + let len = data.len(); + let mut status = unsafe { + sys::napi_create_external_buffer( + env.0, + len, + inner_ptr.cast(), + Some(drop_buffer_slice), + Box::into_raw(Box::new(len)).cast(), + &mut buf, + ) + }; + status = if status == sys::Status::napi_no_external_buffers_allowed { + unsafe { + sys::napi_create_buffer_copy( + env.0, + len, + data.as_mut_ptr().cast(), + ptr::null_mut(), + &mut buf, + ) + } + } else { + status + }; + mem::forget(data); + check_status!(status, "Failed to create buffer slice from data")?; + Ok(Self { + inner: unsafe { slice::from_raw_parts_mut(buf.cast(), len) }, + raw_value: buf, + }) + } + + /// ## Safety + /// + /// Mostly the same with `from_data` + /// + /// Provided `finalize_callback` will be called when `BufferSlice` got dropped. + /// + /// You can pass in `noop_finalize` if you have nothing to do in finalize phase. + /// + /// ### Notes + /// + /// JavaScript may mutate the data passed in to this buffer when writing the buffer. + /// However, some JavaScript runtimes do not support external buffers (notably electron!) + /// in which case modifications may be lost. + /// + /// If you need to support these runtimes, you should create a buffer by other means and then + /// later copy the data back out. + pub unsafe fn from_external( + env: &Env, + data: *mut u8, + len: usize, + finalize_hint: T, + finalize_callback: F, + ) -> Result { + let mut buf = ptr::null_mut(); + if data.is_null() || data as *const u8 == EMPTY_VEC.as_ptr() { + return Err(Error::new( + Status::InvalidArg, + "Borrowed data should not be null".to_owned(), + )); + } + #[cfg(all(debug_assertions, not(windows)))] + { + let is_existed = BUFFER_DATA.with(|buffer_data| { + let buffer = buffer_data.lock().expect("Unlock buffer data failed"); + buffer.contains(&data) + }); + if is_existed { + panic!("Share the same data between different buffers is not allowed, see: https://github.com/nodejs/node/issues/32463#issuecomment-631974747"); + } + } + let hint_ptr = Box::into_raw(Box::new((finalize_hint, finalize_callback))); + let mut status = unsafe { + sys::napi_create_external_buffer( + env.0, + len, + data.cast(), + Some(crate::env::raw_finalize_with_custom_callback::), + hint_ptr.cast(), + &mut buf, + ) + }; + status = if status == sys::Status::napi_no_external_buffers_allowed { + let (hint, finalize) = *Box::from_raw(hint_ptr); + let status = + unsafe { sys::napi_create_buffer_copy(env.0, len, data.cast(), ptr::null_mut(), &mut buf) }; + finalize(hint, *env); + status + } else { + status + }; + check_status!(status, "Failed to create buffer slice from data")?; + Ok(Self { + inner: unsafe { slice::from_raw_parts_mut(buf.cast(), len) }, + raw_value: buf, + }) + } + + /// Copy data from a `&[u8]` and create a `BufferSlice` from it. + pub fn copy_from>(env: &Env, data: D) -> Result { + let data = data.as_ref(); + let len = data.len(); + let data_ptr = data.as_ptr(); + let mut buf = ptr::null_mut(); + let mut result_ptr = ptr::null_mut(); + check_status!( + unsafe { + sys::napi_create_buffer_copy(env.0, len, data_ptr.cast(), &mut result_ptr, &mut buf) + }, + "Faild to create a buffer from copied data" + )?; + Ok(Self { + inner: unsafe { slice::from_raw_parts_mut(result_ptr.cast(), len) }, + raw_value: buf, + }) + } + + /// Convert a `BufferSlice` to a `Buffer` + /// + /// This will perform a `napi_create_reference` internally. + pub fn into_buffer(self, env: &Env) -> Result { + unsafe { Buffer::from_napi_value(env.0, self.raw_value) } + } +} + impl<'scope> FromNapiValue for BufferSlice<'scope> { unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result { let mut buf = ptr::null_mut(); @@ -171,8 +315,8 @@ 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. +/// 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 {} impl Clone for Buffer { @@ -351,9 +495,9 @@ impl ToNapiValue for Buffer { sys::napi_create_external_buffer( env, len, - value_ptr as *mut c_void, + value_ptr.cast(), Some(drop_buffer), - val_box_ptr as *mut c_void, + val_box_ptr.cast(), &mut ret, ) }; diff --git a/crates/napi/src/bindgen_runtime/mod.rs b/crates/napi/src/bindgen_runtime/mod.rs index b3acec2d..d72a52a2 100644 --- a/crates/napi/src/bindgen_runtime/mod.rs +++ b/crates/napi/src/bindgen_runtime/mod.rs @@ -88,3 +88,25 @@ pub unsafe extern "C" fn drop_buffer( drop(Box::from_raw(finalize_hint as *mut Buffer)); } } + +/// # Safety +/// +/// called when node buffer slice is ready for gc +#[doc(hidden)] +pub unsafe extern "C" fn drop_buffer_slice( + _env: sys::napi_env, + finalize_data: *mut c_void, + finalize_hint: *mut c_void, +) { + let len = *unsafe { Box::from_raw(finalize_hint.cast()) }; + #[cfg(all(debug_assertions, not(windows)))] + { + js_values::BUFFER_DATA.with(|buffer_data| { + let mut buffer = buffer_data.lock().expect("Unlock Buffer data failed"); + buffer.remove(&(finalize_data as *mut u8)); + }); + } + unsafe { + drop(Vec::from_raw_parts(finalize_data, len, len)); + } +} diff --git a/crates/napi/src/env.rs b/crates/napi/src/env.rs index 1d225086..3713fbc9 100644 --- a/crates/napi/src/env.rs +++ b/crates/napi/src/env.rs @@ -273,6 +273,7 @@ impl Env { )) } + #[deprecated(since = "3.0.0", note = "Use `BufferSlice::from_data` instead")] /// This API allocates a node::Buffer object and initializes it with data backed by the passed in buffer. /// /// While this is still a fully-supported data structure, in most cases using a TypedArray will suffice. @@ -324,6 +325,7 @@ impl Env { )) } + #[deprecated(since = "3.0.0", note = "Use `BufferSlice::from_external` instead")] /// # Safety /// Mostly the same with `create_buffer_with_data` /// @@ -361,15 +363,8 @@ impl Env { let status = sys::napi_create_external_buffer( self.0, length, - data as *mut c_void, - Some( - raw_finalize_with_custom_callback:: - as unsafe extern "C" fn( - env: sys::napi_env, - finalize_data: *mut c_void, - finalize_hint: *mut c_void, - ), - ), + data.cast(), + Some(raw_finalize_with_custom_callback::), hint_ptr.cast(), &mut raw_value, ); @@ -418,6 +413,7 @@ impl Env { Ok(0) } + #[deprecated(since = "3.0.0", note = "Use `BufferSlice::copy_from` instead")] /// This API allocates a node::Buffer object and initializes it with data copied from the passed-in buffer. /// /// While this is still a fully-supported data structure, in most cases using a TypedArray will suffice. @@ -1392,7 +1388,7 @@ impl Env { } } -/// This function could be used for `create_buffer_with_borrowed_data` and want do noting when Buffer finalized. +/// This function could be used for `BufferSlice::from_external` and want do noting when Buffer finalized. pub fn noop_finalize(_hint: Hint, _env: Env) {} unsafe extern "C" fn drop_buffer( @@ -1452,7 +1448,7 @@ unsafe extern "C" fn cleanup_env(hook_data: *mut c_void) { (cleanup_env_hook.hook)(cleanup_env_hook.data); } -unsafe extern "C" fn raw_finalize_with_custom_callback( +pub(crate) unsafe extern "C" fn raw_finalize_with_custom_callback( env: sys::napi_env, _finalize_data: *mut c_void, finalize_hint: *mut c_void, diff --git a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md index cc26b776..7f85dac9 100644 --- a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md +++ b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md @@ -394,8 +394,12 @@ Generated by [AVA](https://avajs.dev). ␊ export declare function createBigIntI64(): bigint␊ ␊ + export declare function createBufferSliceFromCopiedData(): Buffer␊ + ␊ export declare function createExternal(size: number): ExternalObject␊ ␊ + export declare function createExternalBufferSlice(): Buffer␊ + ␊ export declare function createExternalString(content: string): ExternalObject␊ ␊ export declare function createExternalTypedArray(): Uint32Array␊ @@ -485,6 +489,8 @@ Generated by [AVA](https://avajs.dev). ␊ export declare function getBuffer(): Buffer␊ ␊ + export declare function getBufferSlice(): Buffer␊ + ␊ export declare function getCwd(callback: (arg0: string) => void): void␊ ␊ export declare function getEmptyBuffer(): Buffer␊ diff --git a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.snap b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.snap index fa8304d9..97b1b401 100644 Binary files a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.snap and b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.snap differ diff --git a/examples/napi/__tests__/__snapshots__/values.spec.ts.snap b/examples/napi/__tests__/__snapshots__/values.spec.ts.snap index bc12e921..0cc62fed 100644 Binary files a/examples/napi/__tests__/__snapshots__/values.spec.ts.snap and b/examples/napi/__tests__/__snapshots__/values.spec.ts.snap differ diff --git a/examples/napi/__tests__/values.spec.ts b/examples/napi/__tests__/values.spec.ts index ce590f34..7528a0e5 100644 --- a/examples/napi/__tests__/values.spec.ts +++ b/examples/napi/__tests__/values.spec.ts @@ -190,6 +190,9 @@ import { StructuredKind, validateStructuredEnum, createArraybuffer, + getBufferSlice, + createExternalBufferSlice, + createBufferSliceFromCopiedData, } from '../index.cjs' import { test } from './test.framework.js' @@ -782,6 +785,9 @@ test('buffer', (t) => { t.is(buf.toString('utf-8'), 'Hello world') buf = appendBuffer(buf) t.is(buf.toString('utf-8'), 'Hello world!') + t.is(getBufferSlice().toString('utf-8'), 'Hello world') + t.is(createExternalBufferSlice().toString('utf-8'), 'Hello world') + t.is(createBufferSliceFromCopiedData().toString('utf-8'), 'Hello world') const a = getEmptyBuffer() const b = getEmptyBuffer() diff --git a/examples/napi/example.wasi-browser.js b/examples/napi/example.wasi-browser.js index 9e38f8db..932cbee9 100644 --- a/examples/napi/example.wasi-browser.js +++ b/examples/napi/example.wasi-browser.js @@ -339,34 +339,37 @@ function __napi_rs_initialize_modules(__napiInstance) { __napiInstance.exports['__napi_register__Pet_struct_341']?.() __napiInstance.exports['__napi_register__tsfn_in_either_342']?.() __napiInstance.exports['__napi_register__get_buffer_343']?.() - __napiInstance.exports['__napi_register__append_buffer_344']?.() - __napiInstance.exports['__napi_register__get_empty_buffer_345']?.() - __napiInstance.exports['__napi_register__get_empty_typed_array_346']?.() - __napiInstance.exports['__napi_register__convert_u32_array_347']?.() - __napiInstance.exports['__napi_register__create_external_typed_array_348']?.() - __napiInstance.exports['__napi_register__mutate_typed_array_349']?.() - __napiInstance.exports['__napi_register__deref_uint8_array_350']?.() - __napiInstance.exports['__napi_register__buffer_pass_through_351']?.() - __napiInstance.exports['__napi_register__array_buffer_pass_through_352']?.() - __napiInstance.exports['__napi_register__accept_slice_353']?.() - __napiInstance.exports['__napi_register__accept_arraybuffer_354']?.() - __napiInstance.exports['__napi_register__create_arraybuffer_355']?.() - __napiInstance.exports['__napi_register__u8_array_to_array_356']?.() - __napiInstance.exports['__napi_register__i8_array_to_array_357']?.() - __napiInstance.exports['__napi_register__u16_array_to_array_358']?.() - __napiInstance.exports['__napi_register__i16_array_to_array_359']?.() - __napiInstance.exports['__napi_register__u32_array_to_array_360']?.() - __napiInstance.exports['__napi_register__i32_array_to_array_361']?.() - __napiInstance.exports['__napi_register__f32_array_to_array_362']?.() - __napiInstance.exports['__napi_register__f64_array_to_array_363']?.() - __napiInstance.exports['__napi_register__u64_array_to_array_364']?.() - __napiInstance.exports['__napi_register__i64_array_to_array_365']?.() - __napiInstance.exports['__napi_register__accept_uint8_clamped_slice_366']?.() - __napiInstance.exports['__napi_register__accept_uint8_clamped_slice_and_buffer_slice_367']?.() - __napiInstance.exports['__napi_register__AsyncBuffer_impl_368']?.() - __napiInstance.exports['__napi_register__async_reduce_buffer_369']?.() - __napiInstance.exports['__napi_register__async_buffer_to_array_370']?.() - __napiInstance.exports['__napi_register__u_init8_array_from_string_371']?.() + __napiInstance.exports['__napi_register__get_buffer_slice_344']?.() + __napiInstance.exports['__napi_register__append_buffer_345']?.() + __napiInstance.exports['__napi_register__get_empty_buffer_346']?.() + __napiInstance.exports['__napi_register__create_external_buffer_slice_347']?.() + __napiInstance.exports['__napi_register__create_buffer_slice_from_copied_data_348']?.() + __napiInstance.exports['__napi_register__get_empty_typed_array_349']?.() + __napiInstance.exports['__napi_register__convert_u32_array_350']?.() + __napiInstance.exports['__napi_register__create_external_typed_array_351']?.() + __napiInstance.exports['__napi_register__mutate_typed_array_352']?.() + __napiInstance.exports['__napi_register__deref_uint8_array_353']?.() + __napiInstance.exports['__napi_register__buffer_pass_through_354']?.() + __napiInstance.exports['__napi_register__array_buffer_pass_through_355']?.() + __napiInstance.exports['__napi_register__accept_slice_356']?.() + __napiInstance.exports['__napi_register__accept_arraybuffer_357']?.() + __napiInstance.exports['__napi_register__create_arraybuffer_358']?.() + __napiInstance.exports['__napi_register__u8_array_to_array_359']?.() + __napiInstance.exports['__napi_register__i8_array_to_array_360']?.() + __napiInstance.exports['__napi_register__u16_array_to_array_361']?.() + __napiInstance.exports['__napi_register__i16_array_to_array_362']?.() + __napiInstance.exports['__napi_register__u32_array_to_array_363']?.() + __napiInstance.exports['__napi_register__i32_array_to_array_364']?.() + __napiInstance.exports['__napi_register__f32_array_to_array_365']?.() + __napiInstance.exports['__napi_register__f64_array_to_array_366']?.() + __napiInstance.exports['__napi_register__u64_array_to_array_367']?.() + __napiInstance.exports['__napi_register__i64_array_to_array_368']?.() + __napiInstance.exports['__napi_register__accept_uint8_clamped_slice_369']?.() + __napiInstance.exports['__napi_register__accept_uint8_clamped_slice_and_buffer_slice_370']?.() + __napiInstance.exports['__napi_register__AsyncBuffer_impl_371']?.() + __napiInstance.exports['__napi_register__async_reduce_buffer_372']?.() + __napiInstance.exports['__napi_register__async_buffer_to_array_373']?.() + __napiInstance.exports['__napi_register__u_init8_array_from_string_374']?.() } export const Animal = __napiModule.exports.Animal export const AnimalWithDefaultConstructor = __napiModule.exports.AnimalWithDefaultConstructor @@ -469,7 +472,9 @@ export const convertU32Array = __napiModule.exports.convertU32Array export const createArraybuffer = __napiModule.exports.createArraybuffer export const createBigInt = __napiModule.exports.createBigInt export const createBigIntI64 = __napiModule.exports.createBigIntI64 +export const createBufferSliceFromCopiedData = __napiModule.exports.createBufferSliceFromCopiedData export const createExternal = __napiModule.exports.createExternal +export const createExternalBufferSlice = __napiModule.exports.createExternalBufferSlice export const createExternalString = __napiModule.exports.createExternalString export const createExternalTypedArray = __napiModule.exports.createExternalTypedArray export const createObj = __napiModule.exports.createObj @@ -500,6 +505,7 @@ export const fibonacci = __napiModule.exports.fibonacci export const fnReceivedAliased = __napiModule.exports.fnReceivedAliased export const getBtreeMapping = __napiModule.exports.getBtreeMapping export const getBuffer = __napiModule.exports.getBuffer +export const getBufferSlice = __napiModule.exports.getBufferSlice export const getCwd = __napiModule.exports.getCwd export const getEmptyBuffer = __napiModule.exports.getEmptyBuffer export const getEmptyTypedArray = __napiModule.exports.getEmptyTypedArray diff --git a/examples/napi/example.wasi.cjs b/examples/napi/example.wasi.cjs index 02df12e1..7634e572 100644 --- a/examples/napi/example.wasi.cjs +++ b/examples/napi/example.wasi.cjs @@ -363,34 +363,37 @@ function __napi_rs_initialize_modules(__napiInstance) { __napiInstance.exports['__napi_register__Pet_struct_341']?.() __napiInstance.exports['__napi_register__tsfn_in_either_342']?.() __napiInstance.exports['__napi_register__get_buffer_343']?.() - __napiInstance.exports['__napi_register__append_buffer_344']?.() - __napiInstance.exports['__napi_register__get_empty_buffer_345']?.() - __napiInstance.exports['__napi_register__get_empty_typed_array_346']?.() - __napiInstance.exports['__napi_register__convert_u32_array_347']?.() - __napiInstance.exports['__napi_register__create_external_typed_array_348']?.() - __napiInstance.exports['__napi_register__mutate_typed_array_349']?.() - __napiInstance.exports['__napi_register__deref_uint8_array_350']?.() - __napiInstance.exports['__napi_register__buffer_pass_through_351']?.() - __napiInstance.exports['__napi_register__array_buffer_pass_through_352']?.() - __napiInstance.exports['__napi_register__accept_slice_353']?.() - __napiInstance.exports['__napi_register__accept_arraybuffer_354']?.() - __napiInstance.exports['__napi_register__create_arraybuffer_355']?.() - __napiInstance.exports['__napi_register__u8_array_to_array_356']?.() - __napiInstance.exports['__napi_register__i8_array_to_array_357']?.() - __napiInstance.exports['__napi_register__u16_array_to_array_358']?.() - __napiInstance.exports['__napi_register__i16_array_to_array_359']?.() - __napiInstance.exports['__napi_register__u32_array_to_array_360']?.() - __napiInstance.exports['__napi_register__i32_array_to_array_361']?.() - __napiInstance.exports['__napi_register__f32_array_to_array_362']?.() - __napiInstance.exports['__napi_register__f64_array_to_array_363']?.() - __napiInstance.exports['__napi_register__u64_array_to_array_364']?.() - __napiInstance.exports['__napi_register__i64_array_to_array_365']?.() - __napiInstance.exports['__napi_register__accept_uint8_clamped_slice_366']?.() - __napiInstance.exports['__napi_register__accept_uint8_clamped_slice_and_buffer_slice_367']?.() - __napiInstance.exports['__napi_register__AsyncBuffer_impl_368']?.() - __napiInstance.exports['__napi_register__async_reduce_buffer_369']?.() - __napiInstance.exports['__napi_register__async_buffer_to_array_370']?.() - __napiInstance.exports['__napi_register__u_init8_array_from_string_371']?.() + __napiInstance.exports['__napi_register__get_buffer_slice_344']?.() + __napiInstance.exports['__napi_register__append_buffer_345']?.() + __napiInstance.exports['__napi_register__get_empty_buffer_346']?.() + __napiInstance.exports['__napi_register__create_external_buffer_slice_347']?.() + __napiInstance.exports['__napi_register__create_buffer_slice_from_copied_data_348']?.() + __napiInstance.exports['__napi_register__get_empty_typed_array_349']?.() + __napiInstance.exports['__napi_register__convert_u32_array_350']?.() + __napiInstance.exports['__napi_register__create_external_typed_array_351']?.() + __napiInstance.exports['__napi_register__mutate_typed_array_352']?.() + __napiInstance.exports['__napi_register__deref_uint8_array_353']?.() + __napiInstance.exports['__napi_register__buffer_pass_through_354']?.() + __napiInstance.exports['__napi_register__array_buffer_pass_through_355']?.() + __napiInstance.exports['__napi_register__accept_slice_356']?.() + __napiInstance.exports['__napi_register__accept_arraybuffer_357']?.() + __napiInstance.exports['__napi_register__create_arraybuffer_358']?.() + __napiInstance.exports['__napi_register__u8_array_to_array_359']?.() + __napiInstance.exports['__napi_register__i8_array_to_array_360']?.() + __napiInstance.exports['__napi_register__u16_array_to_array_361']?.() + __napiInstance.exports['__napi_register__i16_array_to_array_362']?.() + __napiInstance.exports['__napi_register__u32_array_to_array_363']?.() + __napiInstance.exports['__napi_register__i32_array_to_array_364']?.() + __napiInstance.exports['__napi_register__f32_array_to_array_365']?.() + __napiInstance.exports['__napi_register__f64_array_to_array_366']?.() + __napiInstance.exports['__napi_register__u64_array_to_array_367']?.() + __napiInstance.exports['__napi_register__i64_array_to_array_368']?.() + __napiInstance.exports['__napi_register__accept_uint8_clamped_slice_369']?.() + __napiInstance.exports['__napi_register__accept_uint8_clamped_slice_and_buffer_slice_370']?.() + __napiInstance.exports['__napi_register__AsyncBuffer_impl_371']?.() + __napiInstance.exports['__napi_register__async_reduce_buffer_372']?.() + __napiInstance.exports['__napi_register__async_buffer_to_array_373']?.() + __napiInstance.exports['__napi_register__u_init8_array_from_string_374']?.() } module.exports.Animal = __napiModule.exports.Animal module.exports.AnimalWithDefaultConstructor = __napiModule.exports.AnimalWithDefaultConstructor @@ -493,7 +496,9 @@ module.exports.convertU32Array = __napiModule.exports.convertU32Array module.exports.createArraybuffer = __napiModule.exports.createArraybuffer module.exports.createBigInt = __napiModule.exports.createBigInt module.exports.createBigIntI64 = __napiModule.exports.createBigIntI64 +module.exports.createBufferSliceFromCopiedData = __napiModule.exports.createBufferSliceFromCopiedData module.exports.createExternal = __napiModule.exports.createExternal +module.exports.createExternalBufferSlice = __napiModule.exports.createExternalBufferSlice module.exports.createExternalString = __napiModule.exports.createExternalString module.exports.createExternalTypedArray = __napiModule.exports.createExternalTypedArray module.exports.createObj = __napiModule.exports.createObj @@ -524,6 +529,7 @@ module.exports.fibonacci = __napiModule.exports.fibonacci module.exports.fnReceivedAliased = __napiModule.exports.fnReceivedAliased module.exports.getBtreeMapping = __napiModule.exports.getBtreeMapping module.exports.getBuffer = __napiModule.exports.getBuffer +module.exports.getBufferSlice = __napiModule.exports.getBufferSlice module.exports.getCwd = __napiModule.exports.getCwd module.exports.getEmptyBuffer = __napiModule.exports.getEmptyBuffer module.exports.getEmptyTypedArray = __napiModule.exports.getEmptyTypedArray diff --git a/examples/napi/index.cjs b/examples/napi/index.cjs index 85e3afa7..013ea1da 100644 --- a/examples/napi/index.cjs +++ b/examples/napi/index.cjs @@ -462,7 +462,9 @@ module.exports.convertU32Array = nativeBinding.convertU32Array module.exports.createArraybuffer = nativeBinding.createArraybuffer module.exports.createBigInt = nativeBinding.createBigInt module.exports.createBigIntI64 = nativeBinding.createBigIntI64 +module.exports.createBufferSliceFromCopiedData = nativeBinding.createBufferSliceFromCopiedData module.exports.createExternal = nativeBinding.createExternal +module.exports.createExternalBufferSlice = nativeBinding.createExternalBufferSlice module.exports.createExternalString = nativeBinding.createExternalString module.exports.createExternalTypedArray = nativeBinding.createExternalTypedArray module.exports.createObj = nativeBinding.createObj @@ -493,6 +495,7 @@ module.exports.fibonacci = nativeBinding.fibonacci module.exports.fnReceivedAliased = nativeBinding.fnReceivedAliased module.exports.getBtreeMapping = nativeBinding.getBtreeMapping module.exports.getBuffer = nativeBinding.getBuffer +module.exports.getBufferSlice = nativeBinding.getBufferSlice module.exports.getCwd = nativeBinding.getCwd module.exports.getEmptyBuffer = nativeBinding.getEmptyBuffer module.exports.getEmptyTypedArray = nativeBinding.getEmptyTypedArray diff --git a/examples/napi/index.d.cts b/examples/napi/index.d.cts index da65031c..7178ae68 100644 --- a/examples/napi/index.d.cts +++ b/examples/napi/index.d.cts @@ -384,8 +384,12 @@ export declare function createBigInt(): bigint export declare function createBigIntI64(): bigint +export declare function createBufferSliceFromCopiedData(): Buffer + export declare function createExternal(size: number): ExternalObject +export declare function createExternalBufferSlice(): Buffer + export declare function createExternalString(content: string): ExternalObject export declare function createExternalTypedArray(): Uint32Array @@ -475,6 +479,8 @@ export declare function getBtreeMapping(): Record export declare function getBuffer(): Buffer +export declare function getBufferSlice(): Buffer + export declare function getCwd(callback: (arg0: string) => void): void export declare function getEmptyBuffer(): Buffer diff --git a/examples/napi/src/enum.rs b/examples/napi/src/enum.rs index cb85d315..8d8c8921 100644 --- a/examples/napi/src/enum.rs +++ b/examples/napi/src/enum.rs @@ -1,5 +1,6 @@ /// default enum values are continuos i32s start from 0 #[napi] +#[derive(Debug, Clone, Copy)] pub enum Kind { /// Barks Dog, diff --git a/examples/napi/src/typed_array.rs b/examples/napi/src/typed_array.rs index bff1aef9..003d3a2c 100644 --- a/examples/napi/src/typed_array.rs +++ b/examples/napi/src/typed_array.rs @@ -5,6 +5,11 @@ fn get_buffer() -> Buffer { String::from("Hello world").as_bytes().into() } +#[napi] +fn get_buffer_slice(env: &Env) -> Result { + BufferSlice::from_data(env, String::from("Hello world").as_bytes().to_vec()) +} + #[napi] fn append_buffer(buf: Buffer) -> Buffer { let mut buf = Vec::::from(buf); @@ -17,6 +22,25 @@ fn get_empty_buffer() -> Buffer { vec![].into() } +#[napi] +pub fn create_external_buffer_slice(env: &Env) -> Result { + let mut data = String::from("Hello world").as_bytes().to_vec(); + let data_ptr = data.as_mut_ptr(); + let len = data.len(); + // Mock the ffi data that not managed by Rust + std::mem::forget(data); + unsafe { + BufferSlice::from_external(env, data_ptr, len, data_ptr, |ptr, _| { + std::mem::drop(Vec::from_raw_parts(ptr, len, len)); + }) + } +} + +#[napi] +pub fn create_buffer_slice_from_copied_data(env: &Env) -> Result { + BufferSlice::copy_from(env, String::from("Hello world").as_bytes()) +} + #[napi] fn get_empty_typed_array() -> Uint8Array { vec![].into()