fix(napi): drop buffer inner data only when Reference count is 0
This commit is contained in:
parent
661b418eb6
commit
bffc49f11a
2 changed files with 18 additions and 8 deletions
|
@ -1,5 +1,6 @@
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use std::ffi::c_void;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
@ -20,9 +21,9 @@ thread_local! {
|
||||||
/// So it is safe to use it in `async fn`, the `&[u8]` under the hood will not be dropped until the `drop` called.
|
/// So it is safe to use it in `async fn`, the `&[u8]` under the hood will not be dropped until the `drop` called.
|
||||||
/// Clone will create a new `Reference` to the same underlying `JavaScript Buffer`.
|
/// Clone will create a new `Reference` to the same underlying `JavaScript Buffer`.
|
||||||
pub struct Buffer {
|
pub struct Buffer {
|
||||||
data_reference: Option<Arc<()>>,
|
pub(crate) data_reference: Option<Arc<()>>,
|
||||||
inner: &'static mut [u8],
|
pub(crate) inner: &'static mut [u8],
|
||||||
capacity: usize,
|
pub(crate) capacity: usize,
|
||||||
raw: Option<(sys::napi_ref, sys::napi_env)>,
|
raw: Option<(sys::napi_ref, sys::napi_env)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,13 +182,14 @@ impl ToNapiValue for Buffer {
|
||||||
// the same data pointer if it's 0x0.
|
// the same data pointer if it's 0x0.
|
||||||
unsafe { sys::napi_create_buffer(env, len, ptr::null_mut(), &mut ret) }
|
unsafe { sys::napi_create_buffer(env, len, ptr::null_mut(), &mut ret) }
|
||||||
} else {
|
} else {
|
||||||
|
let val_ptr = val.inner.as_mut_ptr();
|
||||||
unsafe {
|
unsafe {
|
||||||
sys::napi_create_external_buffer(
|
sys::napi_create_external_buffer(
|
||||||
env,
|
env,
|
||||||
len,
|
len,
|
||||||
val.inner.as_mut_ptr() as *mut _,
|
val_ptr as *mut c_void,
|
||||||
Some(drop_buffer),
|
Some(drop_buffer),
|
||||||
Box::into_raw(Box::new((len, val.capacity))) as *mut _,
|
Box::into_raw(Box::new(val)) as *mut c_void,
|
||||||
&mut ret,
|
&mut ret,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub use callback_info::*;
|
pub use callback_info::*;
|
||||||
pub use ctor::ctor;
|
pub use ctor::ctor;
|
||||||
|
@ -66,7 +67,6 @@ pub unsafe extern "C" fn drop_buffer(
|
||||||
finalize_data: *mut c_void,
|
finalize_data: *mut c_void,
|
||||||
finalize_hint: *mut c_void,
|
finalize_hint: *mut c_void,
|
||||||
) {
|
) {
|
||||||
let length_ptr = finalize_hint as *mut (usize, usize);
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
js_values::BUFFER_DATA.with(|buffer_data| {
|
js_values::BUFFER_DATA.with(|buffer_data| {
|
||||||
|
@ -75,7 +75,15 @@ pub unsafe extern "C" fn drop_buffer(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
let (length, cap) = *Box::from_raw(length_ptr);
|
let buf = Box::from_raw(finalize_hint as *mut Buffer);
|
||||||
mem::drop(Vec::from_raw_parts(finalize_data as *mut u8, length, cap));
|
if let Some(data_reference) = buf.data_reference.as_ref() {
|
||||||
|
if Arc::strong_count(data_reference) == 0 {
|
||||||
|
mem::drop(Vec::from_raw_parts(
|
||||||
|
finalize_data as *mut u8,
|
||||||
|
buf.inner.len(),
|
||||||
|
buf.capacity,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue