From ae2e92000272314c1bb976126c6d91c6f0f0fb81 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 21 Aug 2025 20:44:51 -0700 Subject: [PATCH 1/4] Release program --- internal/execute/build/buildtask.go | 1 + .../incremental/affectedfileshandler.go | 4 +-- .../execute/incremental/emitfileshandler.go | 4 +-- internal/execute/incremental/program.go | 36 +++++++++++-------- internal/execute/tsctests/sys.go | 6 ++-- 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/internal/execute/build/buildtask.go b/internal/execute/build/buildtask.go index 8c32163e30..6769d9d692 100644 --- a/internal/execute/build/buildtask.go +++ b/internal/execute/build/buildtask.go @@ -70,6 +70,7 @@ func (t *buildTask) report(orchestrator *Orchestrator, configPath tspath.Path, b buildResult.programStats = append(buildResult.programStats, t.statistics) } if t.program != nil { + t.program.MakeReadonly() buildResult.result.IncrementalProgram = append(buildResult.result.IncrementalProgram, t.program) buildResult.statistics.ProjectsBuilt++ } diff --git a/internal/execute/incremental/affectedfileshandler.go b/internal/execute/incremental/affectedfileshandler.go index d03a8e8608..6b7d384160 100644 --- a/internal/execute/incremental/affectedfileshandler.go +++ b/internal/execute/incremental/affectedfileshandler.go @@ -324,8 +324,8 @@ func (h *affectedFilesHandler) updateSnapshot() { h.updatedSignatures.Range(func(filePath tspath.Path, update *updatedSignature) bool { if info, ok := h.program.snapshot.fileInfos.Load(filePath); ok { info.signature = update.signature - if h.program.updatedSignatureKinds != nil { - h.program.updatedSignatureKinds[filePath] = update.kind + if h.program.testingData.UpdatedSignatureKinds != nil { + h.program.testingData.UpdatedSignatureKinds[filePath] = update.kind } } return true diff --git a/internal/execute/incremental/emitfileshandler.go b/internal/execute/incremental/emitfileshandler.go index 9ff05cfe19..50ec7b145c 100644 --- a/internal/execute/incremental/emitfileshandler.go +++ b/internal/execute/incremental/emitfileshandler.go @@ -229,8 +229,8 @@ func (h *emitFilesHandler) updateSnapshot() []*compiler.EmitResult { h.signatures.Range(func(file tspath.Path, signature string) bool { info, _ := h.program.snapshot.fileInfos.Load(file) info.signature = signature - if h.program.updatedSignatureKinds != nil { - h.program.updatedSignatureKinds[file] = SignatureUpdateKindStoredAtEmit + if h.program.testingData.UpdatedSignatureKinds != nil { + h.program.testingData.UpdatedSignatureKinds[file] = SignatureUpdateKindStoredAtEmit } h.program.snapshot.buildInfoEmitPending.Store(true) return true diff --git a/internal/execute/incremental/program.go b/internal/execute/incremental/program.go index 09c50e7d19..cdf3a62550 100644 --- a/internal/execute/incremental/program.go +++ b/internal/execute/incremental/program.go @@ -30,11 +30,12 @@ type BuildHost interface { } type Program struct { - snapshot *snapshot - program *compiler.Program - semanticDiagnosticsPerFile *collections.SyncMap[tspath.Path, *diagnosticsOrBuildInfoDiagnosticsWithFileName] - updatedSignatureKinds map[tspath.Path]SignatureUpdateKind - host BuildHost + snapshot *snapshot + program *compiler.Program + host BuildHost + + // Testing data + testingData TestingData } var _ compiler.ProgramLike = (*Program)(nil) @@ -47,12 +48,17 @@ func NewProgram(program *compiler.Program, oldProgram *Program, buildHost BuildH } if testing { + incrementalProgram.testingData.SemanticDiagnosticsPerFile = &incrementalProgram.snapshot.semanticDiagnosticsPerFile if oldProgram != nil { - incrementalProgram.semanticDiagnosticsPerFile = &oldProgram.snapshot.semanticDiagnosticsPerFile + incrementalProgram.testingData.OldProgramSemanticDiagnosticsPerFile = &oldProgram.snapshot.semanticDiagnosticsPerFile } else { - incrementalProgram.semanticDiagnosticsPerFile = &collections.SyncMap[tspath.Path, *diagnosticsOrBuildInfoDiagnosticsWithFileName]{} + incrementalProgram.testingData.OldProgramSemanticDiagnosticsPerFile = &collections.SyncMap[tspath.Path, *diagnosticsOrBuildInfoDiagnosticsWithFileName]{} } - incrementalProgram.updatedSignatureKinds = make(map[tspath.Path]SignatureUpdateKind) + incrementalProgram.testingData.UpdatedSignatureKinds = make(map[tspath.Path]SignatureUpdateKind) + incrementalProgram.testingData.ConfigFilePath = program.Options().ConfigFilePath + incrementalProgram.testingData.Files = core.Map(program.GetSourceFiles(), func(file *ast.SourceFile) ast.HasFileName { + return ast.NewHasFileName(file.FileName(), file.Path()) + }) } return incrementalProgram } @@ -62,15 +68,11 @@ type TestingData struct { OldProgramSemanticDiagnosticsPerFile *collections.SyncMap[tspath.Path, *diagnosticsOrBuildInfoDiagnosticsWithFileName] UpdatedSignatureKinds map[tspath.Path]SignatureUpdateKind ConfigFilePath string + Files []ast.HasFileName } -func (p *Program) GetTestingData(program *compiler.Program) TestingData { - return TestingData{ - SemanticDiagnosticsPerFile: &p.snapshot.semanticDiagnosticsPerFile, - OldProgramSemanticDiagnosticsPerFile: p.semanticDiagnosticsPerFile, - UpdatedSignatureKinds: p.updatedSignatureKinds, - ConfigFilePath: p.snapshot.options.ConfigFilePath, - } +func (p *Program) GetTestingData() TestingData { + return p.testingData } func (p *Program) panicIfNoProgram(method string) { @@ -84,6 +86,10 @@ func (p *Program) GetProgram() *compiler.Program { return p.program } +func (p *Program) MakeReadonly() { + p.program = nil +} + // Options implements compiler.AnyProgram interface. func (p *Program) Options() *core.CompilerOptions { return p.snapshot.options diff --git a/internal/execute/tsctests/sys.go b/internal/execute/tsctests/sys.go index 90b269bac0..3229e9c7bb 100644 --- a/internal/execute/tsctests/sys.go +++ b/internal/execute/tsctests/sys.go @@ -280,7 +280,7 @@ func (s *testSys) baselineProgram(baseline *strings.Builder, program *incrementa return } - testingData := program.GetTestingData(program.GetProgram()) + testingData := program.GetTestingData() if testingData.ConfigFilePath != "" { baseline.WriteString(tspath.GetRelativePathFromDirectory(s.cwd, testingData.ConfigFilePath, tspath.ComparePathsOptions{ UseCaseSensitiveFileNames: s.FS().UseCaseSensitiveFileNames(), @@ -288,7 +288,7 @@ func (s *testSys) baselineProgram(baseline *strings.Builder, program *incrementa }) + "::\n") } baseline.WriteString("SemanticDiagnostics::\n") - for _, file := range program.GetProgram().GetSourceFiles() { + for _, file := range testingData.Files { if diagnostics, ok := testingData.SemanticDiagnosticsPerFile.Load(file.Path()); ok { if oldDiagnostics, ok := testingData.OldProgramSemanticDiagnosticsPerFile.Load(file.Path()); !ok || oldDiagnostics != diagnostics { baseline.WriteString("*refresh* " + file.FileName() + "\n") @@ -300,7 +300,7 @@ func (s *testSys) baselineProgram(baseline *strings.Builder, program *incrementa // Write signature updates baseline.WriteString("Signatures::\n") - for _, file := range program.GetProgram().GetSourceFiles() { + for _, file := range testingData.Files { if kind, ok := testingData.UpdatedSignatureKinds[file.Path()]; ok { switch kind { case incremental.SignatureUpdateKindComputedDts: From 668900635ea61050e8671c4be81fbf534cc92bb7 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 21 Aug 2025 20:47:36 -0700 Subject: [PATCH 2/4] Cache only json and dts files --- internal/execute/build/host.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/execute/build/host.go b/internal/execute/build/host.go index c2621baa7b..a56399c41c 100644 --- a/internal/execute/build/host.go +++ b/internal/execute/build/host.go @@ -114,7 +114,10 @@ func (h *host) GetSourceFile(opts ast.SourceFileParseOptions) *ast.SourceFile { } file := h.host.GetSourceFile(opts) - file, _ = h.sourceFiles.LoadOrStore(opts, file) + // Cache dts and json files as they will reused + if file != nil && (tspath.IsDeclarationFileName(file.FileName()) || tspath.FileExtensionIs(file.FileName(), tspath.ExtensionJson)) { + file, _ = h.sourceFiles.LoadOrStore(opts, file) + } return file } From b5939e9c17b4ecebff35436208888cd2e68e72e3 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 21 Aug 2025 21:10:46 -0700 Subject: [PATCH 3/4] Remove snapshots retention from tsc -b (we will retain them when we implement --w but in orchestrator) --- internal/execute/build/buildtask.go | 4 +- .../incremental/affectedfileshandler.go | 2 +- .../execute/incremental/emitfileshandler.go | 2 +- internal/execute/incremental/program.go | 12 ++--- internal/execute/tsc.go | 6 ++- internal/execute/tsc/compile.go | 6 +-- internal/execute/tsctests/runner.go | 7 ++- internal/execute/tsctests/sys.go | 49 +++++++++---------- internal/execute/watcher.go | 3 ++ 9 files changed, 45 insertions(+), 46 deletions(-) diff --git a/internal/execute/build/buildtask.go b/internal/execute/build/buildtask.go index 6769d9d692..2d022b945f 100644 --- a/internal/execute/build/buildtask.go +++ b/internal/execute/build/buildtask.go @@ -70,8 +70,10 @@ func (t *buildTask) report(orchestrator *Orchestrator, configPath tspath.Path, b buildResult.programStats = append(buildResult.programStats, t.statistics) } if t.program != nil { + if orchestrator.opts.Testing != nil { + orchestrator.opts.Testing.OnProgram(t.program) + } t.program.MakeReadonly() - buildResult.result.IncrementalProgram = append(buildResult.result.IncrementalProgram, t.program) buildResult.statistics.ProjectsBuilt++ } if t.pseudoBuild { diff --git a/internal/execute/incremental/affectedfileshandler.go b/internal/execute/incremental/affectedfileshandler.go index 6b7d384160..355b58aec8 100644 --- a/internal/execute/incremental/affectedfileshandler.go +++ b/internal/execute/incremental/affectedfileshandler.go @@ -324,7 +324,7 @@ func (h *affectedFilesHandler) updateSnapshot() { h.updatedSignatures.Range(func(filePath tspath.Path, update *updatedSignature) bool { if info, ok := h.program.snapshot.fileInfos.Load(filePath); ok { info.signature = update.signature - if h.program.testingData.UpdatedSignatureKinds != nil { + if h.program.testingData != nil { h.program.testingData.UpdatedSignatureKinds[filePath] = update.kind } } diff --git a/internal/execute/incremental/emitfileshandler.go b/internal/execute/incremental/emitfileshandler.go index 50ec7b145c..273d0a7319 100644 --- a/internal/execute/incremental/emitfileshandler.go +++ b/internal/execute/incremental/emitfileshandler.go @@ -229,7 +229,7 @@ func (h *emitFilesHandler) updateSnapshot() []*compiler.EmitResult { h.signatures.Range(func(file tspath.Path, signature string) bool { info, _ := h.program.snapshot.fileInfos.Load(file) info.signature = signature - if h.program.testingData.UpdatedSignatureKinds != nil { + if h.program.testingData != nil { h.program.testingData.UpdatedSignatureKinds[file] = SignatureUpdateKindStoredAtEmit } h.program.snapshot.buildInfoEmitPending.Store(true) diff --git a/internal/execute/incremental/program.go b/internal/execute/incremental/program.go index cdf3a62550..cd10bca861 100644 --- a/internal/execute/incremental/program.go +++ b/internal/execute/incremental/program.go @@ -35,7 +35,7 @@ type Program struct { host BuildHost // Testing data - testingData TestingData + testingData *TestingData } var _ compiler.ProgramLike = (*Program)(nil) @@ -48,6 +48,7 @@ func NewProgram(program *compiler.Program, oldProgram *Program, buildHost BuildH } if testing { + incrementalProgram.testingData = &TestingData{} incrementalProgram.testingData.SemanticDiagnosticsPerFile = &incrementalProgram.snapshot.semanticDiagnosticsPerFile if oldProgram != nil { incrementalProgram.testingData.OldProgramSemanticDiagnosticsPerFile = &oldProgram.snapshot.semanticDiagnosticsPerFile @@ -55,10 +56,6 @@ func NewProgram(program *compiler.Program, oldProgram *Program, buildHost BuildH incrementalProgram.testingData.OldProgramSemanticDiagnosticsPerFile = &collections.SyncMap[tspath.Path, *diagnosticsOrBuildInfoDiagnosticsWithFileName]{} } incrementalProgram.testingData.UpdatedSignatureKinds = make(map[tspath.Path]SignatureUpdateKind) - incrementalProgram.testingData.ConfigFilePath = program.Options().ConfigFilePath - incrementalProgram.testingData.Files = core.Map(program.GetSourceFiles(), func(file *ast.SourceFile) ast.HasFileName { - return ast.NewHasFileName(file.FileName(), file.Path()) - }) } return incrementalProgram } @@ -67,11 +64,9 @@ type TestingData struct { SemanticDiagnosticsPerFile *collections.SyncMap[tspath.Path, *diagnosticsOrBuildInfoDiagnosticsWithFileName] OldProgramSemanticDiagnosticsPerFile *collections.SyncMap[tspath.Path, *diagnosticsOrBuildInfoDiagnosticsWithFileName] UpdatedSignatureKinds map[tspath.Path]SignatureUpdateKind - ConfigFilePath string - Files []ast.HasFileName } -func (p *Program) GetTestingData() TestingData { +func (p *Program) GetTestingData() *TestingData { return p.testingData } @@ -88,6 +83,7 @@ func (p *Program) GetProgram() *compiler.Program { func (p *Program) MakeReadonly() { p.program = nil + p.testingData = nil } // Options implements compiler.AnyProgram interface. diff --git a/internal/execute/tsc.go b/internal/execute/tsc.go index cac0195ce4..1d31a884cb 100644 --- a/internal/execute/tsc.go +++ b/internal/execute/tsc.go @@ -290,9 +290,11 @@ func performIncrementalCompilation( compileTimes, testing, ) + if testing != nil { + testing.OnProgram(incrementalProgram) + } return tsc.CommandLineResult{ - Status: result.Status, - IncrementalProgram: []*incremental.Program{incrementalProgram}, + Status: result.Status, } } diff --git a/internal/execute/tsc/compile.go b/internal/execute/tsc/compile.go index cceb0f4c96..8d3c90b0cb 100644 --- a/internal/execute/tsc/compile.go +++ b/internal/execute/tsc/compile.go @@ -40,9 +40,8 @@ type Watcher interface { } type CommandLineResult struct { - Status ExitStatus - IncrementalProgram []*incremental.Program - Watcher Watcher + Status ExitStatus + Watcher Watcher } type CommandLineTesting interface { @@ -55,6 +54,7 @@ type CommandLineTesting interface { OnBuildStatusReportStart(w io.Writer) OnBuildStatusReportEnd(w io.Writer) GetTrace(w io.Writer) func(msg string) + OnProgram(program *incremental.Program) } type CompileTimes struct { diff --git a/internal/execute/tsctests/runner.go b/internal/execute/tsctests/runner.go index efaf923e50..37fe3b8c38 100644 --- a/internal/execute/tsctests/runner.go +++ b/internal/execute/tsctests/runner.go @@ -80,7 +80,7 @@ func (test *tscInput) run(t *testing.T, scenario string) { sys.baselineFSwithDiff(baselineBuilder) result := test.executeCommand(sys, baselineBuilder, test.commandLineArgs) sys.serializeState(baselineBuilder) - sys.baselinePrograms(baselineBuilder, result.IncrementalProgram, result.Watcher) + sys.baselinePrograms(baselineBuilder) var unexpectedDiff string for index, do := range test.edits { @@ -95,14 +95,13 @@ func (test *tscInput) run(t *testing.T, scenario string) { } sys.baselineFSwithDiff(baselineBuilder) - var editResult tsc.CommandLineResult if result.Watcher == nil { - editResult = test.executeCommand(sys, baselineBuilder, commandLineArgs) + result = test.executeCommand(sys, baselineBuilder, commandLineArgs) } else { result.Watcher.DoCycle() } sys.serializeState(baselineBuilder) - sys.baselinePrograms(baselineBuilder, editResult.IncrementalProgram, result.Watcher) + sys.baselinePrograms(baselineBuilder) }) wg.Queue(func() { // Compute build with all the edits diff --git a/internal/execute/tsctests/sys.go b/internal/execute/tsctests/sys.go index 3229e9c7bb..62f10bde25 100644 --- a/internal/execute/tsctests/sys.go +++ b/internal/execute/tsctests/sys.go @@ -140,6 +140,7 @@ type snapshot struct { type testSys struct { currentWrite *strings.Builder + programBaselines strings.Builder tracer *harnessutil.TracerForBaselining serializedDiff *snapshot forIncrementalCorrectness bool @@ -263,57 +264,53 @@ func (s *testSys) GetTrace(w io.Writer) func(str string) { } } -func (s *testSys) baselinePrograms(baseline *strings.Builder, programs []*incremental.Program, watcher tsc.Watcher) { - if watcher != nil { - programs = []*incremental.Program{watcher.GetProgram()} - } - for index, program := range programs { - if index > 0 { - baseline.WriteString("\n") - } - s.baselineProgram(baseline, program) - } -} - -func (s *testSys) baselineProgram(baseline *strings.Builder, program *incremental.Program) { - if program == nil { - return +func (s *testSys) OnProgram(program *incremental.Program) { + if s.programBaselines.Len() != 0 { + s.programBaselines.WriteString("\n") } testingData := program.GetTestingData() - if testingData.ConfigFilePath != "" { - baseline.WriteString(tspath.GetRelativePathFromDirectory(s.cwd, testingData.ConfigFilePath, tspath.ComparePathsOptions{ + if configFilePath := program.Options().ConfigFilePath; configFilePath != "" { + s.programBaselines.WriteString(tspath.GetRelativePathFromDirectory(s.cwd, configFilePath, tspath.ComparePathsOptions{ UseCaseSensitiveFileNames: s.FS().UseCaseSensitiveFileNames(), CurrentDirectory: s.GetCurrentDirectory(), }) + "::\n") } - baseline.WriteString("SemanticDiagnostics::\n") - for _, file := range testingData.Files { + s.programBaselines.WriteString("SemanticDiagnostics::\n") + for _, file := range program.GetProgram().GetSourceFiles() { if diagnostics, ok := testingData.SemanticDiagnosticsPerFile.Load(file.Path()); ok { if oldDiagnostics, ok := testingData.OldProgramSemanticDiagnosticsPerFile.Load(file.Path()); !ok || oldDiagnostics != diagnostics { - baseline.WriteString("*refresh* " + file.FileName() + "\n") + s.programBaselines.WriteString("*refresh* " + file.FileName() + "\n") } } else { - baseline.WriteString("*not cached* " + file.FileName() + "\n") + s.programBaselines.WriteString("*not cached* " + file.FileName() + "\n") } } // Write signature updates - baseline.WriteString("Signatures::\n") - for _, file := range testingData.Files { + s.programBaselines.WriteString("Signatures::\n") + for _, file := range program.GetProgram().GetSourceFiles() { if kind, ok := testingData.UpdatedSignatureKinds[file.Path()]; ok { switch kind { case incremental.SignatureUpdateKindComputedDts: - baseline.WriteString("(computed .d.ts) " + file.FileName() + "\n") + s.programBaselines.WriteString("(computed .d.ts) " + file.FileName() + "\n") case incremental.SignatureUpdateKindStoredAtEmit: - baseline.WriteString("(stored at emit) " + file.FileName() + "\n") + s.programBaselines.WriteString("(stored at emit) " + file.FileName() + "\n") case incremental.SignatureUpdateKindUsedVersion: - baseline.WriteString("(used version) " + file.FileName() + "\n") + s.programBaselines.WriteString("(used version) " + file.FileName() + "\n") } } } } +func (s *testSys) baselinePrograms(baseline *strings.Builder) { + baseline.WriteString(s.programBaselines.String()) + s.programBaselines.Reset() +} + +func (s *testSys) baselineProgram(program *incremental.Program) { +} + func (s *testSys) serializeState(baseline *strings.Builder) { s.baselineOutput(baseline) s.baselineFSwithDiff(baseline) diff --git a/internal/execute/watcher.go b/internal/execute/watcher.go index d2cd8b6f4c..702ed36b33 100644 --- a/internal/execute/watcher.go +++ b/internal/execute/watcher.go @@ -86,6 +86,9 @@ func (w *Watcher) DoCycle() { // print something??? // fmt.Fprintln(w.sys.Writer(), "no changes detected at ", w.sys.Now()) } + if w.testing != nil { + w.testing.OnProgram(w.program) + } } func (w *Watcher) compileAndEmit() { From 0a3377529210312614ba00c31c195136b321fdab Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 21 Aug 2025 21:13:40 -0700 Subject: [PATCH 4/4] Update internal/execute/build/host.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- internal/execute/build/host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/execute/build/host.go b/internal/execute/build/host.go index a56399c41c..e9554f32ad 100644 --- a/internal/execute/build/host.go +++ b/internal/execute/build/host.go @@ -114,7 +114,7 @@ func (h *host) GetSourceFile(opts ast.SourceFileParseOptions) *ast.SourceFile { } file := h.host.GetSourceFile(opts) - // Cache dts and json files as they will reused + // Cache dts and json files as they will be reused if file != nil && (tspath.IsDeclarationFileName(file.FileName()) || tspath.FileExtensionIs(file.FileName(), tspath.ExtensionJson)) { file, _ = h.sourceFiles.LoadOrStore(opts, file) }