asopi tech
asopi techIndie Developer
MoonBit and the State of WASM Languages (2026) — Choosing a Language in the Wasm GC Era

[July 2026 edition]

MoonBit and the State of WASM Languages (2026) — Choosing a Language in the Wasm GC Era

Published: Jul 24, 2026
Reading time: ~11 min

Part 1 mapped the division of roles among technologies; Part 2 mapped the runtimes and frameworks. This final installment organizes the languages you write code in on top of them — the “WASM languages” — centered on MoonBit. This is the state of things as of July 2026.

”WASM Languages” Split into Three Groups

“WASM languages” is a single phrase for three groups of quite different character.

  1. Languages designed from the start for WASM — MoonBit, Grain, AssemblyScript, and so on
  2. Existing languages with a WASM backend added — Rust, C/C++, Go, Kotlin, Dart, Swift, C#, and so on
  3. Frameworks that use WASM as an app distribution format — Blazor WebAssembly, Compose Multiplatform, Flutter Web, Spin, and so on

Among these, MoonBit is not merely a language that can compile to WASM: it is a language whose compiler, build system, package management, testing, and IDE support are designed as one for the WASM era. It currently has wasm, wasm-gc, JavaScript, and native backends, and directly supports WIT/the Component Model.

The Axes of Comparison — “Can It Emit .wasm?” Is Not Enough

When evaluating a WASM-capable language, “can it emit .wasm?” is not enough. The axes that matter:

AxisWhat to check
WASM kindCore Wasm, Wasm GC, WASI, Component Model
Memory managementManual, ownership, own GC, Wasm GC
External APIsHow it connects to JavaScript, DOM, WebGPU, WASI
OutputSingle WASM, JS glue, bundled language runtime
Binary sizeSuited to small libraries or large apps
Execution locationBrowser, Node.js, WASI, edge, embedded
InteropRaw numeric ABI or WIT component
ToolingBuild, test, LSP, package management
MaturityProduction use, spec stability, library assets

The biggest of these is the difference between traditional linear-memory WASM and Wasm GC.

Traditional WASM         Wasm GC
linear memory            struct / array / typed reference
pointer + length         host GC manages objects
language manages heap     suits Kotlin / Dart / MoonBit
suits C / Rust / AssemblyScript

WebAssembly 3.0 integrated GC and typed references into the spec, greatly strengthening the base for putting GC languages onto WASM. This shift is moving the premises of language choice.

MoonBit

What MoonBit Is

MoonBit is a statically typed, general-purpose language designed with WASM as its primary target. The official docs list wasm, wasm-gc, JavaScript, C/native, and LLVM (experimental) backends. It also envisions mixed-backend configurations where a web frontend and native processing share the same domain model within one module.

As a language, it combines elements of Rust, OCaml, Go, and TypeScript.

enum Result[T, E] {
  Ok(T)
  Err(E)
}

struct User {
  id : Int
  name : String
}

fn find_user(id : Int) -> Result[User, String] {
  if id > 0 {
    Ok({ id, name: "Alice" })
  } else {
    Err("invalid id")
  }
}

Its main traits are static typing, type inference, algebraic data types, pattern matching, generics, traits, null safety, exception-effect tracking, built-in tests, GC-based memory management, and fast incremental/parallel builds. It has Rust-like syntax but is not a language built around ownership and lifetimes.

Using wasm and wasm-gc

MoonBit separates traditional WASM and Wasm GC explicitly. wasm (linear memory) is supported by a wide range of runtimes and integrates easily with existing WASM tools and WASI environments. wasm-gc uses WASM’s GC types directly, handling strings, arrays, and structs as the engine’s GC objects.

wasm       : MoonBit object → linear memory → MoonBit runtime / GC
wasm-gc    : MoonBit object → Wasm struct / array / ref → browser GC

The theoretical benefits of Wasm GC are a smaller own-GC runtime, better bridging to JS objects, use of typed references, and fewer pointer conversions in linear memory. On the other hand, the WASI and Component Model ecosystems have matured around traditional Core Wasm, so Wasm GC integration requires confirming runtime and tool support.

Component Model Support

MoonBit can generate bindings from WIT and build WebAssembly components. The Bytecode Alliance’s official Component Model guide lists it as a supported language.

package example:calculator;

world calculator {
  export add: func(a: s32, b: s32) -> s32;
}

This means MoonBit can be used not just as a browser language but as a server/edge component language that runs on Spin, Wasmtime, Wasmer, and others.

FFI and Host Dependence

Access to the outside world depends on importing host functions. The official docs note that some standard-library parts require MoonBit-specific host functions and should be avoided when portability matters.

extern "js" fn console_log(value : String) = "console.log"

The caveat is that writing in MoonBit does not give you direct, fully type-safe access to Web APIs. Browser use still needs JavaScript FFI, Web API bindings, JS glue, per-host import definitions, and async integration with Workers/Promises. Async support exists, but parts of it are treated as experimental.

Toolchain

MoonBit’s strength is that not just the language but the whole toolchain is integrated. moon unifies incremental/parallel builds, testing, package management, and doc generation, with Mooncakes as the registry.

