Compile JS as-is
to native speed

Plain JS in, tiny WASM out. No rewrite, no runtime, no GC.
For DSP, math, visuals and more.

··op/s

Hero demo compiling in your browser…

What is JZ?

JZ compiles a distilled JavaScript subset, Crockford’s “good parts” – into native-grade WASM.

Valid JZ is valid JS. Same source runs as plain JS or compiles without rewrite to .wasm – sandboxed, portable, memory-safe. No runtime, no GC, no type annotations, auto-SIMD, deterministic output.

Good for Not for
DSP, audio, synthesis UI, DOM, frontend state
Images, video, pixels Network, hot I/O, serving HTTP
Simulation, physics, games Dynamic object models and monkey-patching
Parsers, codecs, compression Allocation-heavy, long-lived object graphs
Scientific, numeric, edge ML Security-sensitive cryptography and arbitrary-precision integers
Hashing, checksums, RNG Tiny calls where the JS/WASM boundary dominates
What is supported?

A minimal modern functional JS subset – no dynamic constructs or reflection. The jzify layer lowers legacy patterns, generators, and async/await.

Not supported evalProxy ReflectdefinePropertygetters/settersDOMNode Intl
Compat varfunctionswitchclass extendsthis superstatic #privatefunction* yieldasync/awaitasync function*for awaitPromiseusingprototype== !=instanceofmore →
Strict let/const=>…spreaddestructuringimport/exportif/for/whiletry/catchnumbersstringsarrays objectstyped arraysMath JSON RegExpMap Setiterator helpersAtomics
Why no types?
Ordinary code already carries useful type evidence: let x = 0.5, Float32Array, an array index, a loop counter. JZ infers it instead of turning the file into another language. Ambiguous values take a slower, always-correct dynamic path.
Why not Porffor, scriptc, or AssemblyScript?

Porffor aims to cover the full JS spec but emits no WASM (its 2026 rewrite compiles through C to native) and runs slower than V8 on the cases it completes; scriptc makes native CLI binaries from TypeScript, no WASM target; AssemblyScript is a typed TypeScript dialect for WASM whose source can’t run as JS.

JZ compiles plain JS that still runs and tests as JS, and the release gate keeps its WASM fastest per case; the price is the overdynamic constructs it refuses.

Why not Rust, Go, or C?

Rust, Go, and C are excellent when a rewrite and second toolchain make sense. JZ is for the hot path you want to keep in JavaScript: one source, one test suite, a JS fallback, and comparable WASM or native performance.

Is it fast?

JZ leads V8 and AssemblyScript by geomean on the covered corpus and targets near-native speed. The release gate is stricter than an average: JZ must be the fastest WASM on every case. Per-case numbers, missing target coverage, and every measured loss stay visible on the bench page; a rival win remains a bug to close, not an exception to hide.

If you hit a slow case, report it →

How can it beat V8?

WASM isn't magically faster – V8 also JIT-compiles hot JS to machine code. But a JIT pays for staying ready for any JS: shape checks, deopt guards, GC pauses in the hot loop. JZ's subset is closed, so it commits ahead of time to what a JIT only gambles on – static layout, monomorphic calls, no GC – and auto-vectorizes loops to SIMD, which V8 doesn't attempt on plain JS.

Can it go native?

jz → wasm2c → clang -O3 produces a standalone native binary. See full pipeline →.

Can it compile itself?
JZ compiles itself to jz.wasm, and the self-compiled build passes the full test suite in CI. self-host CI status
Is it production ready?

It’s experimental (pre-1.0) – ABI can still shift.

But real code already ships on it: color-space v3 builds its precompiled 27-space WASM backend with JZ.

CI gates the full suite, test262, the bench, and the self-compile. A fuzzer diffs every kernel against the same source in V8.

And the exit is free: valid JZ is valid JS – drop the compile step and the same file keeps running.

How do I use it?
The CLI (jz kernel.js) or the API (compile()) produces a plain .wasm you load like any other module. Setup & options →

Examples