Skip to content

Switch to ES Map/Set internally #33771

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jun 26, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace ts {
referenced: boolean;
}

export function getModuleInstanceState(node: ModuleDeclaration, visited?: Map<ModuleInstanceState | undefined>): ModuleInstanceState {
export function getModuleInstanceState(node: ModuleDeclaration, visited?: Map<string, ModuleInstanceState | undefined>): ModuleInstanceState {
if (node.body && !node.body.parent) {
// getModuleInstanceStateForAliasTarget needs to walk up the parent chain, so parent pointers must be set on this tree already
setParent(node.body, node);
Expand All @@ -35,7 +35,7 @@ namespace ts {
return result;
}

function getModuleInstanceStateWorker(node: Node, visited: Map<ModuleInstanceState | undefined>): ModuleInstanceState {
function getModuleInstanceStateWorker(node: Node, visited: Map<string, ModuleInstanceState | undefined>): ModuleInstanceState {
// A module is uninstantiated if it contains only
switch (node.kind) {
// 1. interface declarations, type alias declarations
Expand Down Expand Up @@ -107,7 +107,7 @@ namespace ts {
return ModuleInstanceState.Instantiated;
}

function getModuleInstanceStateForAliasTarget(specifier: ExportSpecifier, visited: Map<ModuleInstanceState | undefined>) {
function getModuleInstanceStateForAliasTarget(specifier: ExportSpecifier, visited: Map<string, ModuleInstanceState | undefined>) {
const name = specifier.propertyName || specifier.name;
let p: Node | undefined = specifier.parent;
while (p) {
Expand Down
68 changes: 33 additions & 35 deletions src/compiler/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ namespace ts {
/**
* Cache of bind and check diagnostics for files with their Path being the key
*/
semanticDiagnosticsPerFile?: ReadonlyMap<readonly ReusableDiagnostic[] | readonly Diagnostic[]> | undefined;
semanticDiagnosticsPerFile?: ReadonlyMap<string, readonly ReusableDiagnostic[] | readonly Diagnostic[]> | undefined;
/**
* The map has key by source file's path that has been changed
*/
changedFilesSet?: ReadonlyMap<true>;
changedFilesSet?: ReadonlySet<string>;
/**
* Set of affected files being iterated
*/
Expand All @@ -41,15 +41,15 @@ namespace ts {
* Map of file signatures, with key being file path, calculated while getting current changed file's affected files
* These will be committed whenever the iteration through affected files of current changed file is complete
*/
currentAffectedFilesSignatures?: ReadonlyMap<string> | undefined;
currentAffectedFilesSignatures?: ReadonlyMap<string, string> | undefined;
/**
* Newly computed visible to outside referencedSet
*/
currentAffectedFilesExportedModulesMap?: Readonly<BuilderState.ComputingExportedModulesMap> | undefined;
/**
* True if the semantic diagnostics were copied from the old state
*/
semanticDiagnosticsFromOldState?: Map<true>;
semanticDiagnosticsFromOldState?: Set<string>;
/**
* program corresponding to this state
*/
Expand All @@ -65,7 +65,7 @@ namespace ts {
/**
* Files pending to be emitted kind.
*/
affectedFilesPendingEmitKind?: ReadonlyMap<BuilderFileEmit> | undefined;
affectedFilesPendingEmitKind?: ReadonlyMap<string, BuilderFileEmit> | undefined;
/**
* Current index to retrieve pending affected file
*/
Expand All @@ -89,11 +89,11 @@ namespace ts {
/**
* Cache of bind and check diagnostics for files with their Path being the key
*/
semanticDiagnosticsPerFile: Map<readonly Diagnostic[]> | undefined;
semanticDiagnosticsPerFile: Map<string, readonly Diagnostic[]> | undefined;
/**
* The map has key by source file's path that has been changed
*/
changedFilesSet: Map<true>;
changedFilesSet: Set<string>;
/**
* Set of affected files being iterated
*/
Expand All @@ -110,23 +110,23 @@ namespace ts {
* Map of file signatures, with key being file path, calculated while getting current changed file's affected files
* These will be committed whenever the iteration through affected files of current changed file is complete
*/
currentAffectedFilesSignatures: Map<string> | undefined;
currentAffectedFilesSignatures: Map<string, string> | undefined;
/**
* Newly computed visible to outside referencedSet
*/
currentAffectedFilesExportedModulesMap: BuilderState.ComputingExportedModulesMap | undefined;
/**
* Already seen affected files
*/
seenAffectedFiles: Map<true> | undefined;
seenAffectedFiles: Set<string> | undefined;
/**
* whether this program has cleaned semantic diagnostics cache for lib files
*/
cleanedDiagnosticsOfLibFiles?: boolean;
/**
* True if the semantic diagnostics were copied from the old state
*/
semanticDiagnosticsFromOldState?: Map<true>;
semanticDiagnosticsFromOldState?: Set<string>;
/**
* program corresponding to this state
*/
Expand All @@ -142,7 +142,7 @@ namespace ts {
/**
* Files pending to be emitted kind.
*/
affectedFilesPendingEmitKind: Map<BuilderFileEmit> | undefined;
affectedFilesPendingEmitKind: Map<string, BuilderFileEmit> | undefined;
/**
* Current index to retrieve pending affected file
*/
Expand All @@ -154,16 +154,16 @@ namespace ts {
/**
* Already seen emitted files
*/
seenEmittedFiles: Map<BuilderFileEmit> | undefined;
seenEmittedFiles: Map<string, BuilderFileEmit> | undefined;
/**
* true if program has been emitted
*/
programEmitComplete?: true;
}

function hasSameKeys<T, U>(map1: ReadonlyMap<T> | undefined, map2: ReadonlyMap<U> | undefined): boolean {
function hasSameKeys(map1: ReadonlyCollection<string> | undefined, map2: ReadonlyCollection<string> | undefined): boolean {
// Has same size and every key is present in both maps
return map1 as ReadonlyMap<T | U> === map2 || map1 !== undefined && map2 !== undefined && map1.size === map2.size && !forEachKey(map1, key => !map2.has(key));
return map1 === map2 || map1 !== undefined && map2 !== undefined && map1.size === map2.size && !forEachKey(map1, key => !map2.has(key));
}

/**
Expand All @@ -178,7 +178,7 @@ namespace ts {
if (!outFile(compilerOptions)) {
state.semanticDiagnosticsPerFile = createMap<readonly Diagnostic[]>();
}
state.changedFilesSet = createMap<true>();
state.changedFilesSet = new Set();

const useOldState = BuilderState.canReuseOldState(state.referencedMap, oldState);
const oldCompilerOptions = useOldState ? oldState!.compilerOptions : undefined;
Expand All @@ -196,14 +196,12 @@ namespace ts {
}

// Copy old state's changed files set
if (changedFilesSet) {
copyEntries(changedFilesSet, state.changedFilesSet);
}
changedFilesSet?.forEach(value => state.changedFilesSet.add(value));
if (!outFile(compilerOptions) && oldState!.affectedFilesPendingEmit) {
state.affectedFilesPendingEmit = oldState!.affectedFilesPendingEmit.slice();
state.affectedFilesPendingEmitKind = cloneMapOrUndefined(oldState!.affectedFilesPendingEmitKind);
state.affectedFilesPendingEmitIndex = oldState!.affectedFilesPendingEmitIndex;
state.seenAffectedFiles = createMap();
state.seenAffectedFiles = new Set();
}
}

Expand All @@ -227,7 +225,7 @@ namespace ts {
// Referenced file was deleted in the new program
newReferences && forEachKey(newReferences, path => !state.fileInfos.has(path) && oldState!.fileInfos.has(path))) {
// Register file as changed file and do not copy semantic diagnostics, since all changed files need to be re-evaluated
state.changedFilesSet.set(sourceFilePath, true);
state.changedFilesSet.add(sourceFilePath);
}
else if (canCopySemanticDiagnostics) {
const sourceFile = newProgram.getSourceFileByPath(sourceFilePath as Path)!;
Expand All @@ -240,23 +238,23 @@ namespace ts {
if (diagnostics) {
state.semanticDiagnosticsPerFile!.set(sourceFilePath, oldState!.hasReusableDiagnostic ? convertToDiagnostics(diagnostics as readonly ReusableDiagnostic[], newProgram, getCanonicalFileName) : diagnostics as readonly Diagnostic[]);
if (!state.semanticDiagnosticsFromOldState) {
state.semanticDiagnosticsFromOldState = createMap<true>();
state.semanticDiagnosticsFromOldState = new Set();
}
state.semanticDiagnosticsFromOldState.set(sourceFilePath, true);
state.semanticDiagnosticsFromOldState.add(sourceFilePath);
}
}
});

// If the global file is removed, add all files as changed
if (useOldState && forEachEntry(oldState!.fileInfos, (info, sourceFilePath) => info.affectsGlobalScope && !state.fileInfos.has(sourceFilePath))) {
BuilderState.getAllFilesExcludingDefaultLibraryFile(state, newProgram, /*firstSourceFile*/ undefined)
.forEach(file => state.changedFilesSet.set(file.resolvedPath, true));
.forEach(file => state.changedFilesSet.add(file.resolvedPath));
}
else if (oldCompilerOptions && !outFile(compilerOptions) && compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions)) {
// Add all files to affectedFilesPendingEmit since emit changed
newProgram.getSourceFiles().forEach(f => addToAffectedFilesPendingEmit(state, f.resolvedPath, BuilderFileEmit.Full));
Debug.assert(!state.seenAffectedFiles || !state.seenAffectedFiles.size);
state.seenAffectedFiles = state.seenAffectedFiles || createMap<true>();
state.seenAffectedFiles = state.seenAffectedFiles || new Set();
}

state.buildInfoEmitPending = !!state.changedFilesSet.size;
Expand Down Expand Up @@ -308,15 +306,15 @@ namespace ts {
function cloneBuilderProgramState(state: Readonly<BuilderProgramState>): BuilderProgramState {
const newState = BuilderState.clone(state) as BuilderProgramState;
newState.semanticDiagnosticsPerFile = cloneMapOrUndefined(state.semanticDiagnosticsPerFile);
newState.changedFilesSet = cloneMap(state.changedFilesSet);
newState.changedFilesSet = new Set(state.changedFilesSet);
newState.affectedFiles = state.affectedFiles;
newState.affectedFilesIndex = state.affectedFilesIndex;
newState.currentChangedFilePath = state.currentChangedFilePath;
newState.currentAffectedFilesSignatures = cloneMapOrUndefined(state.currentAffectedFilesSignatures);
newState.currentAffectedFilesExportedModulesMap = cloneMapOrUndefined(state.currentAffectedFilesExportedModulesMap);
newState.seenAffectedFiles = cloneMapOrUndefined(state.seenAffectedFiles);
newState.seenAffectedFiles = state.seenAffectedFiles && new Set(state.seenAffectedFiles);
newState.cleanedDiagnosticsOfLibFiles = state.cleanedDiagnosticsOfLibFiles;
newState.semanticDiagnosticsFromOldState = cloneMapOrUndefined(state.semanticDiagnosticsFromOldState);
newState.semanticDiagnosticsFromOldState = state.semanticDiagnosticsFromOldState && new Set(state.semanticDiagnosticsFromOldState);
newState.program = state.program;
newState.compilerOptions = state.compilerOptions;
newState.affectedFilesPendingEmit = state.affectedFilesPendingEmit && state.affectedFilesPendingEmit.slice();
Expand Down Expand Up @@ -391,7 +389,7 @@ namespace ts {
state.affectedFiles = BuilderState.getFilesAffectedBy(state, program, nextKey.value as Path, cancellationToken, computeHash, state.currentAffectedFilesSignatures, state.currentAffectedFilesExportedModulesMap);
state.currentChangedFilePath = nextKey.value as Path;
state.affectedFilesIndex = 0;
state.seenAffectedFiles = state.seenAffectedFiles || createMap<true>();
state.seenAffectedFiles = state.seenAffectedFiles || new Set();
}
}

Expand Down Expand Up @@ -533,7 +531,7 @@ namespace ts {
}

Debug.assert(!!state.currentAffectedFilesExportedModulesMap);
const seenFileAndExportsOfFile = createMap<true>();
const seenFileAndExportsOfFile = new Set<string>();
// Go through exported modules from cache first
// If exported modules has path, all files referencing file exported from are affected
if (forEachEntry(state.currentAffectedFilesExportedModulesMap, (exportedModules, exportedFromPath) =>
Expand All @@ -555,7 +553,7 @@ namespace ts {
/**
* Iterate on files referencing referencedPath
*/
function forEachFilesReferencingPath(state: BuilderProgramState, referencedPath: Path, seenFileAndExportsOfFile: Map<true>, fn: (state: BuilderProgramState, filePath: Path) => boolean) {
function forEachFilesReferencingPath(state: BuilderProgramState, referencedPath: Path, seenFileAndExportsOfFile: Set<string>, fn: (state: BuilderProgramState, filePath: Path) => boolean) {
return forEachEntry(state.referencedMap!, (referencesInFile, filePath) =>
referencesInFile.has(referencedPath) && forEachFileAndExportsOfFile(state, filePath as Path, seenFileAndExportsOfFile, fn)
);
Expand All @@ -564,8 +562,8 @@ namespace ts {
/**
* fn on file and iterate on anything that exports this file
*/
function forEachFileAndExportsOfFile(state: BuilderProgramState, filePath: Path, seenFileAndExportsOfFile: Map<true>, fn: (state: BuilderProgramState, filePath: Path) => boolean): boolean {
if (!addToSeen(seenFileAndExportsOfFile, filePath)) {
function forEachFileAndExportsOfFile(state: BuilderProgramState, filePath: Path, seenFileAndExportsOfFile: Set<string>, fn: (state: BuilderProgramState, filePath: Path) => boolean): boolean {
if (!tryAddToSet(seenFileAndExportsOfFile, filePath)) {
return false;
}

Expand Down Expand Up @@ -622,7 +620,7 @@ namespace ts {
state.programEmitComplete = true;
}
else {
state.seenAffectedFiles!.set((affected as SourceFile).resolvedPath, true);
state.seenAffectedFiles!.add((affected as SourceFile).resolvedPath);
if (emitKind !== undefined) {
(state.seenEmittedFiles || (state.seenEmittedFiles = createMap())).set((affected as SourceFile).resolvedPath, emitKind);
}
Expand Down Expand Up @@ -1142,14 +1140,14 @@ namespace ts {
}
}

function getMapOfReferencedSet(mapLike: MapLike<readonly string[]> | undefined, toPath: (path: string) => Path): ReadonlyMap<BuilderState.ReferencedSet> | undefined {
function getMapOfReferencedSet(mapLike: MapLike<readonly string[]> | undefined, toPath: (path: string) => Path): ReadonlyMap<string, BuilderState.ReferencedSet> | undefined {
if (!mapLike) return undefined;
const map = createMap<BuilderState.ReferencedSet>();
// Copies keys/values from template. Note that for..in will not throw if
// template is undefined, and instead will just exit the loop.
for (const key in mapLike) {
if (hasProperty(mapLike, key)) {
map.set(toPath(key), arrayToSet(mapLike[key], toPath));
map.set(toPath(key), new Set(mapLike[key].map(toPath)));
}
}
return map;
Expand Down
Loading