diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index abae979a25d..e18ce2efeeb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5336,7 +5336,7 @@ namespace ts { while (i > 0) { i--; if (isSubtypeOfAny(types[i], types)) { - removeItemAt(types, i); + removeItemAtPreservingOrder(types, i); } } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index dd4ba822243..73c92eff547 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1395,7 +1395,7 @@ namespace ts { } /** Remove an item from an array, moving everything to its right one space left. */ - export function removeItemAt(array: T[], index: number): void { + export function removeItemAtPreservingOrder(array: T[], index: number): void { // This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`. for (let i = index; i < array.length - 1; i++) { array[i] = array[i + 1]; @@ -1403,23 +1403,29 @@ namespace ts { array.pop(); } + export function unorderedRemoveItemAt(array: T[], index: number): void { + // Fill in the "hole" left at `index`. + array[index] = array[array.length - 1]; + array.pop(); + } + /** Remove the *first* occurrence of `item` from the array. */ - export function removeItem(item: T, array: T[]): void { - removeFirstItemWhere(array, element => element === item); + export function unorderedRemoveItem(item: T, array: T[]): void { + unorderedRemoveFirstItemWhere(array, element => element === item); } /** Remove the *first* element satisfying `predicate`. */ - export function removeFirstItemWhere(array: T[], predicate: (element: T) => boolean): void { + export function unorderedRemoveFirstItemWhere(array: T[], predicate: (element: T) => boolean): void { for (let i = 0; i < array.length; i++) { if (predicate(array[i])) { - removeItemAt(array, i); + unorderedRemoveItemAt(array, i); break; } } } - export function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string { - return useCaseSensitivefileNames + export function createGetCanonicalFileName(useCaseSensitiveFileNames: boolean): (fileName: string) => string { + return useCaseSensitiveFileNames ? ((fileName) => fileName) : ((fileName) => fileName.toLowerCase()); } diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 7953a2f42e8..966a282ae62 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -285,7 +285,7 @@ namespace ts { function removeFileWatcherCallback(filePath: string, callback: FileWatcherCallback) { const callbacks = fileWatcherCallbacks[filePath]; if (callbacks) { - removeItem(callback, callbacks); + unorderedRemoveItem(callback, callbacks); if (callbacks.length === 0) { delete fileWatcherCallbacks[filePath]; } diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 02a97c01132..bd3f88676bc 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -490,7 +490,7 @@ namespace ts { sourceFile.fileWatcher.close(); sourceFile.fileWatcher = undefined; if (removed) { - removeItem(sourceFile.fileName, rootFileNames); + unorderedRemoveItem(sourceFile.fileName, rootFileNames); } startTimerForRecompilation(); } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 3b36381146f..634c159dbb8 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1558,7 +1558,7 @@ namespace Harness { tsConfig.options.configFilePath = data.name; // delete entry from the list - ts.removeItemAt(testUnitData, i); + ts.removeItemAtPreservingOrder(testUnitData, i); break; } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index cd87164245a..b02e4d81cd3 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -214,7 +214,7 @@ namespace ts { referenceCount: 0, directoryName, close: () => { - removeFirstItemWhere(callbacks, cb => cb.cb === callback); + unorderedRemoveFirstItemWhere(callbacks, cb => cb.cb === callback); if (!callbacks.length) { delete this.watchedDirectories[path]; } @@ -248,7 +248,7 @@ namespace ts { callbacks.push(callback); return { close: () => { - removeItem(callback, callbacks); + unorderedRemoveItem(callback, callbacks); if (!callbacks.length) { delete this.watchedFiles[path]; } @@ -263,7 +263,7 @@ namespace ts { }; readonly clearTimeout = (timeoutId: any): void => { if (typeof timeoutId === "number") { - removeItemAt(this.callbackQueue, timeoutId); + unorderedRemoveItemAt(this.callbackQueue, timeoutId); } }; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 0a12bf68d79..0aa10819c49 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -275,7 +275,7 @@ namespace ts.server { removeRoot(info: ScriptInfo) { if (this.filenameToScript.contains(info.path)) { this.filenameToScript.remove(info.path); - removeItem(info, this.roots); + unorderedRemoveItem(info, this.roots); this.resolvedModuleNames.remove(info.path); this.resolvedTypeReferenceDirectives.remove(info.path); } @@ -849,7 +849,7 @@ namespace ts.server { project.directoryWatcher.close(); forEachValue(project.directoriesWatchedForWildcards, watcher => { watcher.close(); }); delete project.directoriesWatchedForWildcards; - removeItem(project, this.configuredProjects); + unorderedRemoveItem(project, this.configuredProjects); } else { for (const directory of project.directoriesWatchedForTsconfig) { @@ -861,7 +861,7 @@ namespace ts.server { delete project.projectService.directoryWatchersForTsconfig[directory]; } } - removeItem(project, this.inferredProjects); + unorderedRemoveItem(project, this.inferredProjects); } const fileNames = project.getFileNames(); @@ -986,7 +986,7 @@ namespace ts.server { } } else { - removeItem(info, this.openFilesReferenced); + unorderedRemoveItem(info, this.openFilesReferenced); } info.close(); } @@ -1496,13 +1496,13 @@ namespace ts.server { // openFileRoots or openFileReferenced. if (info.isOpen) { if (this.openFileRoots.indexOf(info) >= 0) { - removeItem(info, this.openFileRoots); + unorderedRemoveItem(info, this.openFileRoots); if (info.defaultProject && !info.defaultProject.isConfiguredProject()) { this.removeProject(info.defaultProject); } } if (this.openFilesReferenced.indexOf(info) >= 0) { - removeItem(info, this.openFilesReferenced); + unorderedRemoveItem(info, this.openFilesReferenced); } this.openFileRootsConfigured.push(info); info.defaultProject = project;