top | item 45279384

WASM 3.0 Completed

1086 points| todsacerdoti | 5 months ago |webassembly.org

494 comments

order
[+] jjcm|5 months ago|reply
I'm definitely excited to see 64 bit as a default part of the spec. A lot of web apps have been heavily restricted by this, in particular any online video editors. We see a bunch of restrictions due to the 32 bit cap today here at Figma. One thing I'm curious though is whether mobile devices will keep their addressable per-tab memory cap the same. It's often OS defined rather than tied to the 32 bit space.
[+] prewett|5 months ago|reply
I guess I’m just a crusty ol’ greybeard C++ developer, but it seems like a video editor is out of place in a document browser. There’s a perfectly good native operating system that nobody uses any more.

If we think we need a more thoroughly virtualized machine than traditional operating system processes give us (which I think is obvious), then we should be honest and build a virtualization abstraction that is actually what we want, rather than converting a document reader into a video editor…

[+] renehsz|5 months ago|reply
Unfortunately, Memory64 comes with a significant performance penalty because the wasm runtime has to check bounds (which wasn't necessary on 32-bit as the runtime would simply allocate the full 4GB of address space every time).

But if you really need more than 4GB of memory, then sure, go ahead and use it.

[+] tjoff|5 months ago|reply
Webapps limited by 4GiB memory?

Sounds about right. Guess 512 GiB menory is the minimum to read email nowadays.

[+] j0e1|5 months ago|reply
> Garbage collection. In addition to expanding the capabilities of raw linear memories, Wasm also adds support for a new (and separate) form of storage that is automatically managed by the Wasm runtime via a garbage collector. Staying true to the spirit of Wasm as a low-level language, Wasm GC is low-level as well: a compiler targeting Wasm can declare the memory layout of its runtime data structures in terms of struct and array types, plus unboxed tagged integers, whose allocation and lifetime is then handled by Wasm. But that’s it.

Wow!

[+] teleforce|5 months ago|reply
It's very refreshing and good to see WASM is embracing GC in addition to non-GC support. This approach is similar to D language where both non-GC and GC are supported with fast compilation and execution.

By the way now you can generate WASM via Dlang compiler LDC [1].

[1] Generating WebAssembly with LDC:

https://wiki.dlang.org/Generating_WebAssembly_with_LDC

[+] Zariff|5 months ago|reply
I'm not familiar with WASM. Can someone explain why this is a good thing? How does this work with languages that do not have a garbage collector, like Rust?
[+] wyager|5 months ago|reply
This seems less than ideal to me.

1. Different languages have totally different allocation requirements, and only the compiler knows what type of allocator works best (e.g. generational bump allocator for functional languages, classic malloc style allocator for C-style languages).

2. This perhaps makes wasm less suitable for usage on embedded targets.

The best argument I can make for this is that they're trying to emulate the way that libc is usually available and provides a default malloc() impl, but honestly that feels quite weak.

[+] satellite2|5 months ago|reply
That sounds like WASM is going into the Java direction. Is that really a good thing?
[+] cedws|5 months ago|reply
When is WASM finally going to be able to touch the DOM? It feels like that was the whole point of WASM and instead its become a monster of its own that barely has anything to do with web anymore. When can we finally kill JavaScript?
[+] re|5 months ago|reply
I haven't really been following WASM development in the last year and didn't realize that WASM had moved to a versioned release model. I've been aware of the various features in development[1] and had thought many of the newer features were going to remain optional but I guess now that implementations are expected to support all the features to be able to claim compatibility with e.g. "WASM 3.0"?

It'll be interesting to see what the second non-browser-based WASM runtime to fully support 3.0 will be (I'm guessing wasmtime will be first; I'm not counting Deno since it builds on v8). Garbage collection seems like a pretty tricky feature in particular.

Does anyone know how this 3.0 release fits into the previously announced "evergreen" release model?[2]

> With the advent of 2.0, the Working Group is switching to a so-called “evergreen” model for future releases. That means that the Candidate Recommendation will be updated in place when we create new versions of the language, without ever technically moving it to the final Recommendation state. For all intents and purposes, the latest Candidate Recommendation Draft[3] is considered to be the current standard, representing the consensus of the Community Group and Working Group.

[1] https://webassembly.org/features/

[2] https://webassembly.org/news/2025-03-20-wasm-2.0/

[3] https://www.w3.org/TR/wasm-core-2/

[+] cfallin|5 months ago|reply
> It'll be interesting to see what the second non-browser-based WASM runtime to fully support 3.0 will be (I'm guessing wasmtime will be first; ...)

