rustwasm / wasm-bindgen

Facilitating high-level interactions between Wasm modules and JavaScript

Home Page:https://rustwasm.github.io/docs/wasm-bindgen/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Allow closures to take by reference

zopsicle opened this issue · comments

Motivation

Currently the following fails to compile:

#[wasm_bindgen]
struct S
{
    x: X,
}

Closure::<dyn Fn(&S)>::new(|s| f(&s.x))

To work around this, one can do this:

#[wasm_bindgen]
struct S
{
    #[wasm_bindgen(getter_with_clone)]
    pub inner: SInner,
}

#[derive(Clone)]
#[wasm_bindgen]
struct SInner
{
    x: Rc<X>,
}

Closure::<dyn Fn(SInner)>::new(|s_inner| f(&s_inner.x))

which is less efficient and requires the caller (JavaScript) to access the inner field before calling the closure.

Proposed Solution

Allow closures to take by reference, just like global functions can.

Alternatives

Prohibit closures taking by reference, requiring workarounds such as additional indirections or possibly inefficient cloning.

Allow closures to take by clone. JavaScript would clone the value before passing it to the closure instead of consuming it. This would be like the above workaround but remove the need for an additional class and field access.

It appears that WasmClosure is implemented for functions that take one argument by reference, but IntoWasmClosure is not. 🤔

Apparently, using Closure::wrap instead of Closure::new, this works!