Find your next open-source project

Search by name, purpose, or keyword — or paste a GitHub repository URL

earendil-works/djs

Developer Tools

A small no_std Rust JS/TS engine for wasm, designed to run model-written tool scripts with snapshots and resumability.

138
3
Rust
2 days old

What it is

djs is a small JavaScript and TypeScript engine implemented in no_std Rust, aimed primarily at wasm32. Its intended role is to replace QuickJS inside pi's codemode: model-written scripts that call host tools, handle results, and return or print data. It follows that workload rather than general browser or Node compatibility.

The design centers on a single byte arena addressed by u32 offsets. VM snapshotting is copying bytes, and restoring is copying them back. The interpreter does not recurse on the Rust stack for JS calls, so execution can pause between instructions, including inside getters, builtins' callbacks, promise jobs, generators, and async functions, and then resume. Inbound values use a compact wire format, while outbound results are read directly from the heap by the host. The compiler emits stack bytecode in one pass without an AST and erases TypeScript during parsing. Builtins are written in a strict TypeScript subset and compiled to bytecode and Rust state machines. Determinism is a goal: clock, randomness, and weak references come from the host, and identical inputs should produce byte-identical heap images natively and in wasm.

Quick start

Build the Rust workspace and try the CLI. You need stable Rust (edition 2024) with the wasm32-unknown-unknown target. Node 22.6 or newer is needed for the JS host package, and the oracle-based tests also expect dquickts' qjs at ~/Development/dquickts/qjs or at $DJS_QJS.

cargo build
cargo run -p djs-cli -- run file.js
cargo run -p djs-cli -- run --ts file.ts
cargo run -p djs-cli -- repl
scripts/build-wasm.sh

The run command prints console output. --body runs a codemode async function body, and other flags include --gc-stress, --suspend-every N, and --backend bytecode|native. To use the engine from JavaScript, use the @djs/host package and create a Sandbox:

import { Sandbox } from "@djs/host";

const sb = await Sandbox.create({
  asyncFunctions: { search: (q) => mySearch(q as string) },
  memoryLimit: 64 << 20,
});
const result = await sb.runAsync("const hits = await search(q); return hits.length;", { q: "djs" });
const image = sb.bytes();

js/pi/vm.ts adapts the engine to pi's codemode VM contract. The host API, wasm ABI, and pi adapter are covered in the host documentation, linked from the guide site.

Constraints and compatibility

This is not a drop-in general JS runtime. By design it skips Intl, Temporal, SharedArrayBuffer/Atomics, Annex B, sloppy mode, direct eval, and modules, and it is always strict. Most known failures follow from that strictness, along with tests that expect the quickjs-wasi fingerprint. Its behavior reference and test oracle is dquickts, a QuickJS fork, including error messages. The wasm module measures 1,471 KB (525 KB gzip, 423 KB brotli), of which 218 KB is the base snapshot; creating a VM copies that snapshot in about 40 µs in wasm. The README reports test262 conformance of 38,069 of 38,109 active tests and 538 of 549 differential corpus cases matching qjs, measured on 2026-11-01.

Performance is not uniformly ahead of quickjs-wasi in the README's wasm measurements: for example, tight loops were 0.42×, property access 0.49×, and higher-order map/filter/reduce 2.92×. A pi-like script measured 10.0G versus 7.3G, where higher is better for the published ratios. The repository declares no license, which matters if you plan to embed or redistribute it.

Documentation and testing

The repository includes a human-oriented guide under docs/guide/ with design trade-offs and live examples, plus architecture, testing, compiler, object, host, wire, and CLI notes. The full source layout separates the core engine, builtin compiler, prelude, wasm build, CLI, test262 runner, differential corpus runner, benchmarks, and docs generator.

Tests include cargo test, test262 against a recorded expected-failure list, the differential corpus against qjs, and Node tests for the host package. Engine-running workflows should go through scripts/timeout.sh, and scripts/gate.sh is described as the pre-main gate.

HotRepo's take

The station's only recorded snapshot is from 2026-11-03, when the repository appeared on the Rust new-project list at 109 stars and gained 6 stars in about an hour, with 1 fork gained in the same window. There is no all-language daily rank recorded and no discussion thread. That is too narrow a window to say anything about sustained adoption; what the available material does support is a project with a concrete design thesis and unusually detailed conformance and performance reporting, rather than a generic “fast JS engine” claim.

Project source and documentation

Written by AI from the project's README, updated . The project's own docs are the source of truth.