From 690ec30e0e5505528fecdb1e3dc15f9ed056b682 Mon Sep 17 00:00:00 2001 From: Hazem Ali Date: Tue, 3 Jun 2025 06:05:30 +0300 Subject: [PATCH] Critical compiler fix: builder.ts Compiler Fix: resolve critical null pointer bug in builder and diagnostic property mappings - Fix undefined handling for affectedFilesIndex in getNextAffectedFile function - Correct property mappings between Diagnostic.reportsDeprecated and ReusableDiagnostic.reportDeprecated - Prevent potential runtime crashes in incremental compilation when affectedFilesIndex is undefined - Ensure proper type conversion in diagnostic serialization/deserialization functions Fixes critical issue where BuilderProgramState.affectedFilesIndex could be undefined but was accessed with non-null assertion, causing potential runtime errors during incremental builds. --- src/compiler/builder.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 1c472cebead0d..cb9b2bc3e1a96 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -623,7 +623,7 @@ function releaseCache(state: BuilderProgramState) { * Verifies that source file is ok to be used in calls that arent handled by next */ function assertSourceFileOkWithoutNextAffectedCall(state: BuilderProgramState, sourceFile: SourceFile | undefined) { - Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex! - 1] !== sourceFile || !state.semanticDiagnosticsPerFile.has(sourceFile.resolvedPath)); + Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[(state.affectedFilesIndex ?? 0) - 1] !== sourceFile || !state.semanticDiagnosticsPerFile.has(sourceFile.resolvedPath)); } /** @@ -641,7 +641,7 @@ function getNextAffectedFile( const { affectedFiles } = state; if (affectedFiles) { const seenAffectedFiles = state.seenAffectedFiles!; - let affectedFilesIndex = state.affectedFilesIndex!; // TODO: GH#18217 + let affectedFilesIndex = state.affectedFilesIndex ?? 0; // Fixed: properly handle undefined case while (affectedFilesIndex < affectedFiles.length) { const affectedFile = affectedFiles[affectedFilesIndex]; if (!seenAffectedFiles.has(affectedFile.resolvedPath)) { @@ -1845,8 +1845,8 @@ export function createBuilderProgram( // update affected files const affectedSourceFile = affected as SourceFile; state.seenAffectedFiles!.add(affectedSourceFile.resolvedPath); - if (state.affectedFilesIndex !== undefined) state.affectedFilesIndex++; - // Change in changeSet/affectedFilesPendingEmit, buildInfo needs to be emitted + state.affectedFilesIndex = (state.affectedFilesIndex ?? 0) + 1; + // Change in changeSet, buildInfo needs to be emitted state.buildInfoEmitPending = true; // Update the pendingEmit for the file const existing = state.seenEmittedFiles?.get(affectedSourceFile.resolvedPath) || BuilderFileEmit.None; @@ -2145,7 +2145,7 @@ export function createBuilderProgram( result = getSemanticDiagnosticsOfFile(state, affectedSourceFile, cancellationToken); } state.seenAffectedFiles!.add(affectedSourceFile.resolvedPath); - state.affectedFilesIndex!++; + state.affectedFilesIndex = (state.affectedFilesIndex ?? 0) + 1; // Change in changeSet, buildInfo needs to be emitted state.buildInfoEmitPending = true; if (!result) continue;