rustwasm / wasm-bindgen

Facilitating high-level interactions between Wasm modules and JavaScript
https://rustwasm.github.io/docs/wasm-bindgen/
Apache License 2.0
7.75k stars 1.07k forks source link

`WebSocket::set_onopen` should take a FnOnce? #2786

Open gcoakes opened 2 years ago

gcoakes commented 2 years ago

WebSocket::set_onopen

It appears that we have too strict of a trait on WebSocket::set_onopen for the callback. The callback should only ever be called once, so can we relax that? I'm having to workaround the compiler thinking that my moved values are going to be used after move. i.e.:

let opened_barrier = Arc::new(Barrier::new(2));
let closure_barrier = opened_barrier.clone();
let onopen = Closure::wrap(Box::new(move |_| {
    // This closure should really only be called once, but web-sys requires
    // FnMut for the callback. So, we need to tell the compilers that the
    // barrier owned by the spawn_local task is distinct.
    let task_barrier = closure_barrier.clone();
    spawn_local(async move {
        task_barrier.wait().await;
    })
}) as Box<dyn FnMut(JsValue)>);
ws.set_onopen(Some(onopen.as_ref().unchecked_ref()));
onopen.forget();
alexcrichton commented 2 years ago

All web-sys bindings are automatically generated from the WebIDL and I don't think that WebIDL has a way of saying that a callback will be invoked at most once.