moon
  ├─ moon new / build / check / run
  ├─ moon test / fmt / doc
  └─ moon add / publish

This is a big difference from AssemblyScript (built on the npm ecosystem) and Grain (centered on its own language and compiler): MoonBit provides language + build + test + LSP + package management as one.

Where MoonBit Fits

It suits small WASM libraries, in-browser parsing/transformation, edge functions, WASM components, DSLs and parsers, algorithm implementations, plugins, cross-backend domain logic, and new WASM-native apps. Conversely, be cautious for apps needing huge existing library assets, apps deeply dependent on OS APIs, apps needing mature GUI frameworks, complex DOM apps, and advanced async networking apps. It is promising, but not yet as rich in existing assets as Rust, C++, C#, or Kotlin.

AssemblyScript

AssemblyScript is a WASM-only language with TypeScript-like syntax. It is often called “a subset of TypeScript,” but more accurately it is an independent language that targets WASM directly using TS-like syntax. It does not use JavaScript’s dynamic types or object model as-is.

export function add(a: i32, b: i32): i32 {
  return a + b;
}

let value = load<i32>(ptr);
store<i32>(ptr, value + 1);

It implements its own runtime and GC (incremental/minimal/stub) in linear memory. Small numeric functions can produce very small output, but heavy use of strings, arrays, and classes needs the runtime and JS-side bindings. Advantages include an easy on-ramp for TypeScript developers, closeness to raw WASM, and easy npm integration; constraints include not being able to use TS libraries as-is, no direct DOM API, its own GC, limits on exceptions/async, and the Component Model not being a central workflow. Wasm GC support is on the roadmap, but the existing design assumes linear memory and its own runtime.

It is more accurate to think of it as writing C-like WASM code with TypeScript-like syntax than “turning TypeScript into WASM.”

Grain

Grain is a functionally inclined language designed with WASM as its sole primary execution base, intended to run in browsers, CLIs, servers, and WASI environments.

enum Option<a> {
  Some(a),
  None,
}

let divide = (a, b) =>
  if (b == 0) {
    None
  } else {
    Some(a / b)
  }

Its traits are Hindley–Milner type inference, algebraic data types, pattern matching, an immutable orientation, no null, GC, and JavaScript FFI. It is more functional than MoonBit and prioritizes simplicity of language design. It suits functional WASM apps, education, CLIs, WASI apps like Spin, type-safe small services, and parsers. Its challenges are a small ecosystem, a non-central native backend, and few GUI/Web UI libraries, with limited enterprise adoption. Where MoonBit aims to be “a general-purpose system/app language for the WASM era,” Grain is closer to “an approachable functional language that uses WASM as its execution base.”

Existing Languages’ WASM Backends

Rust

Rust is not a WASM-only language, but it remains one of the most mature options. Its targets are wasm32-unknown-unknown (browser/JS host), wasm32-wasip1 (WASI Preview 1), and the Component Model (cargo-component/wit-bindgen). Its strength is a very thick periphery: wasm-bindgen, web-sys, js-sys, wit-bindgen, cargo-component, wasm-tools, affinity with Wasmtime, wgpu, SIMD, threads, memory control, and a huge crate ecosystem. Weaknesses are the learning cost of ownership/lifetimes, verbose code in DOM-centric apps, the complexity of async plus the WASM boundary, and the need to tune binary size. Rust is more mature in language and libraries than MoonBit, while MoonBit demands less low-level management and lets you write more concisely. Rust for performance, assets, and control; MoonBit for development speed, concision, and WASM-first design.

C / C++

C/C++ can compile to WASM via Emscripten or the WASI SDK. Its greatest value is existing assets: SQLite, FFmpeg, OpenCV, LLVM, game engines, compression/crypto libraries, and CAD/scientific-computing code brought to the web. Strengths are porting native assets, mature Emscripten, SIMD/threads, WebGL/WebGPU integration, and fine memory control. Weaknesses are memory safety, glue bloat, dependence on POSIX-compat layers, and unsuitability for DOM work. Less a new-language choice than the main route for bringing existing native code to WASM.

TinyGo / Go

Go has a browser js/wasm target and WASI targets, but standard Go tends to produce large output because it bundles the Go runtime, GC, and scheduler. Go 1.24 strengthened WASM function export and reactor mode, making WASM easier to treat as an extension unit of a Go app. TinyGo is a Go compiler that produces small binaries for WASM/WASI/embedded, with wasm, wasi, and embedded targets, and its Component Model language support is advancing. In return, it is not fully compatible with standard Go, with constraints on reflection, some standard-library parts, and GC/goroutine behavior. It is strong for Go developers writing WASI components, but browser UI centers on JS interop.

Kotlin/Wasm

