Skip to content

fix: answer without an import graph where TypeScript is the native 7 - #384

Closed
alexander-akait wants to merge 2 commits into
mainfrom
fix/import-graph-typescript-7
Closed

alexander-akait wants to merge 2 commits into
mainfrom
fix/import-graph-typescript-7

Conversation

@alexander-akait

Copy link
Copy Markdown
Member

Part of the performance series (#376–#383).

Problem

The import graph (src/import-graph.js) loads the project's own typescript. TypeScript 7's package is the native compiler, and its JavaScript entry exports only { version, versionMajorMinor }. getGraph built a graph on it anyway, and the first read through ts.sys / preProcessFile threw:

[eslint] Cannot read properties of undefined (reading 'readFile')

That's what the current main reports for a project whose node_modules/typescript is a TypeScript-7-shaped module.

Change

getGraph only builds a graph from a TypeScript that has preProcessFile, resolveModuleName and sys. Anything else is answered as a TypeScript that couldn't be loaded, which every caller already handles:

  • ESLint turns its own cache off for typed linting;
  • a rebuild lints every file.

Keeping the pruning on TypeScript 7 would need an import scanner that doesn't depend on TypeScript. That's a separate, larger change, alongside running the TypeScript check on tsgo.

Measured

The project above, with the ESLint check under typed linting:

errors
main [eslint] Cannot read properties of undefined (reading 'readFile')
this PR none: all files linted, nothing reused

Tests

  • New: a project whose typescript exports only a version gets no graph. With the guard disabled, the test fails.
  • Full suite: 315/315, global module path cleared, as on CI. eslint, tsc, prettier, cspell and lint:schema are clean.
  • README (readsAcrossFiles) and a changeset are updated.

Generated by Claude Code

TypeScript 7's package is a native compiler and exports only its
version. Loaded as the project's TypeScript, it made a graph whose
first read threw: a rebuild of oxlint or Biome swallowed it and linted
every file, and typed ESLint's signatures failed the check with
"Cannot read properties of undefined (reading 'readFile')".

The graph is now made only from a TypeScript with `preProcessFile`,
`resolveModuleName` and `sys`; anything else is answered as one that
cannot be loaded, which every caller already falls back from.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01App18sYbe6Vf6HDCjCXbvf
@linux-foundation-easycla

linux-foundation-easycla Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

CLA Not Signed

One or more co-authors of this pull request were not found. You must specify co-authors in commit message trailer via:

Co-authored-by: name <email>

Supported Co-authored-by: formats include:

  1. Anything <id+login@users.noreply.github.com> - it will locate your GitHub user by id part.
  2. Anything <login@users.noreply.github.com> - it will locate your GitHub user by login part.
  3. Anything <public-email> - it will locate your GitHub user by public-email part. Note that this email must be made public on Github.
  4. Anything <other-email> - it will locate your GitHub user by other-email part but only if that email was used before for any other CLA as a main commit author.
  5. login <any-valid-email> - it will locate your GitHub user by login part, note that login part must be at least 3 characters long.

Alternatively, if the co-author should not be included, remove the Co-authored-by: line from the commit message.

Please update your commit message(s) by doing git commit --amend and then git push [--force] and then request re-running CLA check via commenting on this pull request:

/easycla

@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 15 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 33090342-fcb2-4165-a1da-28c141b72eea
📥 Commits

Reviewing files that changed from the base of the PR and between f62bdb5 and 090fdbb.

📒 Files selected for processing: 4
  • .changeset/import-graph-typescript-7.md
  • README.md
  • src/import-graph.js
  • test/import-graph.test.js
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.64%. Comparing base (f62bdb5) to head (090fdbb).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #384   +/-   ##
=======================================
  Coverage   99.64%   99.64%           
=======================================
  Files          19       19           
  Lines        5570     5630   +60     
=======================================
+ Hits         5550     5610   +60     
  Misses         20       20           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01App18sYbe6Vf6HDCjCXbvf

Copy link
Copy Markdown
Member Author

EasyCLA fails because the commits carry a Co-Authored-By: Claude trailer that maps to no GitHub account. It is not a code failure. Whether to drop the trailer or accept the check is for the maintainers to decide, so I haven't rewritten history.


Generated by Claude Code

alexander-akait added a commit that referenced this pull request Oct 29, 2026
…red TypeScript runs (#392)

* perf: watch rebuilds, TypeScript 7, and shared or stopped TypeScript runs

One change in place of #371, #384, #387, #389, #390 and #391.

Core:
- One place keeps what lives as long as a compiler (src/compiler-state.js):
  keptFor() for state kept per compiler (results, detached reports, the
  import graph, the TypeScript program), and acquire()/release() for the
  workers and processes compilers share, started once per key and stopped
  when the last compiler using them shuts down or closes its watch. The
  TypeScript check's worker and TypeScript 7's process both go through it,
  in place of a lifecycle of their own each.
- lintDependentsAfterBuild (opt-in): a watch rebuild of a check that reads
  across files lints only what webpack rebuilt, and what the change
  reaches after the build.
- A check can stop a run of an older compilation nothing will report
  (cancel()); one another compiler joined is never stopped.
- Biome and oxlint are handed every file at once rather than in batches.

TypeScript:
- TypeScript 7 runs through the API it ships, in a process of its own
  kept open while webpack watches; the import graph answers without a
  graph there.
- A stale run stops between files; compilers checking the same project
  alike share one worker and one program.

Nothing is listed by hand where the tool can say it: assets and the
scripts a config file picks up are told apart by the extensions
TypeScript reads, the fallback resolution mode and the error category
come from the loaded TypeScript, and each run carries its own stop flag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01App18sYbe6Vf6HDCjCXbvf

* test: cover the TypeScript 7 check's error paths rather than ignore them

The line under a diagnostic is printed from the text the native compiler
checked (Program.getSourceFile) rather than read from disk again, and a
file gone since webpack saw it is told by statSync without throwing, so
neither needs a catch. A project with no tsconfig.json above it is now
tested from a directory outside this repository.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01App18sYbe6Vf6HDCjCXbvf

* fix: match the files webpack saw change against the native compiler's on Windows

webpack names a changed file with the platform's separators, the native
compiler with forward slashes, and Windows tells no case apart, so both
are now compared by the same key. The cancel test accepts a run already
stopped by the time it looks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01App18sYbe6Vf6HDCjCXbvf

* fix: take turns on a shared TypeScript 7 process, and forget a stopped run

Compilers checking the same project share the native compiler's process,
and a run replaces the snapshot and disposes of the last one, which a run
for another compiler could still be reading: runs on one process now take
turns. A run stopped for a newer compilation found nothing, so it is no
longer kept as what a rebuild the program does not see is answered with.
A directory no config file covers is now tested in the import graph.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01App18sYbe6Vf6HDCjCXbvf

* refactor: check TypeScript 7 through its 7.1 API, and drop what did not pay off

TypeScript 7.1 ships its API as typescript/async, makes snapshots with
createSnapshot and snapshot.update, and formats diagnostics itself. The
native check now uses that API, found by what the package exports rather
than by its version, and TypeScript's own formatter in place of one
written here. TypeScript 7.0's API was an unstable preview with none of
these calls; a TypeScript offering no API to check with now says so.

Measured again on this branch, two additions did not earn their place:
- lintDependentsAfterBuild finished the build sooner but printed an
  error it found in an importer no sooner (1.96-2.64 s against
  2.09-2.21 s without it), at the cost of an option and a second report.
- cancel() on the checker API only ever served a TypeScript 6 check on
  a worker reporting as advisory, and TypeScript 7 does not use it.
Both are removed, with what they needed: a stop flag per worker run,
bookkeeping of which runs another compiler joined, and their tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01App18sYbe6Vf6HDCjCXbvf

* fix: watch the config files a TypeScript 7 project extends, and let a run finish before closing

The native check reported only the root config file to the watcher, so an
edit to a config file it extends, outside the folder watched, went
unnoticed unless webpack's own tsconfig resolution happened to watch it.
It now reports every config file the program names (getConfigFileNames),
and tells the compiler of a change to one as a change rather than a new
file. Closing the native process now waits for a run still going.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01App18sYbe6Vf6HDCjCXbvf

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants