Description
Over time wasm-bindgen
has picked up more features to follow the WebAssembly proposals, namely the interface types proposal. Additionally wasm-bindgen
has been used for new embeddings such as WASI! One of the major goals of interface types is to also help bring wasm code to many more places outside of the web browser.
Currently for this "outside the web browser" use case wasm-bindgen
is acting as Rust's implementation of interface types (to follow the standard), and I think that's likely to continue being the case into the future. Unfortunately though this causes a bit of an impedance mismatch!
- From the start
wasm-bindgen
was built for the web and assumes JS. Lots of functionality isn't available in standalone webassembly (almost none of the APIs onJsValue
, classes, etc) - Currently debug builds, by default, fail for the interface types target because they don't optimize out calls to
__wbindgen_throw
. There are no intrinsics with a standalone wasm file! - Restrictions on the web are not actually restrictions everywhere else. We support u64/i64 on the web by passing two i32 components, but Support for i64/u64 in interface types #1837 points out this is natively supported by all other runtimes.
Overall I think that to continue to faithfully pursue the standalone outside-the-web browser use case we'll want to do something about the current organization. I don't think this should be isolated to just the wasm32-wasi
target, but it should include it!
I would expect an organization where you still use #[wasm_bindgen]
-the-macro but if you're in a standalone environment you'd have a type like Anyref
instead of JsValue
. Additionally you would have no access to intrinsics in a standalone environment, unlike the JS environment. I think we'll want to tweak the features available in #[wasm_bindgen]
as well, where if you're in a standalone environment we require a module
for all imports and don't support any features like js_namespace
and such.
I sort of envision this happening by doing something like the following:
- Spilt out a
wasm-bindgen-core
crate. This crate defines theAnyref
type, uses zero intrinsics, and defines all the basic conversion traits. - Add a dependency from
wasm-bindgen-core
towasm-bindgen-macro
, and reexport it - The current
wasm-bindgen
crate would then depend onwasm-bindgen-core
, reexporting most of its functionality and layeringJsValue
on top ofAnyref
. - Update
wasm-bindgen-macro
with an off-by-defaultjs
feature (or something like that). When enabled this enables all the support for things likejs_namespace
and such. Thewasm-bindgen-core
crate would not turn this feature on, butwasm-bindgen
would - If necessary add a
js
feature towasm-bindgen-core
whichwasm-bindgen
would activate, which would tweak impls like the ABI of i64/u64.
The general user experience would then be that if you're using wasm-bindgen
today, nothing changes. For standalone use-cases though that do not intend on targeting the web specifically, you'd use the wasm-bindgen-core
crate. The wasm-bindgen-core
crate would statically ensure that you stay within what interface types are supported. This means no support for fancy types like closures (until they're added to the standard eventually). The hope here is that you can get errors in crate compilation long before you actually run the wasm-bindgen
CLI tool.
In any case I'm curious what others think of this strategy? Is wasm-bindgen
still an appropriate place for all this? Do others think that this should all be split out somehow? Should we send a PR tomorrow? (etc, etc)