refactor(napi): allow create BufferSlice from external data (#2263)

- also refactor the enum codegen, now we will not emit #[derive(Copy,
  Clone)] for the original enums.
- also refacotr the fn codegen, now #[napi] fn can accept env: &Env as
  argument, this is useful when the return type contains lifetime
This commit is contained in:
LongYinan 2024-09-19 22:22:33 +08:00 committed by GitHub
parent cea16807da
commit 521ef58f59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 320 additions and 81 deletions

View File

@ -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 {

View File

@ -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" {

View File

@ -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::<Case, Diagnostic>(match c.0.as_str() {

View File

@ -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<u8>`.
///
/// While this is still a fully-supported data structure, in most cases using a `Uint8Array` will suffice.
pub fn from_data<D: Into<Vec<u8>>>(env: &Env, data: D) -> Result<Self> {
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<T: 'scope, F: FnOnce(T, Env)>(
env: &Env,
data: *mut u8,
len: usize,
finalize_hint: T,
finalize_callback: F,
) -> Result<Self> {
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::<T, F>),
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<D: AsRef<[u8]>>(env: &Env, data: D) -> Result<Self> {
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<Buffer> {
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<Self> {
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,
)
};

View File

@ -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));
}
}

View File

@ -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::<Hint, Finalize>
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, Finalize>),
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: Hint, _env: Env) {}
unsafe extern "C" fn drop_buffer(
@ -1452,7 +1448,7 @@ unsafe extern "C" fn cleanup_env<T: 'static>(hook_data: *mut c_void) {
(cleanup_env_hook.hook)(cleanup_env_hook.data);
}
unsafe extern "C" fn raw_finalize_with_custom_callback<Hint, Finalize>(
pub(crate) unsafe extern "C" fn raw_finalize_with_custom_callback<Hint, Finalize>(
env: sys::napi_env,
_finalize_data: *mut c_void,
finalize_hint: *mut c_void,

View File

@ -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<number>
export declare function createExternalBufferSlice(): Buffer␊
export declare function createExternalString(content: string): ExternalObject<string>
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␊

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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<number>
export declare function createExternalBufferSlice(): Buffer
export declare function createExternalString(content: string): ExternalObject<string>
export declare function createExternalTypedArray(): Uint32Array
@ -475,6 +479,8 @@ export declare function getBtreeMapping(): Record<string, number>
export declare function getBuffer(): Buffer
export declare function getBufferSlice(): Buffer
export declare function getCwd(callback: (arg0: string) => void): void
export declare function getEmptyBuffer(): Buffer

View File

@ -1,5 +1,6 @@
/// default enum values are continuos i32s start from 0
#[napi]
#[derive(Debug, Clone, Copy)]
pub enum Kind {
/// Barks
Dog,

View File

@ -5,6 +5,11 @@ fn get_buffer() -> Buffer {
String::from("Hello world").as_bytes().into()
}
#[napi]
fn get_buffer_slice(env: &Env) -> Result<BufferSlice> {
BufferSlice::from_data(env, String::from("Hello world").as_bytes().to_vec())
}
#[napi]
fn append_buffer(buf: Buffer) -> Buffer {
let mut buf = Vec::<u8>::from(buf);
@ -17,6 +22,25 @@ fn get_empty_buffer() -> Buffer {
vec![].into()
}
#[napi]
pub fn create_external_buffer_slice(env: &Env) -> Result<BufferSlice> {
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> {
BufferSlice::copy_from(env, String::from("Hello world").as_bytes())
}
#[napi]
fn get_empty_typed_array() -> Uint8Array {
vec![].into()