An agent-coded JS engine in Rust. I didn't touch a single line of code here. Not one. This repo is a write-only data store. I didn't even create this repo by hand -- my agent did that.
Goal: 100% test262 pass rate.
Read more: jsse - a JavaScript engine built by an agent.
Per the test262 specification (INTERPRETING.md), test files without noStrict, onlyStrict, module, or raw flags must be run twice: once in default (sloppy) mode and once with "use strict"; prepended. Our test runner implements this dual-mode execution. Run uv run python scripts/run-test262.py for the current pass rate.
ES Modules now supported with dynamic import() and import.meta. Async tests run with Promise/async-await support.
spec/— ECMAScript specification (submodule from tc39/ecma262)test262/— Official test suite (submodule from tc39/test262)tests/— Additional custom testsscripts/— Test runner and tooling
- CLI with file execution,
--eval/-einline evaluation, and REPL mode --versionand--helpflags- Exit codes: 0 (success), 1 (runtime error), 2 (syntax error)
- Lexer: all ES2024 tokens, keywords, numeric/string/template literals, Unicode identifiers
- Parser: recursive descent, all statements, expressions, destructuring, arrow functions, classes, private fields, strict mode
- Interpreter: tree-walking execution with environment chain scoping
- Variable declarations (
var,let,constwith TDZ,using,await using) - Explicit Resource Management (
using/await usingdeclarations,DisposableStack,AsyncDisposableStack,SuppressedError,Symbol.dispose,Symbol.asyncDispose) - Control flow (
if,while,do-while,for,for-in,for-of,for-await-of,switch,try/catch/finally) - Functions (declarations, expressions, arrows, closures)
- Classes (declarations, expressions, inheritance,
super, static methods/properties, private fields, private methods, private accessors,#x in objbrand checks) - Operators (arithmetic, comparison, bitwise, logical, assignment, update, typeof, void)
- Objects and arrays (literals, member access, computed properties)
- Template literals (including tagged templates)
String.rawnewoperator with prototype chain setupnew.targetmeta-propertythisbinding (method calls, constructors, arrow lexical scoping)- Property descriptors (data properties with writable/enumerable/configurable)
- Prototype chain inheritance (Object.prototype on all objects)
- Getter/setter support (object literals, classes,
Object.defineProperty) Object.defineProperty,Object.getOwnPropertyDescriptor,Object.getOwnPropertyDescriptors,Object.defineProperties,Object.keys,Object.freeze,Object.getPrototypeOf,Object.setPrototypeOf,Object.create,Object.entries,Object.values,Object.assign,Object.is,Object.getOwnPropertyNames,Object.getOwnPropertySymbols,Object.groupBy,Object.preventExtensions,Object.isExtensible,Object.isFrozen,Object.isSealed,Object.seal,Object.hasOwn,Object.fromEntriesFunction.prototype.call,Function.prototype.apply,Function.prototype.bindObject.prototype.hasOwnProperty,Object.prototype.toString,Object.prototype.valueOf,Object.prototype.propertyIsEnumerable,Object.prototype.isPrototypeOf,Object.prototype.__defineGetter__,Object.prototype.__defineSetter__,Object.prototype.__lookupGetter__,Object.prototype.__lookupSetter__- Number/Boolean primitive method calls (
toString,valueOf,toFixed) instanceofandinoperators- ToPrimitive with valueOf/toString coercion for objects
- Wrapper objects (
new Boolean,new Number,new String) with primitive value eval()supportFunction,GeneratorFunction,AsyncFunction,AsyncGeneratorFunctionconstructors (dynamic function creation)Symbolwith well-known symbols (iterator, hasInstance, toPrimitive, etc.)deleteoperator for object properties- Iterator protocol (
Symbol.iterator, lazyArrayIterator,StringIterator) Array.prototype.values(),.keys(),.entries(),[@@iterator]()returning lazy iteratorsString.prototype[@@iterator]()with Unicode code point iteration- Spread elements in arrays and function calls (iterator-protocol aware)
- Rest parameters in function declarations
- Destructuring (array and object patterns, iterator-protocol aware)
- RegExp literals and
RegExpconstructor withtest,exec,toString - Array prototype methods (
push,pop,shift,unshift,indexOf,lastIndexOf,includes,join,toString,concat,slice,splice,reverse,fill,forEach,map,filter,reduce,reduceRight,some,every,find,findIndex,findLast,findLastIndex,sort,flat,flatMap,at) Array.isArray,Array.from,Array.of- String prototype methods (
charAt,charCodeAt,indexOf,lastIndexOf,includes,startsWith,endsWith,slice,substring,toLowerCase,toUpperCase,trim,trimStart,trimEnd,repeat,padStart,padEnd,concat,split,replace,replaceAll,at,search,match) - Proper Error objects (
TypeError,ReferenceError,SyntaxError,RangeError) with prototype chains andinstanceofsupport JSON.stringify(replacer function/array, space/indent, toJSON, circular detection, BigInt TypeError, wrapper unwrapping),JSON.parse(reviver),JSON.rawJSON,JSON.isRawJSONString.fromCharCodeMapbuilt-in (constructor,get,set,has,delete,clear,size,entries,keys,values,forEach,@@iterator,Map.groupBy)Setbuilt-in (constructor,add,has,delete,clear,size,entries,keys,values,forEach,@@iterator, ES2025 set methods:union,intersection,difference,symmetricDifference,isSubsetOf,isSupersetOf,isDisjointFrom)- Generator functions (
function*,yield,yield*) with replay-based execution - Generator prototype (
next,return,throw,Symbol.iterator,Symbol.toStringTag) - ES Modules (
import,export,import(),import.meta, top-level await) ArrayBuffer(constructor,byteLength,slice,isView)- TypedArrays (
Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array) with indexed access, prototype methods (at,set,subarray,slice,copyWithin,fill,indexOf,lastIndexOf,includes,find,findIndex,findLast,findLastIndex,forEach,map,filter,reduce,reduceRight,every,some,reverse,sort,join,toString,toReversed,toSorted,entries,keys,values,from,of) DataView(constructor, all get/set methods for Int8 through BigUint64, little/big endian)Temporal(all types:Instant,ZonedDateTime,PlainDateTime,PlainDate,PlainTime,PlainYearMonth,PlainMonthDay,Duration,Temporal.Now; full arithmetic, comparison, rounding, formatting; IANA timezone support via ICU4X; 12 calendar systems; 100% test262 + intl402/Temporal compliance)Intl.DateTimeFormat(partial — dateStyle/timeStyle, calendar-aware Temporal formatting)Intl.NumberFormat(partial)ShadowRealm(constructor,evaluate,importValue; full cross-realm value wrapping with WrappedFunction exotic objects)globalThis- Built-ins:
console.log,console.assert,Error,Test262Error,$DONOTEVALUATE$
- Variable declarations (
cargo build --release
./target/release/jsse <file.js>
./target/release/jsse -e "1 + 1"
./target/release/jsse # starts REPLInstall the pinned repository hooks once per checkout:
uv tool install pre-commit
pre-commit installRun every hook against the full repository when changing hook configuration or tooling:
pre-commit run --all-filescargo build --release
uv run python scripts/run-test262.pyOptions: -j <n> for parallelism (default: nproc/2), --timeout <s> (default: 120).
The runner exits non-zero for baseline regressions. Use --fail-on-failures
when a selected test set must be 100% passing, as CI does for smoke/sample runs.
The runner supports multiple engines via --engine:
uv run python scripts/run-test262.py --engine jsse # default
uv run python scripts/run-test262.py --engine node --binary /path/to/node
uv run python scripts/run-test262.py --engine boa --binary /path/to/boaPer-test timing data is written to /tmp/timing-{engine}.json after each run.
Two cargo-fuzz targets live under fuzz/: parse_roundtrip (the parser
must never panic on arbitrary bytes) and differential (jsse vs node on
the same source, surfacing divergences no fixed corpus would). See
docs/adr/0004-fuzz-lib-target-and-subprocess-differential.md for the design
and .claude/skills/fuzzing/SKILL.md for the full run/triage workflow.
cargo install cargo-fuzz --locked
cargo +nightly fuzz run parse_roundtrip -- -max_total_time=60
cargo build --release # differential needs the release binary
cargo +nightly fuzz run differential -- -max_total_time=60 -timeout=30CI runs a corpus-replay smoke check (-runs=0, deterministic) on every PR;
new-mutation fuzzing for both targets runs nightly via
.github/workflows/fuzz.yml's fuzz-deep job and never gates a PR — see the
ADR for why. A finding from either target is a lead, not a fix to make in the
PR that touches the fuzz tooling itself: file it as its own issue and fix it
against spec//test262, never by matching node's observed behavior.
gh repo clone WebKit/JetStream /tmp/JetStream -- --depth 1
cargo build --release
uv run python scripts/run-jetstream.py --test OfflineAssembler --iterations 1 --timeout 120The runner covers pure-JS JetStream 3 workloads and skips Wasm/Worker-dependent tests.
Each workload is measured three times by default. The reported score is derived
from the median of the measured times, and the min-max range of the repeats is
printed alongside it; a range above 5% is flagged UNSTABLE. Controlled runs
refuse a one-minute load average above 1.5 and use the maximum-frequency CPU
cluster when Linux cpufreq data and taskset are available. Use --repeats and
--idle-threshold to tune the protocol; --no-idle-gate is intended only for
diagnostic or parallel runs. JSON output includes the repeat samples and a
host/load/topology fingerprint.
The runner drives workloads with its own harness rather than JetStream's
cli.js, so it emulates the few shell globals they rely on: self
(=== globalThis) and a JetStream object with preload paths and an async
getString backed by the embedded preload files (getBinary rejects as
unsupported). These live only in the generated script, never in jsse's own
globals. An async workload that rejects is reported as benchmark threw: ...,
and every failed workload keeps its clipped stdout/stderr in the --json
report and the first line of it on the FAIL line.
A refused run exits 3 (distinct from argparse's 2) and leaves any existing
jetstream-results.json untouched, so a truncated suite cannot overwrite a
complete baseline. This protection also applies when --json names that file
through an equivalent absolute or symlinked path; choose a distinct output path
to retain partial refusal evidence. Because a single-threaded benchmark
contributes roughly 1.0 to the one-minute average itself, the default 1.5
threshold leaves only about 0.5 of headroom for foreign load; raise
--idle-threshold on a host with unavoidable background activity rather than
disabling the gate.
To confirm the gate actually fires, run the suite against a synthetic load.
One yes asymptotes the one-minute average to only ~1.0, which is below the
1.5 default, so use enough burners to clear the threshold:
for _ in 1 2 3; do yes > /dev/null & done
sleep 60 # let the 1-minute average converge
uv run python scripts/run-jetstream.py --test Air --iterations 1
# expect: "BUSY Air (loadavg1 ... exceeds idle threshold 1.50)" and exit 3
kill %1 %2 %3Beyond test262, real-world npm libraries are run as engine stress tests: each
library's own upstream test suite is bundled with esbuild and executed on
target/release/jsse, cross-checked against Node as a reference oracle.
cargo build --release
./scripts/run-library-tests.sh <lib> # e.g. decimal.js, acorn, zod, moment
./scripts/run-library-tests.sh <lib> --clean # force a fresh clone/rebuild
./scripts/run-library-tests.sh <lib> --node # run on Node only (reference)<lib> is any config name under scripts/libs/: acorn, ajv, big.js,
bignumber.js, decimal.js, highlight.js, js-md5, js-sha256, lodash,
luxon, moment, prismjs, qs, uglify-js, zod. None of this is baked
into jsse's globals or run in CI — it's a manual, additive-only harness that
never affects test262. See scripts/README.md for the
full recipe, the current per-library status table, and how to add a library.