You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue was investigated and written by an AI (Claude), supervised by @NullVoxPopuli. Apologies in advance for any incorrectness — the measurements are real, but the mechanism analysis is a hypothesis and clearly labeled as such.
Summary
Under runTsc in solution-builder watch mode (tsc -b --watch), every watch iteration reconstructs the changed project's Program from scratch: all source files re-parse and the entire module graph re-resolves, even for a one-line change. Plain --watch (createWatchProgram path) through the same proxy reuses the old program correctly.
Measurements
One-line edit in a 19,286-file project (glint's ember-tsc, @volar/typescript 2.4.28, TS 6.0.3, 59-project composite monorepo), --extendedDiagnostics:
phase
-b --watch iteration
plain --watch iteration
Parse
7.29s
0.00s
ResolveModule
7.22s
0.03s
Program
27.57s
1.80s
Check
0.14s
0.15s
Total
29.98s
2.14s
The -b --watch iteration costs the same as that project's initial cold build (29.03s) — only diagnostics scoping (buildinfo layer) survives; in-memory SourceFile/resolution reuse does not.
Suspected mechanism (unproven)
Two candidates in proxyCreateProgram:
options.host = { ...originalHost } with a fresh getSourceFile closure on every createProgram call — the solution builder's per-project rebuilds may lose SourceFile reuse through the re-wrapped host.
When a plugin sets resolveHiddenExtensions (glint does), every module literal resolves through the proxy's wrapper, bypassing TS's reused-resolution fast path (structureIsReused).
Happy to run further instrumentation (--cpu-prof, checking whether oldProgram survives through the proxy) if useful.
Context
Historical: incremental mode is not yet support vuejs/language-tools#787 ("incremental mode is not yet support", 2022) — guidance then was to disable composite/incremental entirely; it appears this was never revisited. Composite -b --watch is rare for vue-tsc users but is the primary mode for TS project-references monorepos using glint.
Note
This issue was investigated and written by an AI (Claude), supervised by @NullVoxPopuli. Apologies in advance for any incorrectness — the measurements are real, but the mechanism analysis is a hypothesis and clearly labeled as such.
Summary
Under
runTscin solution-builder watch mode (tsc -b --watch), every watch iteration reconstructs the changed project'sProgramfrom scratch: all source files re-parse and the entire module graph re-resolves, even for a one-line change. Plain--watch(createWatchProgram path) through the same proxy reuses the old program correctly.Measurements
One-line edit in a 19,286-file project (glint's
ember-tsc,@volar/typescript2.4.28, TS 6.0.3, 59-project composite monorepo),--extendedDiagnostics:-b --watchiteration--watchiterationThe
-b --watchiteration costs the same as that project's initial cold build (29.03s) — only diagnostics scoping (buildinfo layer) survives; in-memory SourceFile/resolution reuse does not.Suspected mechanism (unproven)
Two candidates in
proxyCreateProgram:options.host = { ...originalHost }with a freshgetSourceFileclosure on everycreateProgramcall — the solution builder's per-project rebuilds may lose SourceFile reuse through the re-wrapped host.resolveHiddenExtensions(glint does), every module literal resolves through the proxy's wrapper, bypassing TS's reused-resolution fast path (structureIsReused).Happy to run further instrumentation (
--cpu-prof, checking whetheroldProgramsurvives through the proxy) if useful.Context
composite/incrementalentirely; it appears this was never revisited. Composite-b --watchis rare for vue-tsc users but is the primary mode for TS project-references monorepos using glint.tsc -bdeclaration emit crashes with "Extension .xxx is unsupported" for strippedextraSupportedExtensions#312/fix(typescript): map stripped extensions to .js in tryGetJSExtensionForFile #313 (other-b-mode gaps in the same machinery).🤖 Generated with Claude Code