Notes on writing Rust-based Wasm

notes.brooklynzelenka.com

211 points by vinhnx 18 hours ago


mendyberger - 13 hours ago

Things are slowly getting better in wasm world.

The c-style interface of wasm is pretty limiting when designing higher level interfaces, which is why wasn-bindgen is required in the first place.

Luckily, Firefox is pushing an early proposal to expose all the web apis directly to wasm through a higher level interface based on the wasm component-model proposal.

See https://hacks.mozilla.org/2026/02/making-webassembly-a-first...

Twey - 10 hours ago

> FWIW I prefer `futures::lock::Mutex` on std, or `async_lock::Mutex` under no_std.

Async mutexes in Rust have so many footguns that I've started to consider them a code smell. See for example the one the Oxide project ran into [1]. IME there are relatively few cases where it makes sense to want to await a mutex asynchronously, and approximately none where it makes sense to hold a mutex over a yield point, which is why a lot of people turn to async mutexes despite advice to the contrary [2]. They are essentially incompatible with structured concurrency, but Rust async in general really wants to be structured in order to be able to play nicely with the borrow checker.

`shadow-rs` [3] bears mentioning as a prebuilt way to do some of the build info collection mentioned later in the post.

[1]: https://rfd.shared.oxide.computer/rfd/0609 [2]: https://docs.rs/tokio/latest/tokio/sync/struct.Mutex.html#wh... [3]: https://docs.rs/shadow-rs/latest/shadow_rs/

flohofwoe - 16 hours ago

This reads like the same problems as using Emscripten's embind for automatically generating C++ <=> JS bindings, and my advice would be "just don't do it".

It adds an incredible amount of complexity and bloat versus writing a proper hybrid C++/JS application where non-trivial work is happening in handwritten JS functions versus hopping across the JS/WASM boundary for every little setter/getter. It needs experience though to find just the right balance between what code should go on either side of the boundary.

Alternatively tunnel through a properly designed C API instead of trying to map C++ or Rust types directly to JS (e.g. don't attempt to pass complex C++/Rust objects across the boundary, there's simply too little overlap between the C++/Rust and JS type systems).

The automatic bindings approach makes much more sense for a C API than for a native API of a language with a huge 'semantic surface' like C++ or Rust.

comagoosie - 14 hours ago

A tool that's great to have in one's Rust/Wasm toolbelt is tsify[0] which has been handy in ensuring type-safety for plain ol' data.

Very handy to update serde data structure and see all the typescript errors that after recompiling.

[0]: https://github.com/madonoharu/tsify

pasxizeis - 13 hours ago

Tangential: I decided to write a Wasm parser (more precisely, a decoder the the Wasm binary format) from scratch, as a means to learn both Wasm and Rust[0].

It was the first time I was writing this sort of thing, but I found the spec very clear and well-written.

Fun fact: I was surprised when the test from a toy parser surfaced a real regression in version 3 of the spec[1], released roughly 4 months before.

[0] https://github.com/agis/wadec

[1] https://github.com/WebAssembly/spec/issues/2066

andai - 13 hours ago

Is anyone using WASM with GC languages? I think they added support for that in the last WASM, has that changed the landscape of available languages?

pjmlp - 9 hours ago

The advice regarding Rc<RefCell<T>>, Arc<Mutex<T>> is Gtk-rs all over again, until the clone!() came to be.

This was one of the things that has put me off, and ergonomics are still a subset for Rust Roadmap 2026.

tarun_anand - 13 hours ago

Interesting.. in case you want to see some MCP work with Rust/TS bindings - here is a real implementation I wrote sometime back

https://github.com/modelcontextprotocol/modelcontextprotocol...

https://github.com/modelcontextprotocol/rust-sdk/pull/183

larsnystrom - 16 hours ago

WASM is kind of like Java bytecode, right? A compilation target which requires a runtime? But better sandboxed?

Surac - 14 hours ago

I expected an article about writing code directly in wasm. Title is bit missleading

Decabytes - 16 hours ago

Yes wasm is basically a rust thing at this point unfortunately. And if you want to write a wasi preview 0.2 component, you need a bunch of rust tooling to do it properly

AyanamiKaine - 16 hours ago

I really hate wasm, not because of the idea or concept but because it gets bloated.

The first idea was computation heavy algorithms to be written in a language like C/C++/Rust and to be compiled to wasm.

