Repository navigation
Restart a file's imports when a later arrival lowers its node_modules depth - #64632
Conversation
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The bounded restart logic addresses the root cause and is covered by a focused regression test.
Review effort: Balanced
Findings: None
What changed in this PR
Fixes nondeterministic external-library classification by propagating reduced node_modules depth through already-started imports.
Changes:
- Restarts file subtasks whenever their discovered depth decreases.
- Adds regression coverage for both root-file orderings.
| File | Description |
|---|---|
tsc/internal/compiler/filesparser.go |
Propagates lowered depth through imports. |
tsc/internal/compiler/filesparser_test.go |
Verifies deterministic classification. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
Review effort: Lite
Findings: None
This compiler nightly restarts a file's imports when a later import reaches the file at a lower node_modules depth (microsoft/TypeScript#64632, fixing microsoft/TypeScript#64498). Whether a file comes from an external library no longer depends on which import the compiler followed first, so a project on a monorepo layout that is not read as a workspace gets the same own files, and the same report, on every run.
|
Could this be picked into Through plain Repro with one script and five files: https://github.com/eliseuvideira1/ts7-json-emit-repro. Each compiler is a CI job that fails when any compile skips the JSON file. Compiles out of 30 that wrote it, from https://github.com/eliseuvideira1/ts7-json-emit-repro/actions/runs/42379949272 (GitHub-hosted
With |
|
TypeScript Bot (@typescript-bot) cherry-pick this to release-7.0 |
|
Hey, Jake Bailey (@jakebailey)! I've created #65388 for you. |
When the files parser reaches a file again at a lower depth, it lowers
lowestDepthand setsstartSubtasks, but thestartedSubTasksguard skips the restart because the first arrival already started the file's imports. Those imports keep the first arrival's depth, so a file reached throughnode_modulesfirst and then from a root file without passing throughnode_modulesleaves its own imports insourceFilesFoundSearchingNodeModules, and which arrival comes first depends on scheduling.Impact: in a monorepo where a package is reached both by a relative import and through a
node_moduleslink, which files count as library files changes between identical runs. The same build can then emit different files (#64498), and an analyzer on the API gives a different answer each run: on vitest, 20 opens of one configuration gave five different counts.The change restarts the subtasks whenever the depth drops, even when they were already started. Each restart strictly lowers a file's
lowestDepth, so the extra work is bounded.The compiler test
symlinkedPackageReachedRelativelyIsNotExternalLibraryhasa.tsimport./lib/indexandb.tsimportlibthrough anode_modulessymlink tolib/. Without the change,lib/util.tscounts as from an external library and itsutil.jsis missing from the emit baseline.I met this while building deadset-ts, the TypeScript analyzer of deadset, on the TypeScript 7 API. That work hit a small set of related defects, which is why a few reports come from me.
An AI coding agent wrote this patch. I have read, built and tested it and will handle the review.
Backlogmilestone (required)mainbranchnpx hereby testnpx hereby lintnpx hereby check:formatFixes #64498