WebAssembly @GitHub
A wide variety of languages can compile to WebAssembly (Wasm), but they do so in different ways. They generally fall into three categories: Systems Languages (which have the best support), Managed Languages (which are adopting the new Wasm GC standard), and Interpreted Languages (which compile their own runtime to Wasm).
1. Top-Tier Support (Systems Languages)
These languages have "first-class" support. They compile directly to Wasm instructions and manage their own memory, resulting in small, fast binaries.
Rust: Widely considered the best language for Wasm. It has excellent tooling (wasm-pack), a small footprint, and a massive ecosystem of Wasm-compatible libraries.
C / C++: The original languages for Wasm. Tools like Emscripten are mature and powerful, often used to port huge existing codebases (like Photoshop or game engines) to the web.
Zig: Includes Wasm support out of the box as a first-class build target. It produces extremely small binaries and is becoming a favorite for Wasm tooling.
AssemblyScript: A language built specifically for WebAssembly. It looks like TypeScript but compiles to Wasm. It is one of the easiest ways for web developers to write Wasm without learning a low-level language.
2. The "Wasm GC" Wave (Managed Languages)
Historically, languages with Garbage Collection (GC) were heavy because they had to bundle their entire runtime into the Wasm file. A new feature called Wasm GC allows these languages to use the browser's built-in garbage collector, making them much faster and lighter.
Dart (Flutter): Now has stable support for Wasm GC.[1] This is a major focus for Google to make Flutter apps on the web perform near-natively.
Kotlin: Kotlin/Wasm is in Alpha/Experimental stages but is aggressively targeting Wasm GC to allow Kotlin Multiplatform code to run in the browser without the overhead of the Java Virtual Machine (JVM).
Go (TinyGo): While standard Go supports Wasm (with large file sizes), TinyGo is a specialized compiler that produces tiny Wasm binaries ideal for the web and edge computing.
MoonBit: A new language designed specifically for Wasm GC, offering Rust-like performance with Go-like simplicity.
Grain: A functional language built solely for the Wasm ecosystem that leverages Wasm GC.
3. Runtime-Bundled Languages (Interpreted/VM)
These languages don't technically "compile" your code to Wasm in the traditional sense. Instead, they compile their Virtual Machine (VM) or Interpreter to Wasm. Your code then runs inside that Wasm-hosted interpreter. This works perfectly but results in larger download sizes (often 5MB+).
C# / .NET (Blazor): Microsoft's Blazor runs the .NET runtime in Wasm. It is production-ready and very popular for enterprise apps.
Python: Projects like Pyodide and MicroPython compile the Python interpreter to Wasm, allowing you to run Python data science stacks (NumPy, Pandas) directly in the browser.
Ruby: ruby.wasm allows you to run full Ruby (CRuby) in the browser.
Java: Tools like TeaVM or CheerpJ allow Java to run in Wasm, either by transpiling to Wasm or running a JVM inside Wasm.[2]
PHP: Can run in the browser via WordPress Playground or similar tools that compile the PHP engine to Wasm.
Summary Table
| Rust | ⭐⭐⭐⭐⭐ (Native) | High-performance libraries, complex logic. |
| C/C++ | ⭐⭐⭐⭐⭐ (Native) | Porting desktop apps, games, legacy code. |
| AssemblyScript | ⭐⭐⭐⭐ (Native) | TS developers needing speed/portability. |
| Dart | ⭐⭐⭐⭐ (Wasm GC) | Full-stack apps (Flutter).[1][3] |
| C# (Blazor) | ⭐⭐⭐⭐ (Runtime) | Enterprise web apps, existing .NET teams. |
| Go (TinyGo) | ⭐⭐⭐⭐ (Native) | Small modules, serverless functions. |
| Kotlin | ⭐⭐⭐ (Experimental) | Multiplatform logic sharing (KMP). |
| Python | ⭐⭐⭐ (Runtime) | Data science in the browser (Pyodide). |
WebAssembly (Wasm) can be decompiled, but you generally cannot get the original source code back (like the original Rust, Go, or TypeScript).
Instead, you can decompile it into three main formats, ranging from "readable assembly" to "pseudo-code."
1. The Formats You Can Decompile To
| WAT (.wat) | Low | wasm2wat | This is the official "assembly" text format.[1] It is a direct 1:1 translation of the binary instructions. It is precise but very hard to read for complex logic. |
| C (Source) | Medium | wasm2c | You can convert Wasm into valid, compilable C code.[2][3][4][5] However, it is "machine-generated C"—it looks like a mess of memory commands (e.g., i32_store(ptr, val)) rather than human-written code. |
| Pseudo-C | High | wasm-decompile | This produces a "C-like" syntax designed for humans to read.[1] It cleans up the code to look like normal functions and variables, but it is not valid code you can compile. |
2. Why You Can't Get the Original Code Back
When you compile a language like Rust or C++ to Wasm, the compiler "bakes" the code. It strips away all the human-friendly parts to make the file small and fast.
Variable Names are Gone: A variable named userAccountBalance just becomes "memory location 4028."
Data Structures are Gone: Classes, Objects, and Structs disappear. They all just become raw bytes in a linear memory array.
Control Flow is Flattened: If statements and For loops are often optimized into raw jumps (instruction pointers), making the logic harder to follow.
3. The "Cheat Code": Source Maps
There is one exception. If the developer enabled Source Maps (usually a .wasm.map file) when they built the project, you can see the exact original source code (Rust, C++, etc.) inside your browser's developer tools.
How to check: Open Chrome/Firefox DevTools
→
Sources tab. If you see files ending in .rs (Rust) or .ts (AssemblyScript), the source maps are active, and you have the original code.
4. Top Decompilation Tools
If you need to reverse engineer a Wasm file without source maps, these are the standard tools:
WABT (The WebAssembly Binary Toolkit):
wasm2wat: Converts binary to text assembly.[1][6]
wasm-decompile: Converts binary to readable pseudo-code.[1][7][8][9]
wasm2c: Converts binary to portable C code.[10]
Ghidra: The NSA's open-source reverse engineering tool has a plugin for WebAssembly.[11] It is powerful for analyzing complex binaries and malware.
JEB Decompiler: A professional reverse-engineering tool that produces very readable high-level C code from Wasm.
Browser DevTools: Chrome and Firefox have built-in disassemblers. Just opening a .wasm file in the "Sources" tab will automatically show you the .wat text format.
fn main {
let name = "World!" // Define a variable
println("Hello, \{name}") // and use it directly
println("current count:")
let buf = @buffer.new()
for i in 1..<10 { // Loop over a range from 1 to 10
buf.write_string("\{i} ")
}
println(buf)
}