Meta: This is not an RFC as I don’t believe the change needs one. Instead it is just a proposal and if neccessary parties agree on it, we should implement it. If you disagree, see this as a pre-RFC. I’m open to opening an RFC :).
The current standard library and the
wasm32-unknown-unknown target has most of its functionality stubbed out.
There is no pthreads support by wasm yet, so some functionality has to remain stubbed out for unknown periods of time. But it is possible to provide support for other functionality, like
println!, panic messages, or obtaining the time, with current Web APIs.
These functionalities all require us to call into JS however, and here is the problem: The unknown target has no official functionality where crates can say “these js functions need to be provided as imports”.
js! macro by the
stdweb crate provides the needed functionality: it allows Rust code to specify the js code it needs.
cargo-web then comines all the js code of the used Rust crates.
The way how I understand
stdweb achieves this is by putting the js code as string literals into the generated web assembly file, and
cargo-web parses the web assembly file and extracts the literals.
Resulting story for users
println! and other basic functionalities provided by std will work like on other targets, you can just use them.
Maybe in the future cargo itself can provide support but I want to keep my proposal minimal, so for the time being you’d be required to use
cargo-web if you want to use std togethe with the
wasm32-unknown-unknown target. cargo doc, cargo check etc. should all work without
If you know of any use cases where you want
std but don’t want it to have working functionality, please speak up! Then we can push the current stubbed-out but dependency free std to crates.io.
This move will help to establish
cargo-web as standard tool. This allows third party OS abstraction crates like rand or glutin to rely on its presence and use the
js! macro themselves to get e.g. seeding from js. I think this is the most important benefit of my proposal.
Basic idea: std should be using the
js! macro itself to provide support for
Changes for stdweb:
The main functionality of the js macro seems to be provided through the webcore module. Therefore, I think the webcore module should be factored out of stdweb into a separate crate/module that only depends on std itself. stdweb itself would then depend on that crate.
Changes for upstream Rust
There are two alternatives here: either, add webcore to the sysroot as full crate, and do
extern crate webcore; in std’s lib.rs, or use it as non-public submodule of std. I guess with both proposals you’d include webcore as a submodule of the tree.
The two approaches each have their own advantages and disadvantages.
extern crate webcore;requires webcore to be
#![no_std]and webcore is not able to use functionality from std.
- the submodule approach is a bit more ugly
If its possible to make webcore not use std, one should go with the extern crate route.
webcore would always remain an implementation detail of the standard library: you would still have to do
webcore = ... or
stdweb = ... inside your Cargo.toml if you wanted to use the js macro.
Once this is done, the test runners should be updated to use cargo-web instead of cargo.
Creation of embedding specific targets
As @rpjohnst and @shepmaster suggest, we should create several targets based on wasm32 for different environments, that each differ in their libstd but are otherwise unchanged. E.g.
wasm32-rust-web for client side usage in web browsers,
wasm32-rust-node for usage with node.js. “non-web embeddings” (plugin engines for example) could continue usage of the
I suggest we start with a
Use by js templating tools
There are templating tools like webpack in the js world you can use to create client side artifacts. These tools should now use cargo-web instead of cargo and include the js emitted by cargo-web into their process.