The Complex World of Wasm Language Support
Matt Butcher
languages
go
dotnet
swift
java
rust
javascript
python
ruby
When we started Fermyon in 2021, we believed that the secret to the success of WebAssembly (Wasm) was language support. We feel just as strongly now as we did then. Developers will not fall in love with Wasm unless we can utilize one of its core promises: run all kinds of code regardless of the source language.
We launched the Fermyon site one year ago. One of our marquee features was the Wasm Language Guide where we tracked programming language support for Wasm. What better way to celebrate our first year than to talk about what we’ve learned from a year of maintaining the language guide?
It’s Not How Many Languages, It’s Which Languages
Maybe we got off to an overly simplistic start. Wasm could support dozens of languages and still not be successful. It’s not how many languages support Wasm, it’s whether the right languages support it. More specifically, there are a critical set of languages that must be supported. For Wasm to take off in a big way, most of the following languages need support (ranked most- to least-important):
- JavaScript
- Python
- Java
- PHP
- C# and .NET
- C++
- TypeScript
- Ruby
- C
- Swift
- R
- Objective-C
- Scala
- Go
- Kotlin
- Rust
- Dart
If the list above looks familiar, that’s because it is based on RedMonk’s language rankings. We love the way that RedMonk’s rankings are based on GitHub usage and Stack Overflow questions—two sources that are deeply entrenched in the workflow of the modern developer.
Why seventeen, though? We started with the top 20. But there are three languages in RedMonk’s top rankings that we just don’t think will ever make their way into Wasm simply because there is no compelling use case: CSS, Shell, and PowerShell. Subtract those, and we’re left with 17 of the top 20.
Fermyon tracks a few other languages in addition. There are a few Wasm-specific languages (Grain, AssemblyScript, and Motoko). We think those languages may have a chance at taking off within the Wasm ecosystem even if they lack broader appeal. We don’t yet think of these as critical to Wasm’s success.
We also track a few languages that are notable for historical, utility, or academic reasons, or which we think are particularly promising. Examples include Haskell (academic), Perl (historical), Lua (utility), and Zig (up-and-coming). These languages are powerful contributors to Wasm’s success, but not at the level of the top 17.
How are we doing on the big list? The short answer is that the vast majority have made progress, and most of the languages are usable. But only a few have reached production grade. Rust and C are stable and well-understood. Python, Ruby, Go, and .NET are all highly usable. Kotlin and Dart are still in their earliest stages.
But before we jump to any conclusions about Wasm winning the hearts and minds of developers, there’s another facet to consider: When compiling these languages into Wasm, what tools must one use?. In other words, we need to talk about the toolchains.
Toolchains, Toolchains, and More Toolchains
When we talk about toolchains, we’re talking about the set of one or more tools that are necessary to take a language’s source code and make it runnable. For languages like C, Go, and Rust, we’re talking compilers, linkers, and such. Python, JavaScript, and Ruby require interpreters or runtimes. Java and .NET require both the compiler side and the runtime side.
Some language toolchains support Wasm as a core feature. For example, Rust, Zig, and the LLVM world (which includes C and C++) have Wasm support. Our favorite, due to the magnitude of work involved in adding Wasm support, is the .NET toolchain. Microsoft has done an astounding job supporting Wasm, and with each release of .NET they impress us further.
One exciting development in 2022 comes in the scripting language world. Seemingly days apart, both Python and Ruby announced that their interpreters could be compiled into Wasm. Practically speaking, that meant Wasm support for both languages! (If that sounds unclear, check out our post on scripting versus compiled languages.)
However, there are a variety of languages that have yet to introduce official Wasm support, but whose communities have bridged the gap. For example, the Swiftwasm project provides a Swift-to-wasm compiler. TeaVM supports compiling Java to Wasm. And TinyGo supports compiling Go to Wasm.
JavaScript, language number one on our rankings, has been the most vexing case. This is partly historical. As originally conceived, Wasm would sit in a browser side-by-side with JavaScript. So the idea of running Javascript inside of Wasm seemed counterintuitive. However, both in-browser and extra-browser cases have emerged for JavaScript running in Wasm.
Safari, the V8 world (including Chrome, Edge, and many others), and Firefox each have sophisticated JavaScript engines. But the first successful JS-on-Wasm contender came from a small open-source project called QuickJS. Currently, though, a concerted effort is underway to bring Mozilla’s Spidermonkey engine into the fray. And that is alluring because Spidermonkey is a sophisticated execution environment that can run Javascript far faster than interpreters like QuickJS.
Go into more depth for each language and toolchain with the Wasm Language Guide.
Lots of languages have Wasm support. But as we’ve seen, sometimes to get Wasm support, one must use specialized tools outside the usual toolchain. In our estimation, the state of the ecosystem will change. The mainline toolchains will incorporate or recreate Wasm support. Here at the top of 2023, we are already seeing the Go team weigh the prospect of adding Wasm and WASI (Wasm System Interface) support. Perhaps that would supplant the Wasm WASI support in TinyGo.
So far, things have been optimistic. However, there are a few languages that seem held up. What’s preventing them from also joining the Wasm world? The short answer is standards.
The Pros and Cons of Standards Processes
Wasm is standardized by the W3C. This venerable organization is the one that standardizes HTML, CSS, and other critical pieces of the Web. To say that their process is “battle-hardened” would be a huge understatement. When the Mozilla, Microsoft, and Google teams joined forces to standardize Wasm, they made an excellent choice by placing the new technology under the auspices of W3C.
Standards, especially those in well-established standards bodies, rarely move quickly. From start to completion, standards take years, not weeks or months. And while the core of Wasm is a completed standard, there are add-on standards that are not moving rapidly. One Wasm specification that is important, to at least some languages, is the garbage collection specification (abbreviated Wasm-gc).
Garbage collection describes the function of cleaning up memory in a running program when that memory is no longer actively used. Many languages use garbage collectors to prevent running out of memory.
When it comes to Wasm support, some languages have chosen to implement memory management on their own. Swift, .NET, and Go are examples. But other languages have, for a variety of reasons, chosen to wait for the Wasm-gc specification to reach its final stages. Kotlin and Dart are two examples.
By choosing to base their Wasm implementations on this extra standard, these languages have opted for a slower initial path (but ostensibly because they will gain in efficiency and speed when Wasm-gc matures). Wasm-gc progressed considerably in 2022, and our view is that Kotlin and Dart will both emerge this year. It will then be contingent on the Wasm runtimes themselves to support the Wasm-gc specification. Thankfully, runtime maintainers are eager to add this new feature.
Conclusion
We at Fermyon firmly believe that the key to the success of Wasm is broad language support. There are 17 languages that we consider the most important. And most of those have at least some degree of Wasm support. The few outliers are quickly catching up.
When it comes to toolchains, Wasm support is frequently not part of the core toolchains. This means developers have to install additional tooling to create or run Wasm versions of their source code. This will change over time as official toolchains add Wasm support. And we’re already seeing movement in this direction.
Finally, there are a few languages that are waiting on W3C standards. The wait has seemed long, but we believe the wait is nearly over. In 2023, we think Dart and Kotlin will become usable Wasm languages.
At Fermyon, our thesis is that Wasm will enable a new generation of cloud computing, blending the best of serverless functions with the stateless microservice pattern. If you’d like to gaze into a crystal ball with us, head over to our QuickStart guide and try it for yourself.