2
11
Fork
You've already forked jam
0
Performance aware JS/TS toolchain. Work in progress!
  • Zig 78.6%
  • JavaScript 13.4%
  • TypeScript 7.9%
injuly f4edda4eb2
chore: update code with zig master
Adopt the new `std.Io` interface.
This codebase now works with zig master as of the time of writing.
**Note**: this commit was authored originally using OpenCode big-pickle,
then reviewed a human (me).
2026年03月19日 22:16:08 +05:30
.github/workflows chore: fix benchmark builds 2025年10月25日 13:40:23 +05:30
benchmark chore: fix benchmark builds 2025年10月25日 13:40:23 +05:30
src chore: update code with zig master 2026年03月19日 22:16:08 +05:30
tools chore: update code with zig master 2026年03月19日 22:16:08 +05:30
.gitignore chore: update code with zig master 2026年03月19日 22:16:08 +05:30
build.zig chore: upgrade to zig 0.16/master 2025年10月25日 13:03:53 +05:30
build.zig.zon chore: update code with zig master 2026年03月19日 22:16:08 +05:30
LICENSE chore: update license to MIT 2025年12月18日 23:22:25 +05:30
pre-commit feat(astgen): Add a (generated) child iterator for AST nodes 2025年03月03日 01:58:09 +05:30
README.md chore: update README 2025年10月25日 14:05:10 +05:30

Jam

A high-performance JavaScript parser and semantic analyzer built from the ground up. Work in progress!

Goals

  • Competitive in performance with existing tools.
  • Support JS, JSX, and TypeScript out of the box.
    • And the <script> part of VueJS code.
  • Single, small binary.
  • Support data flow analysis and call-graphs with an accessible API.
  • Expose a capable parsing and scope resolution, such that a bundler, minifier, etc., can be built on top of it.
  • API to write lint rules with zig.
  • Custom JavaScript plugins.

Roadmap

  • Phase 1:
    • A fast, 100% Spec compliant JavaScript parser.
    • Port ESLint scope to Zig
    • JSX parsing.
    • Semantic analysis: Control Flow Graphs (WIP).
    • TypeScript parsing (WIP).
    • Runtime for a linter, with Zig plugin support.
    • Formatter with a language agnostic backend.
  • Alpha release
    • Simple linter with all the base rules from ESLint.
    • A prototype for the jam formatter
  • Beta release
    • Data flow analysis and taint checking

Local development

I've tried to keep the development process hassle-free. You need only a Zig compiler (and optionally an environment variable) to get going.

If you still face any issues, feel free to open an issue or reach out to me on discord (@in.july), twitter, or e-mail. I usually respond within a day.

NOTE: If you're willing to contribute, It's a good idea to copy the contents of ./pre-commit to your ./.git/hooks/pre-commit. This will ensure you didn't break any existing functionality before letting you commit changes.

Basic setup

  1. Ensure you have a master build of the zig compiler – to seamlessly switch between multiple zig versions, I recommend using zvm.
  2. Clone this project into your development machine.
  3. Run zig build run -- <path-to-file.js> to see a parsed AST for the given file.
  4. Run zig build test to run the unit tests.
  5. Run zig build bench-parser to run the parser benchmarks.

Checking ECMAScript conformance

To avoid regressions and keep track of spec compliance, we use a results.json and babel-results.json file – their formats are explained in the tools README.

You'll need to set the JAM_TESTS_262_DIR environment variable to the path of a cloned tc39/test262-parser-tests repository:

git clone --depth 1 https://github.com/tc39/test262-parser-tests.git /tmp/test262-parser-tests
# `tools/ec262-tests` can find the tests if you set the environment variable.
export JAM_TESTS_262_DIR=/tmp/test262-parser-tests

To compare your changes with the existing test results, run zig build test262 -- compare ./tools/results.json. If it exits normally, you didn't break anything!

To update the test results when you increase conformance, run zig build test262 > ./tools/results.json.

Currently, the format of the results.json file is roughly as follows:

{
 // % of test files that either: a) parsed incorrectly, or b) failed to parse.
 "fail_percent": 35.703479576399396,
 // % of test files that were parsed correctly.
 "pass_percent": 64.2965204236006,
 // number of test files that parsed but had an incorrect syntax tree.
 "unmatching_ast_count": 17,
 // results for individual test cases:
 "test_cases": {
 "2db5219f0ac5dd71.js": "parse_error",
 "c532e126a986c1d4.js": "pass",
 "d532e126a986c1d4.js": "ast_no_match",
 // ...goes on for a few thousand lines...