fix(napi): should also delete the reference while dropping the Buffer
This commit is contained in:
parent
4279291f4b
commit
47de6301ee
6 changed files with 53 additions and 36 deletions
|
@ -67,6 +67,11 @@ macro_rules! impl_typed_array {
|
||||||
crate::check_status_or_throw!(
|
crate::check_status_or_throw!(
|
||||||
env,
|
env,
|
||||||
unsafe { sys::napi_reference_unref(env, ref_, &mut 0) },
|
unsafe { sys::napi_reference_unref(env, ref_, &mut 0) },
|
||||||
|
"Failed to unref Buffer reference in drop"
|
||||||
|
);
|
||||||
|
crate::check_status_or_throw!(
|
||||||
|
env,
|
||||||
|
unsafe { sys::napi_delete_reference(env, ref_) },
|
||||||
"Failed to delete Buffer reference in drop"
|
"Failed to delete Buffer reference in drop"
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -25,23 +25,27 @@ pub struct Buffer {
|
||||||
pub(crate) len: usize,
|
pub(crate) len: usize,
|
||||||
pub(crate) capacity: usize,
|
pub(crate) capacity: usize,
|
||||||
raw: Option<(sys::napi_ref, sys::napi_env)>,
|
raw: Option<(sys::napi_ref, sys::napi_env)>,
|
||||||
// use it as ref count
|
pub(crate) ref_count: Arc<()>,
|
||||||
pub(crate) drop_in_vm: Arc<()>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Buffer {
|
impl Drop for Buffer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some((ref_, env)) = self.raw {
|
if Arc::strong_count(&self.ref_count) == 1 {
|
||||||
check_status_or_throw!(
|
if let Some((ref_, env)) = self.raw {
|
||||||
env,
|
let mut ref_count = 0;
|
||||||
unsafe { sys::napi_reference_unref(env, ref_, &mut 0) },
|
check_status_or_throw!(
|
||||||
"Failed to unref Buffer reference in drop"
|
env,
|
||||||
);
|
unsafe { sys::napi_reference_unref(env, ref_, &mut ref_count) },
|
||||||
return;
|
"Failed to unref Buffer reference in drop"
|
||||||
}
|
);
|
||||||
|
check_status_or_throw!(
|
||||||
if Arc::strong_count(&self.drop_in_vm) == 1 {
|
env,
|
||||||
unsafe { Vec::from_raw_parts(self.inner.as_ptr(), self.len, self.capacity) };
|
unsafe { sys::napi_delete_reference(env, ref_) },
|
||||||
|
"Failed to delete Buffer reference in drop"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
unsafe { Vec::from_raw_parts(self.inner.as_ptr(), self.len, self.capacity) };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,24 +54,15 @@ impl Drop for Buffer {
|
||||||
// without synchronization. Also see the docs for the `AsMut` impl.
|
// without synchronization. Also see the docs for the `AsMut` impl.
|
||||||
unsafe impl Send for Buffer {}
|
unsafe impl Send for Buffer {}
|
||||||
|
|
||||||
impl Buffer {
|
impl Clone for Buffer {
|
||||||
pub fn clone(&mut self, env: &Env) -> Result<Self> {
|
fn clone(&self) -> Self {
|
||||||
let raw = if let Some((ref_, _)) = self.raw {
|
Self {
|
||||||
check_status!(
|
|
||||||
unsafe { sys::napi_reference_ref(env.0, ref_, &mut 0) },
|
|
||||||
"Failed to ref Buffer reference in Buffer::clone"
|
|
||||||
)?;
|
|
||||||
Some((ref_, env.0))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
Ok(Self {
|
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
len: self.len,
|
len: self.len,
|
||||||
capacity: self.capacity,
|
capacity: self.capacity,
|
||||||
raw,
|
raw: self.raw,
|
||||||
drop_in_vm: self.drop_in_vm.clone(),
|
ref_count: self.ref_count.clone(),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +90,7 @@ impl From<Vec<u8>> for Buffer {
|
||||||
len,
|
len,
|
||||||
capacity,
|
capacity,
|
||||||
raw: None,
|
raw: None,
|
||||||
drop_in_vm: Arc::new(()),
|
ref_count: Arc::new(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,7 +179,7 @@ impl FromNapiValue for Buffer {
|
||||||
len,
|
len,
|
||||||
capacity: len,
|
capacity: len,
|
||||||
raw: Some((ref_, env)),
|
raw: Some((ref_, env)),
|
||||||
drop_in_vm: Arc::new(()),
|
ref_count: Arc::new(()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,9 +222,16 @@ impl ToNapiValue for Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToNapiValue for &Buffer {
|
||||||
|
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
|
||||||
|
let buf = val.clone();
|
||||||
|
unsafe { ToNapiValue::to_napi_value(env, buf) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToNapiValue for &mut Buffer {
|
impl ToNapiValue for &mut Buffer {
|
||||||
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
|
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
|
||||||
let buf = val.clone(&Env::from(env))?;
|
let buf = val.clone();
|
||||||
unsafe { ToNapiValue::to_napi_value(env, buf) }
|
unsafe { ToNapiValue::to_napi_value(env, buf) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ pub unsafe extern "C" fn raw_finalize_unchecked<T: ObjectFinalize>(
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub unsafe extern "C" fn drop_buffer(
|
pub unsafe extern "C" fn drop_buffer(
|
||||||
_env: sys::napi_env,
|
_env: sys::napi_env,
|
||||||
finalize_data: *mut c_void,
|
#[allow(unused)] finalize_data: *mut c_void,
|
||||||
finalize_hint: *mut c_void,
|
finalize_hint: *mut c_void,
|
||||||
) {
|
) {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
|
|
|
@ -68,8 +68,6 @@ impl Task for AsyncBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
fn async_reduce_buffer(mut buf: Buffer, env: Env) -> Result<AsyncTask<AsyncBuffer>> {
|
fn async_reduce_buffer(buf: Buffer) -> Result<AsyncTask<AsyncBuffer>> {
|
||||||
Ok(AsyncTask::new(AsyncBuffer {
|
Ok(AsyncTask::new(AsyncBuffer { buf: buf.clone() }))
|
||||||
buf: buf.clone(&env)?,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ while (true) {
|
||||||
api.arrayBufferConvert(
|
api.arrayBufferConvert(
|
||||||
Uint8Array.from(Array.from({ length: 1024 * 10240 }).fill(1)),
|
Uint8Array.from(Array.from({ length: 1024 * 10240 }).fill(1)),
|
||||||
)
|
)
|
||||||
|
api.bufferPassThrough(Buffer.from('hello world'.repeat(1024 * 1024)))
|
||||||
|
api.arrayBufferPassThrough(Uint8Array.from('hello world'.repeat(1024 * 1024)))
|
||||||
if (i % 10 === 0) {
|
if (i % 10 === 0) {
|
||||||
await setTimeout(100)
|
await setTimeout(100)
|
||||||
displayMemoryUsageFromNode(initialMemoryUsage)
|
displayMemoryUsageFromNode(initialMemoryUsage)
|
||||||
|
|
|
@ -161,3 +161,13 @@ pub fn array_buffer_convert(array_buffer: Uint8Array) -> Uint8Array {
|
||||||
pub fn array_buffer_len() -> u32 {
|
pub fn array_buffer_len() -> u32 {
|
||||||
Uint8Array::new(vec![1; 1024 * 10240]).len() as u32
|
Uint8Array::new(vec![1; 1024 * 10240]).len() as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[napi]
|
||||||
|
pub fn buffer_pass_through(buffer: Buffer) -> Buffer {
|
||||||
|
buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
#[napi]
|
||||||
|
pub fn array_buffer_pass_through(array_buffer: Uint8Array) -> Uint8Array {
|
||||||
|
array_buffer
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue