tsify icon indicating copy to clipboard operation
tsify copied to clipboard

Returning Vec<T> where T: IntoWasmAbi

Open bes opened this issue 1 year ago • 2 comments

Hello! Thanks for a great library!

In https://github.com/rustwasm/wasm-bindgen/pull/3554 (See also: https://github.com/rustwasm/wasm-bindgen/issues/111 ) the possibility to return a Vec<SomeType> where SomeType has #[wasm_bindgen] on it was introduced.

Later, in https://github.com/rustwasm/wasm-bindgen/issues/3692 @hillin asked why it wasn't possible to return a Vec<T> where T: IntoWasmAbi. I now have the exact same question. Unfortunately that issue was closed, and moved into this discussion https://github.com/rustwasm/wasm-bindgen/discussions/3697 where it received only one reply, from the question asker themself.

The answer was to create a newtype that itself is IntoWasmAbi and then return that:

#[derive(serde::Serialize, tsify::Tsify)]
#[tsify(into_wasm_abi)]
pub struct ThingCollection(Vec<Thing>);

pub fn get_numbers() -> ThingCollection {
   ThingCollection(vec![Thing(1), Thing(2), Thing(3)])
}

Which works, but now I have to have a number of newtypes that I don't want in my code.

I tried improving the situation by creating a generic version of that:

#[derive(serde::Serialize, tsify::Tsify)]
#[tsify(into_wasm_abi)]
pub struct GenericCollection<T: IntoWasmAbi>(Vec<T>);

#[wasm_bindgen(js_class = MyTypeHandle)]
struct MyType {
    #[wasm_bindgen(js_name = getThings)]
    pub fn get_things(&self) -> GenericCollection<Thing> {
        let things = ...;
        GenericCollection(things)
    }
}

Which kind of half-worked - the TS type was correctly generated, but the return value of the function lacked the generic type argument:

export type GenericCollection<T> = T[];

export class MyTypeHandle {
  free(): void;
  getThings(): GenericCollection;
}

So the question is, what's the solution here?

  • Get wasm-bindgen to implement support for Vec<T: IntoWasmAbi>?
  • Get tsify to put the correct generic argument on the ts return type (i.e. getThings(): GenericCollection<Thing>;)?
  • Live with the suboptimal solution?

bes avatar Feb 03 '24 16:02 bes

The problem seems to be that tsify needs to implement the VectorIntoWasmAbi and WasmDescribeVector traits. These are the traits that allow converting a Vec<T> into a JS array of Ts.

jmigual avatar May 21 '24 16:05 jmigual

The tsify-next crate added support for that recently. It might be reasonable to switch to that crate as this one seems unmaintained.

eneoli avatar Aug 05 '24 14:08 eneoli