9 ms·
Notes on writing Rust-based Wasm
- AyanamiKaine 8mo agoI 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.
- shevy-java 8mo agoThe even bigger issue is that this will remain a niche thing. Things that are a niche, will often sooner or later just die - and nobody will even notice this. I don't understand the wasm committee. Why design something that is bound to fail due to barely anyone using it?
- deleted 8mo ago[deleted]
- hobofan 8mo agoI think you overestimate how niche it really is. In the browser it's an essential part for many creative/productivity tools, e.g. Figma or Miro. On the backend it's used quite regularly as sandboxing mechanism or plugin system, e.g. Istio, Helm or OPA (so generally a high prominence in the CNCF ecosystem). There are a lot more niche web standards that have a lot less usage that stuck around for a log time (e.g. the recent debate around removal of XSLT)
- jonex 8mo agoDidn't it start with asm.js, a subset of javascript serving as a way to compile C code to be run in a browser? Then browser makers figured that it'd be better to have a dedicated target for this. So while it can be used to achieve performance in specific scenarions, it's largely designed with the goal in mind to be able to run non js code in a browser. The wasm toolchain Emscripten encompasses this notion quite clearly as it emulates things like filesystems etc. If the main goal was faster execution, they would probably have gone a different route. PRobably even gone for a new language altogether. I'd like a toolchain better targeted for the pure acceleration use case though. Emscripten adds a lot of bloat and edges just to serve out of the box posix compatibility. Which is nice for quick demos of "look I can run Doom in the browser"-kind. But less useful for advanced web app usage, where you anyways will want to keep control of such behavior and interact with the browser apis more directly.
- flohofwoe 8mo ago> Didn't it start with asm.js It started even much earlier. At first Emscripten compiled to a plain Javascript subset, after this demonstrated 'usefulness' this JS subset was properly specificed into 'asm.js' which browsers could specifically target and optimize for. The next evolutionary step was WASM (which didn't immediately bring any peformance improvements over asm.js, but allowed further improvements without having to 'compromise' Javascript with features that are only useful for a compilation target).
- pjmlp 8mo agoEven earlier, it started with NaCL, then PNaCL. With an SDK that supported C, C++ and OCaml. Mozzilla not wanting to jump into Google's boat came up with asm.js. This naturally ignoring all the other plugins.
- flohofwoe 8mo agoI mean... don't believe the hype, doh? ;) WASM is "just" another virtual ISA, everything else is just marketing. If you manage expections (in the sense of "it's just another ISA / bytecode VM") then WASM can be incredibly useful, e.g. all my C/C++ projects are running automatically in browsers thanks to WASM (for instance these home computer emulators: https://floooh.github.io/tiny8bit/ https://floooh.github.io/tiny8bit/).
- twoodfin 8mo agoI think you’re discounting the embedding model, which opens up many interesting use cases for WASM.
- deleted 8mo ago[deleted]
- pjmlp 8mo agoThe irony is all those Java and .NET haters, jumping into startups selling the dream of doing application servers packaged in Kubernetes pods. Plus, having to watch talks selling the idea as if no one had ever done it before. This even ignoring operating systems where the whole userspace was bytecode based.
- DonHopkins 8mo agoMy Apple ][ ran Sweet 16 and UCSD Pascal.
- pjmlp 8mo agoYeah, for example.
- Tepix 8mo agoI was hoping to find Notes on Writing WASM, instead I found stuff for writing Rust to target WASM and their wasm_bindgen issues.
- irishcoffee 8mo agoI don’t know why you expected that. The title very clearly says “notes on writing wasm”
- koolala 8mo ago'with rust bindgen'
- irishcoffee 8mo agoHmm, I didn’t click the link, that is not the link title.
- koolala 8mo agoI can't understand why you replied without clicking the link...
- irishcoffee 8mo agoBecause I don't care about rust.
- dcminter 8mo agoIt misled me too - though I'm interested in the article anyway. I've emailed the mod team so hopefully the submission here will get a less context-dependent title soon.
- dang 8mo agoOK, we've put Rust in the title above.
- shevy-java 8mo agoWell ... 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.
- flohofwoe 8mo agoThis is not specific to WASM, you would have the same problems calling from Rust into any other language through FFI.
- suddenlybananas 8mo agoPyO3 is designed in such a way that it's a lot easier to avoid many of these issues I find.
- antonvs 8mo ago> It's like the tiniest ever fraction of javascript-knowing folks. “Javascript-knowing folks” aren’t likely to have much overlap with people who have a need for WASM. It’s a bit confusing because of the history of WASM, but the two are pretty separate at this point. We use WASM to deploy machine learning models in the browser, for example. That’s not something we would have ever considered doing with Javascript.
- xigoi 8mo ago> wasm will remain a small niche. At the least for the, say, close future. But probably forever. I’m still waiting for being able to access the DOM from WebAssembly, so it’s possible to do something useful with it without JavaScript glue code.
- dcminter 8mo agoDoes anyone know if there's any reasonable timescale likely for this to happen? Last time I looked into the topic it seemed to be completely stalled, but I might well have been looking in the wrong places. To a very casual observer (me) it seems like it ought to be simple, but I expect there are good reasons why it isn't.
- suddenlybananas 8mo agoWhy is PyO3 so much nicer to use than wasm-bindgen? Is it because of WASM itself or just the tooling?
- nicoburns 8mo agoI think its a large part just the tooling. wasm-bindgen hasn't seen active development for several years at this point.
- comagoosie 8mo agoThe good news is that since August 2025 there's been quite the uptick in development, in large part thanks to folks working over at Cloudflare.
- Tpt 8mo agoI guess it's mostly because cpython has a fairly good C API allowing PyO3 to just write "safe" wrappers on top of cpython APIs and provide macros to generate boilerplate whereas wasm-bindgen has to generate both Rust and JS sides and deal with the painful linear memory intermediate.
- Decabytes 8mo agoYes 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
- flohofwoe 8mo agoOnly partially correct IMHO, the *WASM Component Model* is mostly a Rust thing (at least it's very apparent that it has been designed by Rust people), thankfully WASM itself is independent from that overengineered boondoggle.
- throwaway27448 8mo ago> thankfully WASM itself is independent from that overengineered boondoggle. I can't tell if this is a jab at WASM itself or whether it should be taken at face value lmao, WASM is the definition of overengineered boondoggle.
- ncruces 8mo agoWasm 1.0 (and 2.0) is a fairly straightforward portable assembly. It's a great target for a simple language (unless you insist on someone else doing your GC for you, which mandates their design on your language). And it's also fairly easy to build a Wasm interpreter, or an AOT compiler.
- throwaway27448 8mo ago> Wasm 1.0 (and 2.0) is a fairly straightforward portable assembly. It's also largely useless outside of targeting c/c++ and derivatives. Most code we write cannot target wasm without severe drawbacks.
- flohofwoe 8mo agoThis is about the same as saying that the x86 or ARM instruction sets are largely useless outside of targeting C/C++ and derivatives...
- flohofwoe 8mo agoThis 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.
- larsnystrom 8mo agoWASM is kind of like Java bytecode, right? A compilation target which requires a runtime? But better sandboxed?
- flohofwoe 8mo agoIn general, and with a lot of handwaving and omitting details: yes :)
- deleted 8mo ago[deleted]
- wffurr 8mo agoLower level, GC optional, supports stack allocated user defined types. Initially designed for C and C++ as an LLVM backend.
- iberator 8mo agoWASP is almost the same as Java Applets but buildinto browser and works without plugins. Java Applets were amazing technology IMO. Windows Java launcher ruined it (as i understand that was the main security issue). ps. Java 8 still works :P
- ncruces 8mo agoIf you consider just Wasm 1.0 and 2.0, the amount of “runtime” is relatively sparse. A tool like wasm2c (or my wasm2go) shows this: there is no huge runtime to carry, just a fairly direct translation of Wasm byte code to C (or Go). wasm2c: https://github.com/WebAssembly/wabt/blob/main/wasm2c/README.md https://github.com/WebAssembly/wabt/blob/main/wasm2c/README.... wasm2go: https://github.com/ncruces/wasm2go https://github.com/ncruces/wasm2go
- ridhoidi2026 8mo agoGo hack
- comagoosie 8mo agoA 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 https://github.com/madonoharu/tsify
- Surac 8mo agoI expected an article about writing code directly in wasm. Title is bit missleading
- probe_tech 8mo ago[dead]
- tarun_anand 8mo agoInteresting.. 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/discussions/1145 https://github.com/modelcontextprotocol/modelcontextprotocol... https://github.com/modelcontextprotocol/rust-sdk/pull/183 https://github.com/modelcontextprotocol/rust-sdk/pull/183
- pasxizeis 8mo agoTangential: 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 https://github.com/agis/wadec [1] https://github.com/WebAssembly/spec/issues/2066 https://github.com/WebAssembly/spec/issues/2066
- andai 8mo agoIs 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?
- apitman 8mo agoSome exist at least: https://spritely.institute/hoot/ https://spritely.institute/hoot/
- spankalee 8mo agoI'm writing a new Wasm GC language because I'm so unsatisfied with the current options. I'm three months in, and so for it's mostly good. WASM takes care of all the GC bits, but in turn you have to use its ref, struct, and array types for everything. Making vtables is straight forward. Fat pointers for interfaces require an object though, since you can't do your own pointer layout. In web contexts GC should be great because browser GCs can work across DOM, JS, and WASM, so you can hold a reference to a node that you get via JS, and if you remove the node from the DOM and discard the reference, it'll be collected just like in JS. The big downside is data transfer over the Wasm boundary requires a lot more copying with GC. Byte arrays like (array i8) are completely opaque to the outside, so you need to vend individual byte access functions to read data. On the WASI side, it only lowers to linear memory, so you need to allocate some from scratch space, then copy into GC structs and arrays. Strings are doubly awful because of this because you also have to deal with encoding. GC also doesn't support multi-threading yet. Some of this is supposed to be fixed by things like https://github.com/WebAssembly/design/issues/1569 https://github.com/WebAssembly/design/issues/1569 and WASI lowering to GC types. stringref would have been great, but that appears to be dead for now. So I'm on board and optimistic these things will get fixed, but GC is still a bit of a second-class citizen for now.
- James_K 8mo agoIf you are interested in multi-byte access to GCed arrays, something similar can already be accomplished. You can hold the array data in Wasm linear memory, then have an object that wraps a pointer to it, and using JS code, associate a finalizer with that object that frees the related section of linear memory. It's essentially how FFI memory is handled in most native GCed languages.
- andai 8mo agoI 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 :)
- mendyberger 8mo agoThings 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-class-language-on-the-web/ https://hacks.mozilla.org/2026/02/making-webassembly-a-first...
- flohofwoe 8mo agoTbh, apart from the demonstrated performance improvement for string marshalling I really fail to see how integrating the WASM Component Model into the browser is a good thing. It's a lot of complexity for a single niche use case (less overhead for string conversion - but passing tons of strings across the boundary is really only needed for one use case: when doing a 1:1 mapping of the DOM API). I really doubt that web APIs like WebGPU or WebGL would see similar performance improvements, and it's unclear how the much more critical performance problems for accessing WebGPU from WASM would be solved by the WASM Component Model (e.g. WebGPU maps WGPUBuffer content into separate JS ArrayBuffer objects which cannot be accessed directly from WASM without copying the data in and out of the WASM heap).
- mendyberger 8mo agoIt's not just about string performance, it's about making wasm a first class experience on the web. That includes performance improvements - because you don't need to wake up the js engine - but it's a lot more than that. Including much better dev-ex, which is not great as you can see in the OP. It would also enable combining different languages with high-level interfaces rather than having to drop down to c-style interfaces for everything.
- flohofwoe 8mo ago> Including much better dev-ex, which is not great as you can see in the OP. IMHO the developer experience should be provided by compiler toolchains like Emscripten or the Rust compiler, and by their (standard) libraries. E.g. keep the complexity out of the browser, the right place for binding-layer complexity is the toolchains and at compile time. The browser is already complex enough as it is and should be radically stripped down instead instead of throwing more stuff onto the pile. Web APIs are designed from the ground up for Javascript, and no amount of 'hidden magic' can change that. The component model just moves the binding shim to a place inside the browser where it isn't accessible, so it will be even harder to investigate and fix performance problems.
- phplovesong 8mo agoWasm is really cool. I imagine a runtime that competes with the likes of JVM thats fully server side that runs wasm.
- Twey 8mo 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 https://rfd.shared.oxide.computer/rfd/0609 [2]: https://docs.rs/tokio/latest/tokio/sync/struct.Mutex.html#which-kind-of-mutex-should-you-use https://docs.rs/tokio/latest/tokio/sync/struct.Mutex.html#wh... [3]: https://docs.rs/shadow-rs/latest/shadow_rs/ https://docs.rs/shadow-rs/latest/shadow_rs/
- galangalalgol 8mo agoI try to avoid tokio in its entirety. There are some embedded use cases with embassy that make sense to me, but I have never needed to write something that benefited from more threads than I had cores to give it. I don't deny those use cases exist, I just don't run into them. I typically spend more time computing than on i/o but so many solid libraries have abandoned their non-async branches I still have to use it more often than I'd like. I get this is a bit of a whine, I could fork those branches if I cared that much. But complaining is easier.
- IshKebab 8mo agoI agree. Async makes sense for Embassy and WASM. I'm skeptical that it really ever makes sense for performance, even if it is technically faster in some extreme cases.
- Twey 8mo agoI think the dream is executor-independence. You shouldn't really need to care what executor you or your library consumer is using, and the Rust auto traits are designed so that you can in theory be generic over it. There are a few speed bumps that still make that harder than it really should be though. I'm not sure what you mean by ‘more threads than I had cores’, though. Unless you tell it otherwise, Tokio will default to one thread per core on the machine.
- pjmlp 8mo agoThe 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.
- forrestthewoods 8mo agoI 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”. :(
- flohofwoe 8mo agoIt's because every 'programmer category' (game devs, backend devs, traditional web devs, ...) wants something different from WASM, and the early hype also didn't help. For me WASM is "just another ISA" like x86 or ARM, and the web is "just another platform" like Windows, macOS or Linux. All my hobby C/C++ projects (and some Zig projects) also automatically run in the browser, and 'distributing' a URL is much less painful than distributing native binaries or asking users to build the code themselves.
- syskuh 8mo ago[dead]