Repository navigation
quickjs-oxide v0.3.0
quickjs-oxide 0.3.0
Every program now runs on oxide-core: functions compile to register bytecode and run in one loop with inline caches, over NaN-boxed values and a mark-sweep collector. The workspace is safe Rust throughout, with no unsafe.
Performance
Fixed-work programs, release builds on one Linux machine, geometric means of wall time against QuickJS 2026-06-04:
| Suite | quickjs-oxide / QuickJS time |
|---|---|
| V8 v7 (8 programs) | 0.94× |
| Octane 2.0 (15) | 1.15× |
| AWFY (14) | 0.99× |
| all 37 | 1.04× |
On the V8 v7 programs, 0.3.0 takes 0.28× the time of 0.2.1.
| 0.2.1 | 0.3.0 | |
|---|---|---|
stripped qjs, bytes |
7,656,840 | 2,985,704 |
| WebAssembly module, bytes | 4,978,281 | 1,893,077 |
| clean release build | 71.6 s | 22.9 s |
Conformance
Test262: 81,441 of the 83,562 variants in QuickJS 2026-06-04's scope pass (97.462%). ECMA-262 and Test262 decide correctness; QuickJS decides what the specification leaves to the implementation. Where QuickJS departs from the specification, quickjs-oxide follows the specification; dev-support/quickjs-spec-departures.tsv lists those departures.
Calls, templates and expressions of any size compile: a call with 65,533 arguments or a template with 65,532 substitutions runs.
Behavior that differs from QuickJS by decision
withis aSyntaxError, and nothing readsSymbol.unscopables.- A direct
evalruns as an indirect eval. - A runtime has one realm.
- Nothing reads
Symbol.species.
See docs/deviations.md.
Command line
- New:
--heap-cap-mib,--min-heap-mib,--gc-growth,--stack-limit(memory options),--gc-stats,--memory-report,--disassemble, and--ic-stats/--gc-stress=Nin builds with those features. - Removed:
--dump,--trace,--profile-json,--profile-output,--profile-events,--profile-iterations, and theprofilingbuild.
Embedding API
Runtime::new(),Runtime::with_options(RuntimeOptions)andRuntime::with_host(impl Host, RuntimeOptions).RuntimeOptionscarries the heap cap, the collection threshold and growth, the register stack limit and the native stack budget.- One realm per runtime:
Runtime::context()returns it, andContext::newreturns the same realm. - One
Hosttrait for the host's output, clock, time zone, random seed, file reads and promise-rejection events.SystemHost(native) andWebHost(browser) implement it. - Host callbacks receive a
Scopefor the runtime; calling the API from a callback without it returnsRuntimeError::Reentered. AValueowns a handle that is released on drop. RuntimeErrorisException(the context's pending exception),Reentered,Unsupported,Compile,OutOfMemory,InvariantandInternal.Runtime::memory_report()returns aMemoryReport.- The profiling API and its JSONL records are removed.
Rust 1.99 or newer is required.
Install qjs
Prebuilt binaries for Linux (static musl), macOS and Windows are attached below.
# Prebuilt binary through cargo-binstall
cargo binstall --git https://github.com/pocket-nexus/quickjs-oxide quickjs-oxide-cli
# Build from source (Rust 1.99 or newer)
cargo install --locked --git https://github.com/pocket-nexus/quickjs-oxide --tag v0.3.0 quickjs-oxide-cliWebAssembly
quickjs-oxide-wasm-v0.3.0.tar.gz: wasm-bindgen packages for browsers (web/, ES module) and Node.js (nodejs/).quickjs-oxide-playground-v0.3.0.tar.gz: the static playground site for this release, also served at https://pocket-nexus.github.io/quickjs-oxide/releases/v0.3.0/.
SHA256SUMS lists the digest of every attached file.
What's Changed
- Release the receiver a bound call replaces by @Eric-Song-Nop in #123
- Run the QuickJS oracle cases from JS fixtures by @Eric-Song-Nop in #125
- Remove 35k lines of engine code by @Eric-Song-Nop in #124
- The register VM, heap, collector, embedding API and tooling of this release, landed as one commit per pull request: #134 to #152
Full Changelog: v0.2.1...v0.3.0