deno_ast

Rust library for parsing, lexing, and transpiling JavaScript and TypeScript source into a shared AST, built and maintained by the Deno core team.

Library
Cargo
v0.53.3
180stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
61/100Good
Development Activity36
Maintenance56
Community76
Maturity56
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
73/100Good
Architecture80
Code Quality85
Innovation60
Learning Curve65

deno_ast is the Rust crate that Deno and its ecosystem crates — deno_graph, deno_doc, deno_lint, eszip, and dprint-plugin-typescript — rely on for parsing, lexing, and transpiling JavaScript and TypeScript source text. It wraps a pinned, exact-version set of swc crates behind a MediaType-driven API, producing a single ParsedSource that holds the AST, tokens, comments, and source-text info together so downstream tools can lex, analyze scopes, strip types, or fully transpile without re-parsing.

Because swc itself changes frequently, deno_ast does not follow strict semver — instead it documents an explicit release policy tied to whether its five downstream consumer crates still compile, and asks consumers to pin patch versions. This lets the wider Deno toolchain absorb swc’s monthly upgrades in one place rather than in every crate that needs to understand JavaScript or TypeScript source.

What You Get

  • A unified ParsedSource type holding the AST, captured tokens, comments, and source-text info behind an Arc for cheap cross-thread sharing
  • MediaType-aware parsing entry points (parse_module, parse_program, parse_script) that pick the right swc syntax automatically
  • Feature-gated add-ons — scope analysis, CommonJS parsing, JSX/TS transforms, sourcemap-aware codegen emit, and a fast type-only stripping path — so consumers only pull in what they need
  • Direct, pinned access to the underlying swc crates (swc::ast, swc::parser, swc::transforms) for advanced use cases

Common Use Cases

  • Parsing TypeScript/JSX/TSX source into an AST for static analysis tools like linters and doc generators
  • Stripping TypeScript types quickly for a runtime that just needs to execute the resulting JavaScript
  • Building module graph and dependency-resolution tools that need consistent lexing and specifier handling across a codebase
  • Transpiling TypeScript/JSX down to plain JavaScript inside a bundler or build tool

Under The Hood

Architecture The crate is organized around a central ParsedSource type (src/parsed_source.rs) produced by the parsing entry points in src/parsing.rs (parse_module, parse_program, parse_script), which wrap swc’s lexer and parser behind a MediaType-driven Syntax selection and store source text, tokens, comments (src/comments.rs), and the swc AST behind an Arc for cheap cloning and cross-thread sharing. Optional feature-gated modules layer cleanly on top: scopes.rs adds swc scope analysis, transpiling/mod.rs and transpiling/transforms.rs orchestrate the react/typescript/proposal/compat swc transform passes into an emit.rs codegen step, type_strip.rs offers a fast type-erasure-only path via swc_ts_fast_strip, and cjs_parse.rs handles CommonJS-specific parsing. This is a clean layered design (parse -> optional transform -> optional emit) with feature flags used deliberately to keep the swc dependency graph and compile times manageable for consumers who need only a subset; the README’s manual multi-repo “swc upgrade” runbook is direct evidence of how tightly the core ParsedSource/Program abstraction couples to downstream Deno crates like deno_graph, deno_doc, deno_lint, and eszip.

Tech Stack deno_ast is a pure Rust library (2024 edition) with no runtime dependency beyond the standard library. Its core dependency is a pinned, exact-version set of roughly twenty swc crates (swc_ecma_parser 27.0.7, swc_ecma_ast 18.0.0, swc_ecma_lexer 26.0.0, swc_common 17.0.1, and more), plus dprint-swc-ext for shared source-text/view utilities, url for module specifiers, serde for serialization, thiserror for typed errors, and Deno-ecosystem crates (deno_media_type, deno_terminal, deno_error). Build tooling is stock Cargo with a rust-toolchain.toml pin; a set of Deno-authored TypeScript scripts (scripts/01_setup.ts through 04_confirm.ts) exist purely for the recurring cross-repo “upgrade swc” maintenance workflow, not for building the crate itself. There’s no database, network, or deployment target — it’s a library embedded in other Rust crates and ultimately the Deno CLI.

Code Quality The crate has real, non-trivial test coverage — fourteen source files contain #[test] functions (including parsing.rs, type_strip.rs, cjs_parse.rs, and transpiling/transforms.rs) exercising parsing edge cases, JSX/TS transform output, and CJS analysis, and CI runs cargo test --all-targets --all-features --release plus cargo clippy --all-targets --all-features --release with RUSTFLAGS=-D warnings and cargo fmt --check on every pull request, so warnings and formatting drift fail the build. Error handling is explicit and typed throughout, using thiserror-derived diagnostic enums (diagnostics.rs, ParseDiagnostic) rather than string errors or panics, and public APIs return Result. The crate root also denies several clippy lints (disallowed_methods, unnecessary_wraps, print_stderr, print_stdout), enforcing a stricter-than-default bar. No coverage tooling is visible in CI, but the combination of typed errors, enforced linting, and consistent gating indicates a mature, well-maintained codebase.

What Makes It Unique deno_ast’s distinguishing choice is decoupling itself from strict semver in favor of a documented release policy tied to whether its five downstream consumer crates still compile — an unusual but pragmatic response to swc’s own frequent breaking changes, letting the Deno toolchain absorb monthly swc upgrades centrally in one crate rather than in every consumer. It isn’t inventing a new parser — it wraps swc under feature flags — but it adds real value by unifying MediaType-based syntax selection, capturing tokens and comments in one Arc-shared ParsedSource reusable for lexing, linting, and transpiling without re-parsing, and offering a genuinely fast type-only-stripping path (swc_ts_fast_strip) distinct from a full transform-and-emit pipeline. This is solid engineering and ecosystem-specific innovation — the coordinated multi-repo versioning discipline in particular — rather than a novel parsing algorithm.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search