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
#[wasm_bindgen(...)]
pragma to convert to plain Object instead of Class
#2645
Comments
Another use case from a real-world app: let events = js_sys::Object::new();
Reflect::set(&events, &"onReady".into(), on_ready.as_ref()).unwrap();
let config = js_sys::Object::new();
Reflect::set(&config, &"width".into(), &"100%".into()).unwrap();
Reflect::set(&config, &"events".into(), &events).unwrap(); This would be much cleaner: #[wasm_bindgen(as_object)]
struct Events{
#[wasm_bindgen(js_name = onReady)]
on_ready: Closure<dyn Fn()>, // or a reference or a `js_sys::Function` if possible
}
#[wasm_bindgen(as_object)]
struct Foo {
width: String,
events: Events,
} |
Hello there, any thoughts on this? |
@fosskers I think what you want is already possible with https://github.com/cloudflare/serde-wasm-bindgen. This crate is also linked from the wasm-bindgen docs. Still would be great to see this supported out-of-the-box. |
I do use that crate extensively already, although it seems to me that structs should be able to convert into JS objects natively (at least in the |
@fosskers Ah, yeah. Makes sense. |
This would be super useful for some of my current use-cases. |
https://github.com/hamza1311/ducktor is also another solution for this, though it falls apart when nested complex types are involved |
uniffi makes a useful distinction between structs and objects. At Tutao we are currently evaluating the possibility of using both uniffi and wasm-bindgen for using the same Rust SDK and this is a major roadblock. There are many cases where we want to pass plain objects into/from API calls. Something like ducktor but that also generates typescript types (without wrapper classes) would be ideal. It seems odd that something complicated like refcounted classes with prototype hierarchies is implemented but mapping of plain objects is a problem. |
We are doing this internally already when generating dictionary types from the WebIDL. See #3468 as well, where we want to move away from |
Motivation
APIs like https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connect expect to be passed Objects with specific fields. The following is currently possible:
And this
Foo
can be used as an argument to a bound JS function, but it seems that theFoo
is encoded as a class, and APIs that do runtime field sanity checking (like the one above) reject anything with any extra structure (fields, etc.) than what they expected.Proposed Solution
I propose that an option be added to the
#[wasm_bindgen]
macro, such as#[wasm_bindgen(as_object)]
, that would result in the implementations ofIntoWasmAbi
etc. encoding the Rust struct as a plain JS object. This would:JsValue::from_serde
orserde-wasm-bindgen
.Result
from calling the functions in (2).Foo
to be pulled back out of a bound JS function as the return value (maybe not possible?)Alternatives
As mentioned in point (2) above, the current workaround is to leave all arguments to bound JS functions as
JsValue
and write sugar functions over top of them than work in "Serde Land", first encoding via Serde into aJsValue
before passing it down.Unless, of course, I have completely misunderstood how the existing
#[wasm_bindgen]
macro works!The text was updated successfully, but these errors were encountered: