ox_jsdoc
High-performance JSDoc parser with a parser-integrated Binary AST writer and a lazy decoder, inspired by the oxc project.
ox_jsdoc parses /** ... */ comment blocks on the Rust side and emits a compact byte stream (the Binary AST). The same crate provides a Rust-side lazy decoder so callers can walk the tree without materializing every node up front. The byte stream is also the format consumed by the JS-side @ox-jsdoc/decoder package, making the same parser usable from Rust, Node.js (via ox-jsdoc), and the browser (via @ox-jsdoc/wasm).
Features
- Binary AST — parser-integrated writer that produces a self-contained, 8-byte-aligned byte stream with shared string interning across batched comments
- Lazy Rust-side decoder — walk the AST on demand (
LazyJsdocBlock,LazySourceFile, …) without eagerly building intermediate node objects - Batch parsing — amortize parser setup, intern common strings (
*,*/, tag names) once across many comments - Standalone type expression parser —
parse_type_expression/parse_type_checkfor parsing JSDoc type strings without a surrounding comment compat_mode— opt-in@es-joy/jsdoccomment-compatible output for downstream tooling
Installation
[]
= "0.0.13"
= "0.123"
Quick start
Parse a single block
use Allocator;
use ;
let arena = default;
let result = parse;
let root = result.lazy_root.expect;
let tag = root.tags.next.expect;
assert_eq!;
assert_eq!;
assert!;
Parse a batch of blocks
use Allocator;
use ;
let arena = default;
let items = ;
let result = parse_batch;
for in result.lazy_roots.iter.enumerate
Reuse a BinaryWriter
For hot loops (lint runners, watch mode), construct a BinaryWriter once and reuse it across calls so the per-call writer setup cost (string-table prelude, arena buffer init) is amortized:
use Allocator;
use ;
use BinaryWriter;
let arena = default;
let mut writer = new;
for src in
The matching batch entry is parse_batch_into.
Bytes-only API (binding-friendly)
parse_to_bytes and parse_batch_to_bytes skip the arena round-trip and return an owned Vec<u8> directly. This is the API the NAPI / WASM bindings consume so the bytes can be moved into a Uint8Array without an extra copy:
use ;
let result = parse_to_bytes;
let _bytes: = result.binary_bytes;
// `bytes` is the canonical Binary AST byte stream — the JS-side
// `@ox-jsdoc/decoder` package can lazily read it.
Standalone type expressions
use ;
assert_eq!;
assert!;
assert!;
Public API map
| Module / item | Purpose |
|---|---|
parser::parse / parse_into |
Parse one comment, return a ParseResult (lazy root + diagnostics + source file). parse_into reuses a caller-supplied BinaryWriter. |
parser::parse_to_bytes |
Per-comment bytes-only entry point (Vec<u8> + diagnostics). Used by NAPI / WASM bindings. |
parser::parse_batch / parse_batch_into |
Parse N comments into one shared Binary AST buffer + lazy roots. |
parser::parse_batch_to_bytes |
Per-batch bytes-only entry point. |
parser::parse_type_expression / parse_type_check |
Parse a standalone type expression (no surrounding comment). |
parser::ParseOptions |
compat_mode, parse_types, type_parse_mode, preserve_whitespace, fence_aware, base_offset. |
decoder::source_file::LazySourceFile |
Wraps the Binary AST byte buffer and exposes the cached header. |
decoder::nodes::comment_ast::LazyJsdocBlock |
Lazy root accessors (tags(), description(), inline_tags(), …). |
writer::BinaryWriter |
Re-usable writer; arena-backed, shared by parse_into / parse_batch_into. |
format::* |
Wire-format constants (header, node record layout, kind tags, extended-data). |
See the full API documentation on docs.rs for the lazy decoder node hierarchy and per-node accessors.
Design
ox_jsdoc is the canonical Rust core of the ox-jsdoc workspace, which also publishes the corresponding NAPI binding (ox-jsdoc on npm) and WASM binding (@ox-jsdoc/wasm on npm). All three share this crate's parser, byte format, and decoder.
The design rationale (Binary AST format, lazy decoder, batch sharing, NAPI / WASM transport, jsdoccomment compatibility) lives under design/:
design/007-binary-ast/— Binary AST format and decoder designdesign/008-oxlint-oxfmt-support/—compat_mode/preserve_whitespacefor downstream toolingdesign/010-main-stream-binary/— post-cutover migration that promoted the Binary AST to canonicaldesign/009-jsdoc-linter-benchmark/— benchmark methodology and the Rust-direct measurement layer
The original typed AST + JSON implementation is preserved as the workspace-internal ox_jsdoc_origin crate (publish = false) for benchmark / reference comparison only.
Minimum Supported Rust Version (MSRV)
Tracks the workspace rust-version. See the workspace Cargo.toml.