Kotlin/Wasm is a backend that compiles Kotlin to Wasm GC. It has a browser wasm-js and a WASI wasm-wasi, and because it uses Wasm GC, it need not represent classes and objects solely in an in-linear-memory runtime. Its main uses are Compose Multiplatform Web, Kotlin Multiplatform, and sharing Kotlin domain logic on the web; its strengths are the type system, coroutines, Compose, sharing with JVM/Android assets, and Wasm GC. It is not suited to small WASM libraries, needs the Kotlin runtime and standard library, and leans toward UI apps. Where MoonBit uses WASM itself as a distribution/execution base, Kotlin/Wasm centers on existing Kotlin assets and UI sharing.

Dart / Flutter Wasm

Dart has a production compiler dart2wasm that uses Wasm GC, and Flutter Web supports WASM builds. Its JavaScript interop API was also refreshed for WASM support. Strengths are Flutter UI, web/mobile/desktop sharing, high-level async/await, and hot reload. On the other hand, the Flutter runtime and rendering layer are large, it is unsuited to small WASM libraries, and it is not a language for distributing WIT components. Rather than competing with MoonBit, Flutter Wasm is a cross-platform UI base.

C# / Blazor WebAssembly

Blazor WebAssembly loads the .NET runtime itself into the browser as WASM and runs C# apps on top (with more direct compilation when using AOT). Strengths are the .NET ecosystem, C# and Razor, ASP.NET Core integration, rich business libraries, a debugger, and a UI framework. Distribution size and startup time are large, it is unsuited to small-component use, and its reusability as a raw WASM library is low. Blazor is less a WASM language than a way to run the .NET application platform on top of WASM.

SwiftWasm

SwiftWasm is a project that makes the Swift compiler and standard library target WASM, running Swift code in browsers/WASI environments. It uses JavaScriptKit for JS integration.

import JavaScriptKit

let document = JSObject.global.document
document.body.innerText = "Hello from Swift"

Strengths are Swift’s type safety, potential sharing with Apple-ecosystem code, async/await, and Swift Package Manager. Challenges are binary size, Foundation coverage differences, the Swift runtime, the maturity of JS-integration libraries, and few browser UI assets. Its default concurrency uses a single-threaded cooperative task executor.

Language Positioning Comparison

LanguageWASM-firstMemory managementPrimary useComponent ModelBinary tendency
MoonBitStrongGC / Wasm GCGeneral, Component, edgeStrongSmall–medium
AssemblyScriptStrongOwn GC / manual-leaningFast JS-facing librariesWeakSmall
GrainStrongGCFunctional apps, WASIPossibleSmall–medium
RustMediumOwnershipHigh-performance, systems, ComponentVery strongSmall–medium
C/C++MediumManualPorting existing assetsTool-dependentSmall–large
TinyGoMediumGCWASI, embeddedStrengtheningSmall–medium
Kotlin/WasmMediumWasm GCWeb UI, KMPLimitedMedium–large
DartMediumWasm GCFlutter WebWeakLarge
C#Weak.NET GCBlazor business appsLimitedLarge
SwiftWasmMediumARCSwift sharing, web/WASIDevelopingMedium–large

MoonBit vs. AssemblyScript vs. Rust

These three are often compared, but their purposes differ.

  • A small JS-facing WASM library → AssemblyScript. For TS developers writing small modules — image processing, hashing, numeric work.
  • A WASM component / edge app → MoonBit. Writing app logic concisely with WIT, pattern matching, GC, high-level types, and an integrated toolchain.
  • High-performance, low-level, mature assets → Rust. When you need to control WebGPU, SIMD, threads, databases, crypto, and runtime embedding.
RequirementRecommendation
A feel close to TypeScriptAssemblyScript
A GC’d, Rust-like languageMoonBit
Memory safety via ownershipRust
WIT componentsRust or MoonBit
Raw linear-memory controlRust or AssemblyScript
The WebGPU ecosystemRust
Compile speed and short codeMoonBit
npm affinityAssemblyScript
The largest existing library baseRust

Conclusion — MoonBit Starts from “Components with a Clear Boundary”

MoonBit is not “an easier WASM language than Rust.” Its distinctiveness is that it newly designed the language and toolchain around WASM/cloud/edge. It lets you switch between wasm and wasm-gc, supports WIT/the Component Model, can also emit JavaScript and native, lets you use high-level types without ownership, unifies build/test/LSP/package management, and produces relatively small output. It is a good fit for parsers, algorithms, and data processing.

On the other hand, its biggest practical weakness is not the language spec but the surrounding assets: package count, Web API bindings, async I/O, DB drivers, GUI, GPU, native integration, operational track record, and long-term compatibility are all still developing.

So the reasonable 2026 judgment is this. MoonBit is strong for new WASM components, edge processing, in-browser compute libraries, parsers, and data transformation. But for huge existing assets, advanced WebGPU integration, and OS-adjacent work, it is not yet at the stage of replacing Rust or C/C++.

For something like a large data UI, rather than pushing the whole thing into one language, a solid split is: TypeScript for UI/DOM/Web Components; Rust/wgpu for the GPU renderer and low-level shared memory; and MoonBit for compute/transform components with a clear WASM boundary — filter expressions, query transformation, parsers, data shaping, rule engines. Adopting MoonBit not as “the language you write everything in” but as the language for components with a clear boundary is, for now, the most realistic approach.

References