Wasm-bindgen: Closure::once_into_js without static lifetime

Created on 17 Dec 2019  路  2Comments  路  Source: rustwasm/wasm-bindgen

I'm using yew with wasm-bindgen. I'm making various browser API calls that have callbacks. I'm using Closure::once_into_js to map the callbacks. The problem is it is forcing a static lifetime for the callback and that doesn't play well.

https://github.com/rustwasm/wasm-bindgen/blob/c564eb72b167ffd62088d87e7adbe14a58564a7a/src/closure.rs#L23-L24

Closure currently requires that the closures it's created with have the 'static lifetime in Rust for soundness reasons.

Would it be possible to remove the static lifetime requirement now?

enhancement

Most helpful comment

No, it is not possible. And it will never be possible, because JS callbacks are always called after the stack frame is gone, and therefore it is not safe to access stack references inside the Closure.

To workaround lifetime issues, it's normal to use Rc<RefCell<T>>, like this:

let state = Rc::new(RefCell::new(state));

let closure = {
    let state = state.clone();

    Closure::once_into_js(move |_| {
        let mut state = state.borrow_mut();

        // Access state in here...
    })
};

// Also access state out here...

This allows you to access the state in multiple places (inside and outside the closure, or in multiple different closures).

All 2 comments

No, it is not possible. And it will never be possible, because JS callbacks are always called after the stack frame is gone, and therefore it is not safe to access stack references inside the Closure.

To workaround lifetime issues, it's normal to use Rc<RefCell<T>>, like this:

let state = Rc::new(RefCell::new(state));

let closure = {
    let state = state.clone();

    Closure::once_into_js(move |_| {
        let mut state = state.borrow_mut();

        // Access state in here...
    })
};

// Also access state out here...

This allows you to access the state in multiple places (inside and outside the closure, or in multiple different closures).

Yes @Pauan is right in that it's not possible to have a non-'static closue in the JsValue returned, so I'm going to close this.

Was this page helpful?
0 / 5 - 0 ratings