Now it gets marketed as something to write sandboxed code/compontents for every language to be consumed by a wasm runtime.

Then there is the problem with the types of wasm. While it was seen to be something run on the web/browser. Its types are way more similar to rusts. For example strings in JS are fundamentally UTF-16 while wasm/rust is utf-8.

We need to constantly convert between them. I always hoped that wasm would simply allow for faster code on the web not here is my program completly sandboxed from the outside world you cant interact with other programs on the same machine.

phplovesong - 11 hours ago

Wasm is really cool. I imagine a runtime that competes with the likes of JVM thats fully server side that runs wasm.

andai - 13 hours ago

I made a couple 2D browser games a few years ago in various WASM languages. I used C++, Zig, Odin, and Rust.

(Including a game with online multiplayer! Though only the client, I did the server in TS ;)

Now a disclaimer, I experienced most of these languages for the first time during the jams, which biases me towards confusion and suffering. That being said, there was still a big gradient, and it does give us useful data on "how easy is it to get started with the basics and achieve basic tasks" (my games were like, 1970s level complexity).

Spent the last day of the C++ one dealing with a weird Emscripten bug. 12 hours left in the jam and suddenly the whole thing refused to compile, but only with Emscripten.

Spent most of the Zig jam trying to find up to date libraries and documentation. (Stuff changes fast apparently. This was 2024 though so maybe different now).

The Rust one was the most painful because I kept running into "I know what I want to do, and it's correct, and it works in every single other programming language, but rust is an authoritarian nanny state and won't let me."

(That's not WASM specific, I had similar problems when making native games in Rust. But WASM does make that aspect of the Rust experience worse, unless, I'm told, you go for one of the well supported WASM games libraries, in which case it should be relatively smooth.)

I found this too bad because overall Rust should have been the winner, in terms of cool language features. It's just a bad match for "yes I know what I'm doing and this over-cautious compiler case genuinely doesn't apply to me and there's no way to configure that so it actually lets you do your job". Also probably not ideal for game jams where dev speed and flexibility matter more than correctness.

(To beat a dead horse, my favorite part about the Rust jam was going into discord for help, getting even more absurd workarounds than GPT gave me, and then being called a bad person for not prioritizing memory safety on a game jam xD)

Zig was similarly suboptimal for game jams (though I imagine it would be fine for longer projects). Where I had 6 hours left and it was forcing me to think about what kind of division operator I wanted to use xD

Odin, I found surprisingly pleasant, even in the context of a very short jam. Very pleasant syntax. Nicest I've seen by far. (Well, I hear Jai is nice too, being Odin inspired, but no invite from Jon yet ;)

Odin's also very nice for game dev, being batteries included. For wasm there wasn't native support for game libraries at the time, but I found a GitHub repo that let you do it with a C wrapper.

Overall a fun and educational experience (and I definitely want to give Rust another go, in a less time sensitive context — it's the one language you can't just hope to wing it ;).

I did, I must admit, switch back to JS/TS and just use that for the last few games I made, because the truth is you're going to be writing it anyway for web games (unless you're using an engine or heavyweight library / toolchain), and the interop gave me more headaches than the nicer languages solved.

Depending on your scale or timeline, (or deep seated feelings about JavaScript!) WASM may be worth it for you though :)

suddenlybananas - 16 hours ago

Why is PyO3 so much nicer to use than wasm-bindgen? Is it because of WASM itself or just the tooling?

shevy-java - 16 hours ago

Well ... that kind of explains why nobody uses wasm.

Initially I fell for the hype too. Now it seems the number of people using wasm, is mega-low. It's like the tiniest ever fraction of javascript-knowing folks. And this will probably never change either.

I guess it is time to conclude:

- wasm will remain a small niche. At the least for the, say, close future. But probably forever.

forrestthewoods - 8 hours ago

I will admit to being pretty ignorant. But wasm seems like a pretty big swing and a miss. Far too many edges cases and gotchas. It definitely does not “just work”. :(

Tepix - 16 hours ago

I was hoping to find Notes on Writing WASM, instead I found stuff for writing Rust to target WASM and their wasm_bindgen issues.

probe_tech - 14 hours ago

[dead]

syskuh - 8 hours ago

[dead]

ridhoidi2026 - 15 hours ago

Go hack