Paserati is an experimental (mad scientist kind of experimental) TypeScript runtime: it parses + type-checks TypeScript and compiles it directly to bytecode for a register VM. And then it executes the bytecode.
TypeScript is a superset of JavaScript, so if you can execute TypeScript, you’re building an ES2025 runtime too (by definition, plus a lot of pain).
Under the hood: TS/JS → bytecode → register VM, with inline caches, shape-based objects (a.k.a. “hidden classes”-style), and a pluggable async executor with microtask scheduling.
Right now it prioritizes correctness over raw speed, but the architecture is designed for type-driven optimization later (specialization, monomorphization, unchecked fast paths).
- Test262 language suite: 92.0% (see details below)
- Native TS execution: no
tsc, no TS→JS transpilation - TCO: tail call optimization (elite feature)
- Shapes + ICs: fast-ish property access without a JIT
- Runtime type reflection:
Paserati.reflect<T>()(generate a type object / JSON Schema at runtime) - Small-ish footprint:
- ~17MB static binary (unstripped, includes lexer/parser/checker/compiler/VM/builtins)
- ~5MB BSS idle (approx; depends on build/OS)
- Pure Go, with one dependency (
golang.org/x/text)
Paserati has a long way to go performance-wise, but it’s already at the point where it can beat dop251/goja and QuickJS on a couple of simple microbenches.
Results from hyperfine (see bench/hyperfine.sh):
| Benchmark | paserati (Mean) | goja (Mean) | quickjs (Mean) | Relative |
|---|---|---|---|---|
bench/bench.js |
3.924 ± 0.097 s | 5.207 ± 0.093 s | 4.945 ± 0.092 s | paserati 1.33× faster than gojac, 1.26× faster than quickjs |
bench/objects.js |
6.169 ± 0.092 s | 7.015 ± 0.151 s | 8.135 ± 0.130 s | paserati 1.14× faster than gojac, 1.32× faster than quickjs |
If your favorite pure Go JavaScript engine is reading this: skill issue.
- Runtime type reflection / JSON Schema:
examples/reflect.ts - Proxy + classes + async:
examples/reactive.ts - Async/await + generators:
examples/async.ts - Classes (private fields, inheritance, statics):
examples/classes.ts - Typed recursion (Y combinator):
examples/ycomb.ts - “Look ma, generics”:
examples/generics.ts
Examples may or may not work at every commit, but they should work at least once in a while.
- A TypeScript build toolchain replacement: see microsoft/typescript-go
- A JIT in Go: I’ll stop just short of that (for now)
- Perfect “legacy weirdness”: modern ES is the target; some dusty corners (like
with) are still incomplete
# Build
go build -o paserati ./cmd/paserati/
# Run the REPL
./paserati
# Run a snippet
./paserati -e 'console.log("hello from paserati")'
# Execute a script
./paserati path/to/script.ts
# Run the test suite
go test ./tests/...From a recent run:
language (TOTAL) 23410 21533 1852 0 25 92.0% 1m41.734s
Weak spots:
language/import/import-defer: 14.5% (69)language/module-code/namespace: 52.8% (36)language/statements/with: 55.8% (181)language/eval-code/indirect: 62.3% (61)language/expressions/yield: 74.6% (63)language/expressions/super: 75.5% (94)language/statements/for-in: 78.3% (115)language/types/reference: 79.3% (29)language/expressions/call: 79.3% (92)language/eval-code/direct: 79.7% (286)
The engine runs a lot of modern code today, but it’s still a moving target. It might crash on you sometimes, or refuse to run some valid code. I'm working on it. Okay?
Some big-ticket items that work reasonably well:
- Async/await, TLA, Promises, microtasks (incl. top-level await, async generators)
- ESM modules (plus dynamic
import(), pluggable resolution) - Classes (private fields, statics, inheritance)
- (Async) Generators (
yield,yield*) - Modern operators (
?.,??, logical assignment) - Destructuring (arrays/objects/rest/spread)
- Built-ins (Proxy/Reflect/Map/Set/TypedArrays/ArrayBuffer/RegExp/Symbol/BigInt)
- Advanced types (generics, conditional/mapped types, template literal types,
infer)
Last time I checked it could run a pure TS library date-fns from source without any glaring issues. Cough, not sure if it does so at every commit, but it did at the time of writing.
Known gaps:
- WeakMap/WeakSet (tbd)
- Decorators (planned)
evalcorrectness (still bugged; shows up ineval-code/*subsuites)withstatement semantics (incomplete)- Some ASI edge cases (I think, eh)
- Import attributes (experimental ES feature)
See docs/bucketlist.md for the exhaustive yet messy feature inventory.
Seriously, why would you want to contribute to this? …But if you do, I'm both terrified and thrilled. PRs and issues are welcome.
This project is licensed under the MIT License.
This is a one-person project developed in my free time with the help of AI. It is also an experiment in large scale software engineering with AI, aimed at speedrunning a production-quality open source project.
Google Gemini 2.5/3.0 Pro and Claude Sonnet/Opus 4/4.5 wrote almost all the code so far under more or less careful direction and scrutiny - also known as "vibe coding but when you know what you're doing".
That fun sticker at the top of the README? It's made with GPT-4o's image generation.
Remember: Pedal to the metal, or just pedal faster.
