Switch to ES Map/Set internally (#33771)

* Add full implemention of Map and Set to shims

* Update default Map interface

* Remove WeakMap/WeakSet

* Add tests for set shim

* Update most usages of Map<K, true> to Set

* PR Feedback

* Fix lint issues

* Change key in fsWatchCallback

* Simpler shim, more tests

* Fix typo in collection shim
This commit is contained in:
Ron Buckton
2020-06-26 10:12:47 -07:00
committed by GitHub
parent 95690c0aca
commit eb2f4e2337
87 changed files with 1767 additions and 1135 deletions

View File

@@ -126,7 +126,7 @@ namespace ts {
}
}
let outputFingerprints: Map<OutputFingerprint>;
let outputFingerprints: Map<string, OutputFingerprint>;
function writeFileWorker(fileName: string, data: string, writeByteOrderMark: boolean) {
if (!isWatchSet(options) || !system.createHash || !system.getModifiedTime) {
system.writeFile(fileName, data, writeByteOrderMark);
@@ -533,7 +533,7 @@ namespace ts {
export const inferredTypesContainingFile = "__inferred type names__.ts";
interface DiagnosticCache<T extends Diagnostic> {
perFile?: Map<readonly T[]>;
perFile?: Map<Path, readonly T[]>;
allDiagnostics?: readonly T[];
}
@@ -702,14 +702,14 @@ namespace ts {
let processingDefaultLibFiles: SourceFile[] | undefined;
let processingOtherFiles: SourceFile[] | undefined;
let files: SourceFile[];
let symlinks: ReadonlyMap<string> | undefined;
let symlinks: ReadonlyMap<string, string> | undefined;
let commonSourceDirectory: string;
let diagnosticsProducingTypeChecker: TypeChecker;
let noDiagnosticsTypeChecker: TypeChecker;
let classifiableNames: UnderscoreEscapedMap<true>;
const ambientModuleNameToUnmodifiedFileName = createMap<string>();
// Todo:: Use this to report why file was included in --extendedDiagnostics
let refFileMap: MultiMap<ts.RefFile> | undefined;
let refFileMap: MultiMap<Path, ts.RefFile> | undefined;
const cachedBindAndCheckDiagnosticsForFile: DiagnosticCache<Diagnostic> = {};
const cachedDeclarationDiagnosticsForFile: DiagnosticCache<DiagnosticWithLocation> = {};
@@ -803,9 +803,9 @@ namespace ts {
// A parallel array to projectReferences storing the results of reading in the referenced tsconfig files
let resolvedProjectReferences: readonly (ResolvedProjectReference | undefined)[] | undefined;
let projectReferenceRedirects: Map<ResolvedProjectReference | false> | undefined;
let mapFromFileToProjectReferenceRedirects: Map<Path> | undefined;
let mapFromToProjectReferenceRedirectSource: Map<SourceOfProjectReferenceRedirect> | undefined;
let projectReferenceRedirects: Map<Path, ResolvedProjectReference | false> | undefined;
let mapFromFileToProjectReferenceRedirects: Map<Path, Path> | undefined;
let mapFromToProjectReferenceRedirectSource: Map<Path, SourceOfProjectReferenceRedirect> | undefined;
const useSourceOfProjectReferenceRedirect = !!host.useSourceOfProjectReferenceRedirect?.() &&
!options.disableSourceOfProjectReferenceRedirect;
@@ -2028,7 +2028,7 @@ namespace ts {
): readonly U[] {
const cachedResult = sourceFile
? cache.perFile && cache.perFile.get(sourceFile.path)
? cache.perFile?.get(sourceFile.path)
: cache.allDiagnostics;
if (cachedResult) {
@@ -2036,10 +2036,7 @@ namespace ts {
}
const result = getDiagnostics(sourceFile, cancellationToken);
if (sourceFile) {
if (!cache.perFile) {
cache.perFile = createMap();
}
cache.perFile.set(sourceFile.path, result);
(cache.perFile || (cache.perFile = new Map())).set(sourceFile.path, result);
}
else {
cache.allDiagnostics = result;
@@ -2546,7 +2543,7 @@ namespace ts {
*/
function getResolvedProjectReferenceToRedirect(fileName: string) {
if (mapFromFileToProjectReferenceRedirects === undefined) {
mapFromFileToProjectReferenceRedirects = createMap();
mapFromFileToProjectReferenceRedirects = new Map();
forEachResolvedProjectReference((referencedProject, referenceProjectPath) => {
// not input file from the referenced project, ignore
if (referencedProject &&
@@ -2892,13 +2889,13 @@ namespace ts {
function checkSourceFilesBelongToPath(sourceFiles: readonly SourceFile[], rootDirectory: string): boolean {
let allFilesBelongToPath = true;
const absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory));
let rootPaths: Map<true> | undefined;
let rootPaths: Set<Path> | undefined;
for (const sourceFile of sourceFiles) {
if (!sourceFile.isDeclarationFile) {
const absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory));
if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) {
if (!rootPaths) rootPaths = arrayToSet(rootNames, toPath);
if (!rootPaths) rootPaths = new Set(rootNames.map(toPath));
addProgramDiagnosticAtRefPath(
sourceFile,
rootPaths,
@@ -2916,7 +2913,7 @@ namespace ts {
function parseProjectReferenceConfigFile(ref: ProjectReference): ResolvedProjectReference | undefined {
if (!projectReferenceRedirects) {
projectReferenceRedirects = createMap<ResolvedProjectReference | false>();
projectReferenceRedirects = new Map();
}
// The actual filename (i.e. add "/tsconfig.json" if necessary)
@@ -3015,7 +3012,7 @@ namespace ts {
// List of collected files is complete; validate exhautiveness if this is a project with a file list
if (options.composite) {
const rootPaths = arrayToSet(rootNames, toPath);
const rootPaths = new Set(rootNames.map(toPath));
for (const file of files) {
// Ignore file that is not emitted
if (sourceFileMayBeEmitted(file, program) && !rootPaths.has(file.path)) {
@@ -3204,7 +3201,7 @@ namespace ts {
// If the emit is enabled make sure that every output file is unique and not overwriting any of the input files
if (!options.noEmit && !options.suppressOutputPathCheck) {
const emitHost = getEmitHost();
const emitFilesSeen = createMap<true>();
const emitFilesSeen = new Set<string>();
forEachEmittedFile(emitHost, (emitFileNames) => {
if (!options.emitDeclarationOnly) {
verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen);
@@ -3214,7 +3211,7 @@ namespace ts {
}
// Verify that all the emit files are unique and don't overwrite input files
function verifyEmitFilePath(emitFileName: string | undefined, emitFilesSeen: Map<true>) {
function verifyEmitFilePath(emitFileName: string | undefined, emitFilesSeen: Set<string>) {
if (emitFileName) {
const emitFilePath = toPath(emitFileName);
// Report error if the output overwrites input file
@@ -3235,7 +3232,7 @@ namespace ts {
blockEmittingOfFile(emitFileName, createCompilerDiagnostic(Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files, emitFileName));
}
else {
emitFilesSeen.set(emitFileKey, true);
emitFilesSeen.add(emitFileKey);
}
}
}
@@ -3262,8 +3259,8 @@ namespace ts {
return createFileDiagnostic(refFile, pos, end - pos, message, ...args);
}
function addProgramDiagnosticAtRefPath(file: SourceFile, rootPaths: Map<true>, message: DiagnosticMessage, ...args: (string | number | undefined)[]) {
const refPaths = refFileMap && refFileMap.get(file.path);
function addProgramDiagnosticAtRefPath(file: SourceFile, rootPaths: Set<Path>, message: DiagnosticMessage, ...args: (string | number | undefined)[]) {
const refPaths = refFileMap?.get(file.path);
const refPathToReportErrorOn = forEach(refPaths, refPath => rootPaths.has(refPath.file) ? refPath : undefined) ||
elementAt(refPaths, 0);
programDiagnostics.add(
@@ -3455,7 +3452,7 @@ namespace ts {
return comparePaths(file1, file2, currentDirectory, !host.useCaseSensitiveFileNames()) === Comparison.EqualTo;
}
function getProbableSymlinks(): ReadonlyMap<string> {
function getProbableSymlinks(): ReadonlyMap<string, string> {
if (host.getSymlinks) {
return host.getSymlinks();
}
@@ -3481,9 +3478,9 @@ namespace ts {
}
function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSourceOfProjectReferenceRedirect) {
let mapOfDeclarationDirectories: Map<true> | undefined;
let symlinkedDirectories: Map<SymlinkedDirectory | false> | undefined;
let symlinkedFiles: Map<string> | undefined;
let setOfDeclarationDirectories: Set<Path> | undefined;
let symlinkedDirectories: Map<Path, SymlinkedDirectory | false> | undefined;
let symlinkedFiles: Map<Path, string> | undefined;
const originalFileExists = host.compilerHost.fileExists;
const originalDirectoryExists = host.compilerHost.directoryExists;
@@ -3506,19 +3503,19 @@ namespace ts {
if (!host.getResolvedProjectReferences()) return false;
if (!mapOfDeclarationDirectories) {
mapOfDeclarationDirectories = createMap();
if (!setOfDeclarationDirectories) {
setOfDeclarationDirectories = new Set();
host.forEachResolvedProjectReference(ref => {
if (!ref) return;
const out = outFile(ref.commandLine.options);
if (out) {
mapOfDeclarationDirectories!.set(getDirectoryPath(host.toPath(out)), true);
setOfDeclarationDirectories!.add(getDirectoryPath(host.toPath(out)));
}
else {
// Set declaration's in different locations only, if they are next to source the directory present doesnt change
const declarationDir = ref.commandLine.options.declarationDir || ref.commandLine.options.outDir;
if (declarationDir) {
mapOfDeclarationDirectories!.set(host.toPath(declarationDir), true);
setOfDeclarationDirectories!.add(host.toPath(declarationDir));
}
}
});
@@ -3576,7 +3573,7 @@ namespace ts {
const dirPath = host.toPath(dir);
const dirPathWithTrailingDirectorySeparator = `${dirPath}${directorySeparator}`;
return forEachKey(
mapOfDeclarationDirectories!,
setOfDeclarationDirectories!,
declDirPath => dirPath === declDirPath ||
// Any parent directory of declaration dir
startsWith(declDirPath, dirPathWithTrailingDirectorySeparator) ||
@@ -3590,7 +3587,7 @@ namespace ts {
// Because we already watch node_modules, handle symlinks in there
if (!originalRealpath || !stringContains(directory, nodeModulesPathPart)) return;
if (!symlinkedDirectories) symlinkedDirectories = createMap();
if (!symlinkedDirectories) symlinkedDirectories = new Map();
const directoryPath = ensureTrailingDirectorySeparator(host.toPath(directory));
if (symlinkedDirectories.has(directoryPath)) return;
@@ -3629,7 +3626,7 @@ namespace ts {
if (!symlinkedDirectory || !startsWith(fileOrDirectoryPath, directoryPath)) return undefined;
const result = fileOrDirectoryExistsUsingSource(fileOrDirectoryPath.replace(directoryPath, symlinkedDirectory.realPath));
if (isFile && result) {
if (!symlinkedFiles) symlinkedFiles = createMap();
if (!symlinkedFiles) symlinkedFiles = new Map();
// Store the real path for the file'
const absolutePath = getNormalizedAbsolutePath(fileOrDirectory, host.compilerHost.getCurrentDirectory());
symlinkedFiles.set(