Skip to content

quickjs-oxide v0.3.0

Choose a tag to compare

@github-actions github-actions released this 19 Oct 02:42
· 11 commits to main since this release

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

  • with is a SyntaxError, and nothing reads Symbol.unscopables.
  • A direct eval runs 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=N in builds with those features.
  • Removed: --dump, --trace, --profile-json, --profile-output, --profile-events, --profile-iterations, and the profiling build.

Embedding API

  • Runtime::new(), Runtime::with_options(RuntimeOptions) and Runtime::with_host(impl Host, RuntimeOptions). RuntimeOptions carries 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, and Context::new returns the same realm.
  • One Host trait for the host's output, clock, time zone, random seed, file reads and promise-rejection events. SystemHost (native) and WebHost (browser) implement it.
  • Host callbacks receive a Scope for the runtime; calling the API from a callback without it returns RuntimeError::Reentered. A Value owns a handle that is released on drop.
  • RuntimeError is Exception (the context's pending exception), Reentered, Unsupported, Compile, OutOfMemory, Invariant and Internal.
  • Runtime::memory_report() returns a MemoryReport.
  • 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-cli

WebAssembly

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