-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Into<JsValue>
for Vec
#3630
Conversation
Is there any progress here? This would be a fantastic feature |
Something I was always wondering about in wasm-bindgen is why JsValue conversions can't just reuse the ABI representation instead of adding lots of new intrinsics. For example, it's already possible to implement any such conversions as #[wasm_bindgen]
extern {
#[wasm_bindgen(js_name = Object)] // using Object(x) as just an identity function for `x=>x`
fn convert(values: Vec<u32>) -> JsValue;
} It should be possible to generate similar stubs generically for arbitrary types, without resorting to |
Any updates on this? |
This means that `Vec`s can now be returned from `async` functions. Fixes rustwasm#3155. I had to add a new `VectorIntoJsValue` trait, since similarly to `VectorIntoWasmAbi` the orphan rule won't let us directly implement `From<Vec<T>>` for `JsValue` outside of `wasm-bindgen`.
515baae
to
ab75f75
Compare
I was holding out on merging this until I got around to properly benchmarking whether the current approach or the copy-into-a- |
@Liamolucko thank you so much for implementing this! I'm currently trying it out and can't seem to get it working. I wonder what I'm missing. Here's my cargo:
and my lib
And rust complains with
|
The underlying problem going on there is that you're ending up depending on two different versions of The proper way to switch to a git version of [package]
name = "hui"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
wasm-bindgen = "*"
wasm-bindgen-futures = "*"
[patch.crates-io]
wasm-bindgen = { git = "https://github.com/rustwasm/wasm-bindgen" } As for why you got that error, it's due to a weird interaction with |
Thanks @Liamolucko! Awesome explanation and not so obvious. I wouldn't found that issue without your help. Works great! |
@Liamolucko // this doesn't work
#[wasm_bindgen]
pub async fn test_wait_vec() -> Vec<Data> //the trait `JsObject` is not implemented for `Data`, which is required by `Vec<Data>: wasm_bindgen::describe::WasmDescribe`
{
vec![Data::new()]
}
// This works
#[wasm_bindgen]
pub async fn test_wait() -> Data {
Data::new()
}
#[derive(Serialize, Deserialize, Tsify)]
#[into_wasm_abi]
pub struct Data {
pub time: SystemTime,
pub map: HashMap<Test, InnerData>,
}
impl Into<JsValue> for Data {
fn into(self) -> JsValue {
serde_wasm_bindgen::to_value(&self).unwrap()
}
}
impl VectorIntoJsValue for Data {
fn vector_into_jsvalue(vector: Box<[Data]>) -> JsValue {
wasm_bindgen::__rt::js_value_vector_into_jsvalue(vector)
}
} The error is in the comment. When I implement any combination of the following traits below... impl WasmDescribeVector for Data {
fn describe_vector() {
inform(VECTOR);
Data::describe();
}
}
impl VectorIntoJsValue for Data {
fn vector_into_jsvalue(vector: Box<[Data]>) -> JsValue {
wasm_bindgen::__rt::js_value_vector_into_jsvalue(vector)
}
}
impl VectorIntoWasmAbi for Data {
type Abi = WasmSlice;
fn vector_into_abi(vector: Box<[Self]>) -> WasmSlice {
let jsvaluevec: Box<[JsValue]> = vector
.iter()
.map(|x| serde_wasm_bindgen::to_value(&x).unwrap())
.collect();
JsValue::vector_into_abi(jsvaluevec)
}
} I get a different error: error: import of Thank you for your time! :) |
From a quick glance it looks like this would be related to #3919? |
This means that
Vec
s can now be returned fromasync
functions.Fixes #3155.
I had to add a new
VectorIntoJsValue
trait, since similarly toVectorIntoWasmAbi
the orphan rule won't let us directly implementFrom<Vec<T>>
forJsValue
outside ofwasm-bindgen
.I did some quick benchmarking, and it seems like the copy-into-a-new-
Vec
approach used to returnVec
s from synchronous functions is faster:So it might be a good idea to later change this to use a similar implementation. However I haven't checked if these results are the same in other JS runtimes so take that with a grain of salt.