Skip to content

Commit e0293b5

Browse files
authored
Instead of computing signatures during building, compute them afterwards for verification (#51718)
This helps with finding issues with d.ts emit because of caching.
1 parent dc3daa6 commit e0293b5

22 files changed

+123
-740
lines changed

src/compiler/builder.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,8 @@ function hasSameKeys(map1: ReadonlyCollection<string> | undefined, map2: Readonl
286286
/**
287287
* Create the state so that we can iterate on changedFiles/affected files
288288
*/
289-
function createBuilderProgramState(newProgram: Program, oldState: Readonly<ReusableBuilderProgramState> | undefined, disableUseFileVersionAsSignature: boolean | undefined): BuilderProgramState {
290-
const state = BuilderState.create(newProgram, oldState, disableUseFileVersionAsSignature) as BuilderProgramState;
289+
function createBuilderProgramState(newProgram: Program, oldState: Readonly<ReusableBuilderProgramState> | undefined): BuilderProgramState {
290+
const state = BuilderState.create(newProgram, oldState, /*disableUseFileVersionAsSignature*/ false) as BuilderProgramState;
291291
state.program = newProgram;
292292
const compilerOptions = newProgram.getCompilerOptions();
293293
state.compilerOptions = compilerOptions;
@@ -699,7 +699,7 @@ function handleDtsMayChangeOf(
699699
sourceFile,
700700
cancellationToken,
701701
host,
702-
!host.disableUseFileVersionAsSignature
702+
/*useFileVersionAsSignature*/ true
703703
);
704704
// If not dts emit, nothing more to do
705705
if (getEmitDeclarations(state.compilerOptions)) {
@@ -1312,7 +1312,7 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos
13121312
return oldProgram;
13131313
}
13141314

1315-
const state = createBuilderProgramState(newProgram, oldState, host.disableUseFileVersionAsSignature);
1315+
const state = createBuilderProgramState(newProgram, oldState);
13161316
newProgram.getBuildInfo = bundle => getBuildInfo(state, bundle);
13171317

13181318
// To ensure that we arent storing any references to old program or new program without state

src/compiler/builderPublic.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,6 @@ export interface BuilderProgramHost {
3030
* this callback if present would be used to write files
3131
*/
3232
writeFile?: WriteFileCallback;
33-
/**
34-
* disable using source file version as signature for testing
35-
*
36-
* @internal
37-
*/
38-
disableUseFileVersionAsSignature?: boolean;
3933
/**
4034
* Store the list of files that update signature during the emit
4135
*

src/compiler/builderState.ts

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ export namespace BuilderState {
295295
/**
296296
* Creates the state of file references and signature for the new program from oldState if it is safe
297297
*/
298-
export function create(newProgram: Program, oldState?: Readonly<BuilderState>, disableUseFileVersionAsSignature?: boolean): BuilderState {
298+
export function create(newProgram: Program, oldState: Readonly<BuilderState> | undefined, disableUseFileVersionAsSignature: boolean): BuilderState {
299299
const fileInfos = new Map<Path, FileInfo>();
300300
const options = newProgram.getCompilerOptions();
301301
const isOutFile = outFile(options);
@@ -402,6 +402,32 @@ export namespace BuilderState {
402402
(state.hasCalledUpdateShapeSignature ||= new Set()).add(path);
403403
}
404404

405+
export function computeDtsSignature(
406+
programOfThisState: Program,
407+
sourceFile: SourceFile,
408+
cancellationToken: CancellationToken | undefined,
409+
host: HostForComputeHash,
410+
onNewSignature: (signature: string, sourceFiles: readonly SourceFile[]) => void,
411+
) {
412+
programOfThisState.emit(
413+
sourceFile,
414+
(fileName, text, _writeByteOrderMark, _onError, sourceFiles, data) => {
415+
Debug.assert(isDeclarationFileName(fileName), `File extension for signature expected to be dts: Got:: ${fileName}`);
416+
onNewSignature(computeSignatureWithDiagnostics(
417+
programOfThisState,
418+
sourceFile,
419+
text,
420+
host,
421+
data,
422+
), sourceFiles!);
423+
},
424+
cancellationToken,
425+
/*emitOnlyDtsFiles*/ true,
426+
/*customTransformers*/ undefined,
427+
/*forceDtsEmit*/ true
428+
);
429+
}
430+
405431
/**
406432
* Returns if the shape of the signature has changed since last emit
407433
*/
@@ -420,26 +446,12 @@ export namespace BuilderState {
420446
const prevSignature = info.signature;
421447
let latestSignature: string | undefined;
422448
if (!sourceFile.isDeclarationFile && !useFileVersionAsSignature) {
423-
programOfThisState.emit(
424-
sourceFile,
425-
(fileName, text, _writeByteOrderMark, _onError, sourceFiles, data) => {
426-
Debug.assert(isDeclarationFileName(fileName), `File extension for signature expected to be dts: Got:: ${fileName}`);
427-
latestSignature = computeSignatureWithDiagnostics(
428-
programOfThisState,
429-
sourceFile,
430-
text,
431-
host,
432-
data,
433-
);
434-
if (latestSignature !== prevSignature) {
435-
updateExportedModules(state, sourceFile, sourceFiles![0].exportedModulesFromDeclarationEmit);
436-
}
437-
},
438-
cancellationToken,
439-
/*emitOnlyDtsFiles*/ true,
440-
/*customTransformers*/ undefined,
441-
/*forceDtsEmit*/ true
442-
);
449+
computeDtsSignature(programOfThisState, sourceFile, cancellationToken, host, (signature, sourceFiles) => {
450+
latestSignature = signature;
451+
if (latestSignature !== prevSignature) {
452+
updateExportedModules(state, sourceFile, sourceFiles[0].exportedModulesFromDeclarationEmit);
453+
}
454+
});
443455
}
444456
// Default is to use file version as signature
445457
if (latestSignature === undefined) {
@@ -468,28 +480,23 @@ export namespace BuilderState {
468480
export function updateExportedModules(state: BuilderState, sourceFile: SourceFile, exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined) {
469481
if (!state.exportedModulesMap) return;
470482
(state.oldExportedModulesMap ||= new Map()).set(sourceFile.resolvedPath, state.exportedModulesMap.getValues(sourceFile.resolvedPath) || false);
471-
if (!exportedModulesFromDeclarationEmit) {
472-
state.exportedModulesMap.deleteKey(sourceFile.resolvedPath);
473-
return;
474-
}
475-
476-
let exportedModules: Set<Path> | undefined;
477-
exportedModulesFromDeclarationEmit.forEach(symbol => addExportedModule(getReferencedFilesFromImportedModuleSymbol(symbol)));
483+
const exportedModules = getExportedModules(exportedModulesFromDeclarationEmit);
478484
if (exportedModules) {
479485
state.exportedModulesMap.set(sourceFile.resolvedPath, exportedModules);
480486
}
481487
else {
482488
state.exportedModulesMap.deleteKey(sourceFile.resolvedPath);
483489
}
490+
}
484491

485-
function addExportedModule(exportedModulePaths: Path[] | undefined) {
486-
if (exportedModulePaths?.length) {
487-
if (!exportedModules) {
488-
exportedModules = new Set();
489-
}
490-
exportedModulePaths.forEach(path => exportedModules!.add(path));
491-
}
492-
}
492+
export function getExportedModules(exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined) {
493+
let exportedModules: Set<Path> | undefined;
494+
exportedModulesFromDeclarationEmit?.forEach(
495+
symbol => getReferencedFilesFromImportedModuleSymbol(symbol).forEach(
496+
path => (exportedModules ??= new Set()).add(path)
497+
)
498+
);
499+
return exportedModules;
493500
}
494501

495502
/**

src/compiler/sys.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1433,7 +1433,6 @@ export interface System {
14331433

14341434
// For testing
14351435
/** @internal */ now?(): Date;
1436-
/** @internal */ disableUseFileVersionAsSignature?: boolean;
14371436
/** @internal */ storeFilesChangingSignatureDuringEmit?: boolean;
14381437
}
14391438

src/compiler/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7380,7 +7380,6 @@ export interface CompilerHost extends ModuleResolutionHost {
73807380
/** @internal */getSymlinkCache?(): SymlinkCache;
73817381

73827382
// For testing:
7383-
/** @internal */ disableUseFileVersionAsSignature?: boolean;
73847383
/** @internal */ storeFilesChangingSignatureDuringEmit?: boolean;
73857384
/** @internal */ getBuildInfo?(fileName: string, configFilePath: string | undefined): BuildInfo | undefined;
73867385
}

src/compiler/watch.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,6 @@ export function createCompilerHostFromProgramHost(host: ProgramHost<any>, getCom
765765
getEnvironmentVariable: maybeBind(host, host.getEnvironmentVariable) || (() => ""),
766766
createHash: maybeBind(host, host.createHash),
767767
readDirectory: maybeBind(host, host.readDirectory),
768-
disableUseFileVersionAsSignature: host.disableUseFileVersionAsSignature,
769768
storeFilesChangingSignatureDuringEmit: host.storeFilesChangingSignatureDuringEmit,
770769
};
771770
return compilerHost;
@@ -847,7 +846,6 @@ export function createProgramHost<T extends BuilderProgram = EmitAndSemanticDiag
847846
writeFile: (path, data, writeByteOrderMark) => system.writeFile(path, data, writeByteOrderMark),
848847
createHash: maybeBind(system, system.createHash),
849848
createProgram: createProgram || createEmitAndSemanticDiagnosticsBuilderProgram as any as CreateProgram<T>,
850-
disableUseFileVersionAsSignature: system.disableUseFileVersionAsSignature,
851849
storeFilesChangingSignatureDuringEmit: system.storeFilesChangingSignatureDuringEmit,
852850
now: maybeBind(system, system.now),
853851
};

src/compiler/watchPublic.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ export function readBuilderProgram(compilerOptions: CompilerOptions, host: ReadB
121121
export function createIncrementalCompilerHost(options: CompilerOptions, system = sys): CompilerHost {
122122
const host = createCompilerHostWorker(options, /*setParentNodes*/ undefined, system);
123123
host.createHash = maybeBind(system, system.createHash);
124-
host.disableUseFileVersionAsSignature = system.disableUseFileVersionAsSignature;
125124
host.storeFilesChangingSignatureDuringEmit = system.storeFilesChangingSignatureDuringEmit;
126125
setGetSourceFileAsHashVersioned(host);
127126
changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, host.getCurrentDirectory(), host.getCanonicalFileName));
@@ -248,7 +247,6 @@ export interface ProgramHost<T extends BuilderProgram> {
248247
createDirectory?(path: string): void;
249248
writeFile?(path: string, data: string, writeByteOrderMark?: boolean): void;
250249
// For testing
251-
disableUseFileVersionAsSignature?: boolean;
252250
storeFilesChangingSignatureDuringEmit?: boolean;
253251
now?(): Date;
254252
}

src/testRunner/unittests/tsbuild/commandLine.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
compilerOptionsToConfigJson,
55
loadProjectFromFiles,
66
noChangeRun,
7-
noChangeWithExportsDiscrepancyRun,
87
replaceText,
98
TestTscEdit,
109
verifyTscWithEdits,
@@ -41,12 +40,6 @@ describe("unittests:: tsbuild:: commandLine::", () => {
4140
];
4241
return edit;
4342
}
44-
function withOptionChangeAndExportExplanation(subScenario: string, ...options: readonly string[]): TestTscEdit {
45-
return {
46-
...withOptionChange(subScenario, ...options),
47-
discrepancyExplanation: noChangeWithExportsDiscrepancyRun.discrepancyExplanation,
48-
};
49-
}
5043
function nochangeWithIncrementalDeclarationFromBeforeExplaination(): TestTscEdit {
5144
return {
5245
...noChangeRun,
@@ -129,8 +122,8 @@ describe("unittests:: tsbuild:: commandLine::", () => {
129122
fs: () => fs({ incremental: true }),
130123
commandLineArgs: ["--b", "/src/project", "--verbose"],
131124
edits: [
132-
withOptionChangeAndExportExplanation("with sourceMap", "--sourceMap"),
133-
withOptionChangeAndExportExplanation("should re-emit only js so they dont contain sourcemap"),
125+
withOptionChange("with sourceMap", "--sourceMap"),
126+
withOptionChange("should re-emit only js so they dont contain sourcemap"),
134127
withOptionChange("with declaration, emit Dts and should not emit js", "--declaration"),
135128
withOptionChange("with declaration and declarationMap", "--declaration", "--declarationMap"),
136129
nochangeWithIncrementalDeclarationFromBeforeExplaination(),

src/testRunner/unittests/tsbuild/noEmitOnError.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {
22
loadProjectFromDisk,
33
noChangeRun,
4-
noChangeWithExportsDiscrepancyRun,
54
verifyTscWithEdits,
65
} from "../tsc/helpers";
76
import * as vfs from "../../_namespaces/vfs";
@@ -80,7 +79,7 @@ const a: string = "hello";`, "utf-8"),
8079
const a: string = 10;`, "utf-8"),
8180
commandLineArgs: ["--b", "/src/tsconfig.json", "--incremental"],
8281
edits: [
83-
noChangeWithExportsDiscrepancyRun,
82+
noChangeRun,
8483
{
8584
subScenario: "Fix error",
8685
modifyFs: fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db";

0 commit comments

Comments
 (0)