Skip to content
pmatosPublic

About

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.

Topics

Resources

Stars

73 stars

Watchers

0 watching

Forks

Latest commit

 

History

1,714 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

jsse

CodSpeed

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.

Structure

  • spec/ — ECMAScript specification (submodule from tc39/ecma262)
  • test262/ — Official test suite (submodule from tc39/test262)
  • tests/ — Additional custom tests
  • scripts/ — Test runner and tooling

Supported Features

  • CLI with file execution, --eval/-e inline evaluation, and REPL mode
  • --version and --help flags
  • 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, const with TDZ, using, await using)
    • Explicit Resource Management (using/await using declarations, 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 obj brand checks)
    • Operators (arithmetic, comparison, bitwise, logical, assignment, update, typeof, void)
    • Objects and arrays (literals, member access, computed properties)
    • Template literals (including tagged templates)
    • String.raw
    • new operator with prototype chain setup
    • new.target meta-property
    • this binding (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.fromEntries
    • Function.prototype.call, Function.prototype.apply, Function.prototype.bind
    • Object.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)
    • instanceof and in operators
    • ToPrimitive with valueOf/toString coercion for objects
    • Wrapper objects (new Boolean, new Number, new String) with primitive value
    • eval() support
    • Function, GeneratorFunction, AsyncFunction, AsyncGeneratorFunction constructors (dynamic function creation)
    • Symbol with well-known symbols (iterator, hasInstance, toPrimitive, etc.)
    • delete operator for object properties
    • Iterator protocol (Symbol.iterator, lazy ArrayIterator, StringIterator)
    • Array.prototype.values(), .keys(), .entries(), [@@iterator]() returning lazy iterators
    • String.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 RegExp constructor with test, 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 and instanceof support
    • JSON.stringify (replacer function/array, space/indent, toJSON, circular detection, BigInt TypeError, wrapper unwrapping), JSON.parse (reviver), JSON.rawJSON, JSON.isRawJSON
    • String.fromCharCode
    • Map built-in (constructor, get, set, has, delete, clear, size, entries, keys, values, forEach, @@iterator, Map.groupBy)
    • Set built-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$

Building & Running

cargo build --release
./target/release/jsse <file.js>
./target/release/jsse -e "1 + 1"
./target/release/jsse              # starts REPL

Development checks

Install the pinned repository hooks once per checkout:

uv tool install pre-commit
pre-commit install

Run every hook against the full repository when changing hook configuration or tooling:

pre-commit run --all-files

Running test262

cargo build --release
uv run python scripts/run-test262.py

Options: -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/boa

Per-test timing data is written to /tmp/timing-{engine}.json after each run.

Fuzzing

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=30

CI 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.

Running JetStream 3

gh repo clone WebKit/JetStream /tmp/JetStream -- --depth 1
cargo build --release
uv run python scripts/run-jetstream.py --test OfflineAssembler --iterations 1 --timeout 120

The 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 %3

Running the Node-compat library tests

Beyond 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.

About

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.

Topics

Resources

Stars

73 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages