Wasm-bindgen: Should lifetimes on JS values be supported

Created on 8 Jul 2018  路  1Comment  路  Source: rustwasm/wasm-bindgen

This first came up on #419, but one web API looks (sort of) like this:

#[wasm_bindgen]
extern {
    pub type ImageData;

    #[wasm_bindgen(constructor)]
    pub fn new(arr: &[u8], width: u32, height: u32) -> ImageData;
}

Here we're creating an ImageData while also passing a buffer of memory to its contructor. Presumably an ImageData retains a handle to the array passed in to later get rendered, which means that the lifetime of the ImageData instance produced is actually tied to the &[u8] passed in.

Normally in Rust this would be expressed through lifetimes, something like:

#[wasm_bindgen]
extern {
    pub type ImageData<'arr>;

    #[wasm_bindgen(constructor)]
    pub fn new(arr: &[u8], width: u32, height: u32) -> ImageData<'arr>;
}

but that's not supported by #[wasm_bindgen] today!

Should we somehow add support for these lifetimes? Or would this perhaps make web APIs too difficult to use? Should we instead leave-as is where you probably won't get a segfault but you'd get weird results sometimes?

Most helpful comment

I find that the most natural way to expose lifetimes to JS is to take a JS callback and say "the data passed to this callback may only be used while the call is active". This is not always super Rust-y, and not always applicable, but it is generally clear how to use the thing correctly from the JS side.

When JS owns something that borrows something else, it gets more difficult.

At the end of the day, FFI'ing with JS is always going to be unsafe, but our goal is to make the Rust side correct and easy. JS doesn't have borrowck, so lifetimes obviously can't improve the JS side, but they can improve the Rust side, and therefore are worthy of pursuit.

>All comments

I find that the most natural way to expose lifetimes to JS is to take a JS callback and say "the data passed to this callback may only be used while the call is active". This is not always super Rust-y, and not always applicable, but it is generally clear how to use the thing correctly from the JS side.

When JS owns something that borrows something else, it gets more difficult.

At the end of the day, FFI'ing with JS is always going to be unsafe, but our goal is to make the Rust side correct and easy. JS doesn't have borrowck, so lifetimes obviously can't improve the JS side, but they can improve the Rust side, and therefore are worthy of pursuit.

Was this page helpful?
0 / 5 - 0 ratings