State of WebAssembly in Rust

Rust is being praised as an excellent choice for its WebAssembly support, and it was one of the reasons, I've decided to start learning Rust. Sadly, the reality seems much worse than it is advertised unless I am missing something. There are three potential options.

  • wasm32-unknown-emscripten
    It seems it is not supported anymore. It was broken a year and a half ago.
  • wasm32-unknown-unknown
    Sadly, std is stubbed with errors and panics. It makes using third-party crates almost impossible unless they support no_std. It also makes writing code more difficult as it limits what is available. There are also other issues like no source code map support that exist in emscripten, and a lot of small issues reported for wasm-pack and wasm-bindgen that can be annoying sometimes.
  • wasm32-wasi
    The most promising one, because it supports std, and it allows to provide a custom WASI runtime. Unfortunately, wasm-bindgen removed support for it, so there is no way to call Rust from JS. wasm-pack also does not support it.

These problems limit Rust usage in web only to a small set of problems. What's your take on it?

I think you are missing something.

You aren't restricted to no_std with wasm32-unknown-unknown. It's just that any functionality which requires an OS (i.e. the std::fs, std::env, and std::process modules) will unconditionally return errors.

For access to JavaScript and browser APIs, see the js-sys and web-sys crates.

It should be noted that the main use case for wasi-std is being able to run WebAssembly programs directly on the host (i.e. not in the browser).

This is what the WASI proposal says about itself:

WASI stands for WebAssembly System Interface. It's an API designed by the Wasmtime project that provides access to several operating-system-like features, including files and filesystems, Berkeley sockets, clocks, and random numbers, that we'll be proposing for standardization.

It's designed to be independent of browsers, so it doesn't depend on Web APIs or JS, and isn't limited by the need to be compatible with JS. And it has integrated capability-based security, so it extends WebAssembly's characteristic sandboxing to include I/O.

This is in contrast with wasm-bindgen, which is is only designed to make it easier to communicate with JavaScript from a JavaScript environment (i.e. the browser or node.js).

Similarly, wasm-pack lets your Rust code (compiled to WebAssembly) participate in the NPM ecosystem.

If you are wondering why wasm-bindgen and wasm-pack don't support working outside of a JavaScript environment it's because that's not what they are designed to do.

As someone who's company builds heavily on top of WebAssembly and Rust (we build on the wasmer runtime), I believe that Rust has a much nicer WebAssembly story than alternatives like C.

A non-trivial part of using WebAssembly is just getting your code to build (and not just your code, but 3rd party dependencies that weren't originally intended for WebAssembly), and with Rust it Just Works.

I'm curious what makes you say Rust isn't suitable for use the web because my experience has been quite the opposite... You mention you are only just starting to learn Rust, so what resources have you been using? Have you seen the Rust and WebAssembly book?

4 Likes

Thanks for your reply @Michael-F-Bryan. It is valuable to see a different perspective.

True, but you don't get any warnings when you use these modules or you use a crate that is using them, and they are used a lot. So that's not the best experience, and if you need these modules, you don't have a way to stub them like in emscripten or wasi.

One example, I was facing was with sled, the crate compiles, but it uses time, so it crashes at runtime. WASM Support · Issue #1112 · spacejam/sled · GitHub
The discussion in the issue is also interesting. It is not easy for them to resolve it, because they would have force users to pass time from outside, and that would make their API clunky.

I am aware, I was interested in wasi mainly due to the fact it has libc and os modules, and it allowed me to compile creates I wanted to use. Ideally, I would use other targets.

If you build on the wasmer runtime, I assume you use wasi, and you are not interested in JS bindings. In that case, I agree, the experience is great. I've played with wasi, and I liked it, but I want to call my Rust code from JavaScript.

It works only if you write code that does not depend on C and is not using any os modules or if you don't need JavaScript bindings (wasi target).

This is very limiting, not to mention it took me some time to find all these problems because they are not documented anywhere. They are in GitHub issues and what makes it even more confusing is some of them are regressions, so you find old tutorial mentions things that are not working anymore (wasm-bindgen in wasi and usage of emscripten).

This is different to C/C++ where you have Emscripten that works that emulates almost all system calls, and it gives you flexibility to replace them with your own behaviour (e.g. you can provide your own file system).

I've finished the book, and I started creating projects with third-party crates, and sadly, things don't work as I was expecting. The first attempt was using wasm32-unknown-unknown, because that's what is recommended everywhere, but I've discovered crates either do not compile (usually if they have some C) or they panic at runtime. After that I've tried wasm32-unknown-emscripten that just does not work. The last attempt was wasm32-wasi that made me very excited, but in the end I was unable to generate bindings, so it was not very helpful.

Yes, I've read this book, but it focuses on the basics, and it does not explore limitations too much. There is a chapter that talks a bit about what is supported, but it is basically saying what I wrote.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.