JS as it is
to native speed

Compile plain JS to optimized WASM.
For DSP, math, visuals and more.

··op/s

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 compiles a typed TypeScript dialect to WASM.

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. CI checks the wasm-hosted compiler against the test suite. self-compile 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