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!