Search code examples
rustwasm-bindgen

Wouldnt ManuallyDrop without drop call cause memory leak?


I am going through wasm-bindgen guide and i came across the glue code it generates for interacting between js and rust. A reference to a value is passed from js to rust. Rust has to wrap it in ManuallyDrop so that it wont call the Drop implemented on JsValue.

pub fn foo(a: &JsValue) {
    // ...
}

#[export_name = "foo"]
pub extern "C" fn __wasm_bindgen_generated_foo(arg0: u32) {
    let arg0 = unsafe {
        ManuallyDrop::new(JsValue::__from_idx(arg0))
    };
    let arg0 = &*arg0;
    foo(arg0);
}

But I do not see a ManuallyDrop::drop being called on arg0 . So would the JsValuewrapped in ManuallyDrop be dropped unless the ManuallyDrop::drop(arg0) function is called? Wouldnt it cause a memory leak?


Solution

  • ManuallyDrop does not stop the inner value from being destroyed. It only stops drop from being called. Consider a Vec:

    pub struct Vec<T> {
        ptr: *mut T,
        cap: usize,
        len: usize,
    }
    

    The fields ptr, cap, and len will still be destroyed even when wrapped by ManuallyDrop. However, any dynamic resources managed (in this case the data referenced by ptr) will not be released since drop is not called.

    Since JsValue simply holds a u32, no leak will occur on the Rust-side. And since the glue code ensures proper cleanup for &JsValue arguments, no memory is leaked on the Javascript-side.