Wasmtime already supports every major feature in the Wasm 3.0 release, I believe. Of the big ones: garbage collection was implemented by my colleague Nick Fitzgerald a few years ago; tail calls by Jamey Sharp and Trevor Elliott last year (with full generality, any signature to any signature, no trampolines required!); and I built our exceptions support which merged last month and is about to go out in Wasmtime 37 in 3 days.

The "3.0" release of the Wasm spec is meant to show progress and provide a shorthand for a level of features, I think, but the individual proposals have been in progress for a long time so all the engine maintainers have known about them, given their feedback, and built their implementations for the most part already.

(Obligatory: I'm a core maintainer of Wasmtime and its compiler Cranelift)

[+] titzer|5 months ago|reply
Wizard supports all of Wasm 3.0, but as a research tool, it only has an interpreter and baseline compiler tier (no opt compiler), so it doesn't run as fast as, say, V8 or wasmtime.
[+] afiori|5 months ago|reply
I suspect the versioning is going to replicate the JavaScript version system where versions are just sets of features that a runtime can support or not, I am not sure how feature discovery works in wasm though
[+] alabhyajindal|5 months ago|reply
The WebAssembly community should really focus more the developer experience of using it. I recently completed a project where I wrote a compiler¹ targeting it and found the experience to be rather frustrating.

Given that Wasm is designed with formal semantics in mind, why is the DX of using it as a target so bad? I used binaryen.js to emit Wasm in my compiler and didn't get a feeling that I am targeting a well designed instruction set. Maybe this is a criticism of Binaryen and its poor documentation because I liked writing short snippets of Wasm text very much.

1. https://git.sr.ht/~alabhyajindal/jasmine

[+] sjrd|5 months ago|reply
Binaryen has a lot of baggage from Wasm early days, when it was still a strict AST. Many newer features are difficult to manipulate in its model.

In our compiler (featured in TFA), we chose to define our own data structure for an abstract representation of Wasm. We then wrote two emitters: one to .wasm (the default, for speed), and one to .wat (to debug our compiler when we get it wrong). It was pretty straightforward, so I think the instruction set is quite nice. [1]

[1] https://github.com/scala-js/scala-js/tree/main/linker/shared...

[+] sestep|5 months ago|reply
For what it's worth, I also tried Binaryen from TypeScript and similarly found it frustrating. I switched to using wasm-tools from Rust instead, and have found that to be a vastly better experience.
[+] titzer|5 months ago|reply
What were your specific pain points? One thing that can be annoying is validation errors. That's one of the reasons that Wizard has a --trace-validation flag that prints a nicely-formatted depiction of the validation algorithm as it works.
[+] azakai|5 months ago|reply
Sorry about binaryen.js - those JS/TS bindings could be a lot better, and better documented, but priorities are generally focused on improving optimizations in core Binaryen.

That is, most work in Binaryen is on improving wasm-opt which inputs wasm and outputs wasm, so any toolchain can use it (as opposed to just JS/TS).

But if someone had the time to improve the JS/TS bindings that would be great!

[+] Existenceblinks|5 months ago|reply
i found assembly is easier to assemble from scratch (it's apple and orange but.). Most materials should exclude these tooling, mostly rust based tools. We should be able to write them by hands just like when assembly was taught. Compiler and assembly are separate classes. I think it's bad assumption that only compiler devs only care about wasm. It's compiling target, sure, but framing it this way will not broaden its knowledge.
[+] jamii|5 months ago|reply
I've tried using binaryen, and I've also tried emitting raw wasm by hand, and the latter was far easier. It only took ~200 lines of wasm-specific code.
[+] pveierland|5 months ago|reply
The SpecTec mentioned in the announcement is really cool. They're using a single source of truth to derive LaTeX, Sphinx docs, Coq definitions for proofs, and an AST schema. Building the language spec in a way that its soundness can be proven and everything derived from one truth in this way seems super useful.

https://webassembly.org/news/2025-03-27-spectec/

[+] flohofwoe|5 months ago|reply
Since it hasn't been mentioned here yet: I wonder if the multiple-memories feature will somehow allow to avoid the extra copy that's currently needed when mapping a WebGPU resource. This mapping is available in a separate ArrayBuffer object which isn't accessible from WASM without calling into JS and then copying from the ArrayBuffer into the WASM heap and back.

Multiple WASM memories and Clang's/LLVM's address space feature sound like they should be able to solve that problem, but I'm not sure if it is as trivial as it sounds...

[+] bborud|5 months ago|reply
I'm a simple man who has simple needs. I want a better and faster way to pass Go structs in and out of the runtime that doesn't mean I have to do a sword dance on a parquet floor wearing thick knit wool socks and use some fragile grafted on solution.

If there can be a solution that works for more languages: great. I mostly want this for Go. If it means there will be some _reasonable_ limitations, that's also fine.

[+] mixedCase|5 months ago|reply
You're doing native code, this the solution is the same as in native code: your languages agree on a representation, normally C's, or you serialize and deserialize. Mixing language runtimes is just not a nice situation to deal with without the languages having first class support for it, and it should be obvious why.
[+] afiori|5 months ago|reply
I am not sure what you actually want but it sounds like something where the component model (the backbone of WASI) might help.

It defines a framework to allow modules to communicate with structured data types by allowing each module to decide how to map it to and from its linear memory (and in future the runtime GC heap)

In your case you could be able to define WIT interfaces for your go types and have your compiler of choice use it to generate all the relevant glue code

[+] fidotron|5 months ago|reply
This is the truth, and it's not really much better in non-GCed languages either. (In reality my impression is the GCed wasm side runtimes are even worse).

Some of the least fun JavaScript I have ever written involved manually cleaning up pointers that in C++ would be caught by destructors triggering when the variable falls out of scope. It was enough that my recollections of JNI were more tolerable. (Including for go, on Android, curiously).

Then once you get through it you discover there is some serious per-call overhead, so those structs start growing and growing to avoid as many calls as possible.

I too want wasm to be decent, but to date it is just annoying.

[+] zdandoh|5 months ago|reply
That would be more of a library than a WASM spec thing, no? I wrote a code generator that does this well for some internal use-cases.
[+] pjmlp|5 months ago|reply
This is exactly why I say WebGL/WebGPU are much better for perfomance code on the browser than dealing with WebAssembly tooling.
[+] phkahler|5 months ago|reply
Still looking forward to when they support OpenMP. We have an experimental Solvespace web build which could benefit quite a bit from that.

https://cad.apps.dgramop.xyz/

Open source CAD in the browser.

[+] mistahchris|5 months ago|reply
I'm still hype about WASM. This looks like a cool release. I'm running some pretty high traffic WASM plugins on envoy, running some plugins for terminal apps (zellij), and for one of my toy side projects, I'm running a wasm web app (rust leptos).

For 2 of those 3 use cases, i think it's not technically the optimal choice, but i think that future may actually come. Congratulations and nice work to everyone involved!

[+] preommr|5 months ago|reply
On gc:

> Wasm GC is low-level as well: a compiler targeting Wasm can declare the memory layout of its runtime data structures in terms of struct and array types, plus unboxed tagged integers, whose allocation and lifetime is then handled by Wasm.

There's already a lot misunderstandings about wasm, and I fear that people will just go "It supports GC, so we can just export python/java/c#/go etc."

This is not a silver bullet. Cpp, or rust are probably still going to be the way to go.

Relying on the GC features of WASM will require writing code centered around the abstractions for the compiler that generates WASM.

[+] john01dav|5 months ago|reply
I thought that the purpose of GC in WASM was to allow such higher level languages to be placed there without a bulky runtime also in WASM.

What's the value proposition of WASM GC if not this?

[+] jillesvangurp|5 months ago|reply
The Kotlin wasm compiler was basically engineered on top of wasm's GC support. Works fairly OK. As far as I understand it's essentially the same garbage collector that is also used for regular javascript.

> This is not a silver bullet. Cpp, or rust are probably still going to be the way to go.

I don't think that's necessarily true anymore. But as you say, it depends on the compiler you use and how well it utilizes what is there. Jetbrains has big plans with Kotlin and Wasm with e.g. compose multiplatform already supporting it (in addition to IOS native and Android).

[+] mdhb|5 months ago|reply
This isn’t true at all in Dart for example which is a WASM-GC language. Literally one of the very main selling points of Dart is you write your code once and it runs anywhere, WASM is just another compile target like x64 or RISC-V or iOS.
[+] whizzter|5 months ago|reply
Wasm-GC are abstractions for compiler writers to enable GC dependent languages to run without shipping a GC to run inside the already GC'd browser/Wasm heap and instead just use the browser GC directly.

So yes, Java,C#,etc will work better (If you look at the horrible mess the current C# WASM export generates it basically ships with an inner platform containing a GC), and no, it will explicitly not speak with "javascript" objects (you can keep references to JS objects, but you cannot call JS methods directly).

[+] afiori|5 months ago|reply
The two main benefits of wasm GC are that compilers can avoid implementing or compiling a full GC but also that the guest and the host can share structured data types
[+] modeless|5 months ago|reply
Is there a technical reason for the web limit to be 16 GB specifically? Or is it just a round number picked so that the limit could be standardized? Also, has the limit on JS heap size (and ArrayBuffer size) also been relaxed to 16 GB or is it still lower?
[+] hinkley|5 months ago|reply
Still no mention of DOM.

<sets alarm for three years from now>

See you all for WASM 4.0.

[+] boricj|5 months ago|reply
Does WASM still have 64 KiB pages? I get why for desktops, but there are use-cases for running WASM on microcontrollers where that's either inconvenient or outright impossible.

The one in particular I have in mind would be to put WASM on graphical calculators, in order to have a more secure alternative to the ASM programs (it's possible nowadays to write in higher-level languages, but the term stuck) that could work across manufacturers. Mid-range has RAM on the order of 256 KiB, but a 32-bit core clocked at more than 200 MHz, so there's plenty of CPU throughput but not a lot of memory to work with.

Sadly, the closest thing there is for that is MicroPython. It's good for what it does, but its performance and capabilities are nowhere near native.

[+] pbiswal|5 months ago|reply
Is the component model work (https://component-model.bytecodealliance.org/) related to the 3.0 release in any way?
[+] phickey|5 months ago|reply
No, the component model proposal is not part of the Wasm 3.0 release. Proposals only make it into a Wasm point release once they reach stage 5, and the component model is still under development and so is not trying to move through the phases yet.

Unlike any of the proposals which became part of Wasm 3.0, the component model does not make any changes to the core Wasm module encoding or its semantics. Instead, it’s designed as a new encoding container which contain core Wasm modules, and adds extra information alongside each module describing its interface types and how to instantiate and link those modules. By keeping all of these additions outside of core Wasm, we can build implementations out of any plain old Wasm engine, plus extra code that instantiates and links those modules, and converts between the core wasm ABI to higher level interface types. The Jco project https://github.com/bytecodealliance/jco does exactly that using the common JS interface used by every web engine’s Wasm implementation. So, we can ship the component model on the web without web engines putting in any work of their own, which isn’t possible with proposals which add or change core wasm.

[+] jsheard|5 months ago|reply
Has anyone benchmarked 64bit memory on the current implementations? There's the potential for performance regressions there because they could exploit the larger address space of 64bit hosts to completely elide bounds checks when running 32bit WASM code, but that doesn't work if the WASM address space is also 64bit.
[+] steveklabnik|5 months ago|reply
This looks like a great release! Lots of stuff people have wanted for a long time in here.
[+] leoc|5 months ago|reply
Tail calls. Tail calls!