Repository navigation
perf(cli): parse TypeScript dependencies with oxc-parser [RED-1160] [ship] - #1533
Conversation
Findings1. Where the time wentCPU profile of
2. Parser comparison (same 170 files, warm runs)
3. End-to-end perf testSetup:
Same output: at 170 files, the synthesized project payload is byte-identical between 4. TypeScript 7 reproA minimal project with one browser check (
5. Safety net and other runtimes
6. Is oxc maintained well enough?
Risks and mitigations:
7. What's left (follow-ups)
|
|
@sorccu what do you think about making this switch? You know the check-parser and bundler better than anyone, so I'd value your take before we go further. The short version (details in the comment above):
Things I'd especially like your opinion on:
|
Review: backwards compatibilityValid existing projects keep working. Beyond the PR's own parity test, I compared oxc and typescript-estree on about 90 more TypeScript constructs (overloads, abstract members, When existing projects break1. oxc rejects some TypeScript that typescript-estree accepted (hard failure). typescript-estree lets through errors that
All of these except the The reverse also happens: oxc accepts octal literals and Suggested fix: when oxc reports a syntax error and typescript-estree can be loaded, re-parse that one file with typescript-estree before failing. That keeps 2.
When parsing throws,
3. Environments where the native binary can't load. Examples:
Improvements: projects on TypeScript 7 now bundle, and TypeScript check files now parse without Other findings
On the four open questions
🤖 Generated with Claude Code |
Correction to my review: the missing-binary case and the fallback's futureQuestion 1 (native dependency). I called a missing binary combined with TypeScript 7 "the case I'd guard against". That overstated it. When the oxc binary is missing (npm's lockfile bug npm/cli#4828,
So a missing binary never turns a working project into a failing one. TypeScript 7 users just don't get the fix, and they see the old
The suggestion still stands, with lower priority: when oxc failed to load and the fallback also fails, the error should name the oxc failure and give the reinstall fix. Question 3 (keeping typescript-estree). "Keep it while write-back and deploy-diff depend on it" is right, but it should also say what replaces it afterwards:
🤖 Generated with Claude Code |
b665919 to
ff7c446
Compare
Finding the imports of TypeScript check files used typescript-estree, which loads the whole TypeScript compiler from the user's project. That costs ~140ms on every deploy, test and pw-test even for tiny projects, and breaks with TypeScript 7, which typescript-estree doesn't support: any project with typescript@7 failed to bundle TypeScript checks with "Cannot read properties of undefined (reading 'Cjs'/'Intrinsic')". oxc-parser is a native (Rust) parser with an ESTree-compatible AST, so the existing visitors keep working unchanged and the same dependencies are found. It doesn't need TypeScript at all. If its native binding can't be loaded, the parser falls back to typescript-estree. tsconfig.json and other JSON-with-comments files are now parsed with json5 instead of TypeScript's JSON parser, for the same reasons. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ED-1160] When oxc-parser can't load, TypeScript files are parsed with typescript-estree instead. If that fails too (TypeScript isn't installed, or its version isn't supported, e.g. TypeScript 7), the error now also includes why oxc-parser failed to load, which explains how to fix the install. Syntax errors in the parsed file are reported unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
json5 is a hard dependency and no longer needs a lazily loaded parser with a JSON.parse fallback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An edge case that failed in both parsers used to count as a match, which hid that `accessor` class fields couldn't be walked. Edge cases now must parse without errors, the syntax error is its own case, and the grammar errors oxc rejects but typescript-estree accepts are recorded as tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ff7c446 to
cbac804
Compare
Linear: RED-1160
Affected Components
What
To bundle a check, the CLI walks its import graph. For TypeScript files it found imports with
@typescript-eslint/typescript-estree, which loads the whole TypeScript compiler from the user's project. That has two problems:deploy/test/pw-test, and parsing is slow on top of that.typescript-estreesupportstypescript >=4.8.4 <6.1.0, andnpm i -D typescriptnow installs 7.x. In a project withtypescript@7, bundling TypeScript browser, multi-step or Playwright checks fails withDependencyParseError … Cannot read properties of undefined (reading 'Cjs')(or'Intrinsic', depending on the npm layout).This PR parses TypeScript dependencies with
oxc-parser, a native Rust parser (the parser inside Rolldown/Vite 8). Bundling gets ~140–320ms faster depending on project size, and TypeScript 7 projects bundle again. Benchmarks and the TypeScript 7 repro are in this comment.Changes
check-parser/parser.ts: TypeScript files are parsed withoxc-parser.acorn-walkvisitors run unchanged and find the same dependencies, includingimport type. Dynamicimport(),import x = require()and anything inside TS/JSX nodes are still skipped..d.ts/.d.mts/.d.cts/.d.*.tsfiles are parsed in declaration mode.Unexpected token (3:13).--omit=optional, npm's optional-dependency lockfile bug,node_modulescopied from another OS), the CLI falls back totypescript-estree, exactly as before. If the fallback fails too (TypeScript not installed, or TypeScript 7), the error also names the oxc-parser load failure, whose message explains how to reinstall.tsconfig.jsonparsing: JSON with comments is parsed withjson5, already a dependency, instead of TypeScript'sparseJsonText. It now works regardless of the TypeScript version, or without TypeScript installed. The lazy parser state machine and itsJSON.parsefallback are gone.package.json: addsoxc-parser, pinned to an exact version (0.153.0) because oxc is pre-1.0 and releases weekly.Not in this PR:
write-back/deploy-diffstill usetypescript-estree, because they read its token stream. Both are best effort, so on TypeScript 7 the deploy preview loses source details but doesn't fail.Behaviour changes
tscreported, e.g.const xwithout an initializer,awaitas an identifier in a script-style.tsfile, a getter with parameters, orimport.metain a.ctsfile. These now fail with aDependencyParseError. Almost all of them would also fail when the check runs.tsconfig.jsonfiles are ignored. TypeScript's JSON parser recovered from errors such as a missing comma, and treated an empty file as{}. JSON5 rejects them, so the file is skipped as if it didn't exist.Notes for the Reviewer
ts-parser-parity.spec.tsasserts that oxc and typescript-estree find identical dependencies for every TypeScript file in the check-parser fixtures,examples/andbenchmarks/, plus edge cases that must parse cleanly in both. It also records the grammar errors oxc rejects but typescript-estree accepts, and covers the fallback's error reporting.mainand this branch.🤖 Generated with Claude Code