Skip to content

Commit 2961d97

Browse files
author
Andy
authored
Merge pull request #10349 from Microsoft/remove_item_from_list
Use `removeItem` instead of `copyListRemovingItem`
2 parents 5f16a48 + d7b6cc8 commit 2961d97

File tree

8 files changed

+46
-47
lines changed

8 files changed

+46
-47
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5378,7 +5378,7 @@ namespace ts {
53785378
while (i > 0) {
53795379
i--;
53805380
if (isSubtypeOfAny(types[i], types)) {
5381-
types.splice(i, 1);
5381+
orderedRemoveItemAt(types, i);
53825382
}
53835383
}
53845384
}

src/compiler/core.ts

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,18 +1500,38 @@ namespace ts {
15001500
}
15011501
}
15021502

1503-
export function copyListRemovingItem<T>(item: T, list: T[]) {
1504-
const copiedList: T[] = [];
1505-
for (const e of list) {
1506-
if (e !== item) {
1507-
copiedList.push(e);
1503+
/** Remove an item from an array, moving everything to its right one space left. */
1504+
export function orderedRemoveItemAt<T>(array: T[], index: number): void {
1505+
// This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`.
1506+
for (let i = index; i < array.length - 1; i++) {
1507+
array[i] = array[i + 1];
1508+
}
1509+
array.pop();
1510+
}
1511+
1512+
export function unorderedRemoveItemAt<T>(array: T[], index: number): void {
1513+
// Fill in the "hole" left at `index`.
1514+
array[index] = array[array.length - 1];
1515+
array.pop();
1516+
}
1517+
1518+
/** Remove the *first* occurrence of `item` from the array. */
1519+
export function unorderedRemoveItem<T>(array: T[], item: T): void {
1520+
unorderedRemoveFirstItemWhere(array, element => element === item);
1521+
}
1522+
1523+
/** Remove the *first* element satisfying `predicate`. */
1524+
function unorderedRemoveFirstItemWhere<T>(array: T[], predicate: (element: T) => boolean): void {
1525+
for (let i = 0; i < array.length; i++) {
1526+
if (predicate(array[i])) {
1527+
unorderedRemoveItemAt(array, i);
1528+
break;
15081529
}
15091530
}
1510-
return copiedList;
15111531
}
15121532

1513-
export function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string {
1514-
return useCaseSensitivefileNames
1533+
export function createGetCanonicalFileName(useCaseSensitiveFileNames: boolean): (fileName: string) => string {
1534+
return useCaseSensitiveFileNames
15151535
? ((fileName) => fileName)
15161536
: ((fileName) => fileName.toLowerCase());
15171537
}

src/compiler/sys.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -285,13 +285,10 @@ namespace ts {
285285
function removeFileWatcherCallback(filePath: string, callback: FileWatcherCallback) {
286286
const callbacks = fileWatcherCallbacks[filePath];
287287
if (callbacks) {
288-
const newCallbacks = copyListRemovingItem(callback, callbacks);
289-
if (newCallbacks.length === 0) {
288+
unorderedRemoveItem(callbacks, callback);
289+
if (callbacks.length === 0) {
290290
delete fileWatcherCallbacks[filePath];
291291
}
292-
else {
293-
fileWatcherCallbacks[filePath] = newCallbacks;
294-
}
295292
}
296293
}
297294

src/compiler/tsc.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -489,10 +489,7 @@ namespace ts {
489489
sourceFile.fileWatcher.close();
490490
sourceFile.fileWatcher = undefined;
491491
if (removed) {
492-
const index = rootFileNames.indexOf(sourceFile.fileName);
493-
if (index >= 0) {
494-
rootFileNames.splice(index, 1);
495-
}
492+
unorderedRemoveItem(rootFileNames, sourceFile.fileName);
496493
}
497494
startTimerForRecompilation();
498495
}

src/harness/harness.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1785,7 +1785,7 @@ namespace Harness {
17851785
tsConfig.options.configFilePath = data.name;
17861786

17871787
// delete entry from the list
1788-
testUnitData.splice(i, 1);
1788+
ts.orderedRemoveItemAt(testUnitData, i);
17891789

17901790
break;
17911791
}

src/harness/unittests/tsserverProjectSystem.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -199,17 +199,13 @@ namespace ts {
199199
watchDirectory(directoryName: string, callback: DirectoryWatcherCallback, recursive: boolean): DirectoryWatcher {
200200
const path = this.toPath(directoryName);
201201
const callbacks = this.watchedDirectories[path] || (this.watchedDirectories[path] = []);
202-
callbacks.push({ cb: callback, recursive });
202+
const cbWithRecursive = { cb: callback, recursive };
203+
callbacks.push(cbWithRecursive);
203204
return {
204205
referenceCount: 0,
205206
directoryName,
206207
close: () => {
207-
for (let i = 0; i < callbacks.length; i++) {
208-
if (callbacks[i].cb === callback) {
209-
callbacks.splice(i, 1);
210-
break;
211-
}
212-
}
208+
unorderedRemoveItem(callbacks, cbWithRecursive);
213209
if (!callbacks.length) {
214210
delete this.watchedDirectories[path];
215211
}
@@ -243,8 +239,7 @@ namespace ts {
243239
callbacks.push(callback);
244240
return {
245241
close: () => {
246-
const i = callbacks.indexOf(callback);
247-
callbacks.splice(i, 1);
242+
unorderedRemoveItem(callbacks, callback);
248243
if (!callbacks.length) {
249244
delete this.watchedFiles[path];
250245
}
@@ -259,7 +254,7 @@ namespace ts {
259254
};
260255
readonly clearTimeout = (timeoutId: any): void => {
261256
if (typeof timeoutId === "number") {
262-
this.callbackQueue.splice(timeoutId, 1);
257+
orderedRemoveItemAt(this.callbackQueue, timeoutId);
263258
}
264259
};
265260

src/server/editorServices.ts

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ namespace ts.server {
275275
removeRoot(info: ScriptInfo) {
276276
if (this.filenameToScript.contains(info.path)) {
277277
this.filenameToScript.remove(info.path);
278-
this.roots = copyListRemovingItem(info, this.roots);
278+
unorderedRemoveItem(this.roots, info);
279279
this.resolvedModuleNames.remove(info.path);
280280
this.resolvedTypeReferenceDirectives.remove(info.path);
281281
}
@@ -585,16 +585,6 @@ namespace ts.server {
585585
project?: Project;
586586
}
587587

588-
function copyListRemovingItem<T>(item: T, list: T[]) {
589-
const copiedList: T[] = [];
590-
for (let i = 0, len = list.length; i < len; i++) {
591-
if (list[i] != item) {
592-
copiedList.push(list[i]);
593-
}
594-
}
595-
return copiedList;
596-
}
597-
598588
/**
599589
* This helper funciton processes a list of projects and return the concatenated, sortd and deduplicated output of processing each project.
600590
*/
@@ -880,7 +870,7 @@ namespace ts.server {
880870
project.directoryWatcher.close();
881871
forEachProperty(project.directoriesWatchedForWildcards, watcher => { watcher.close(); });
882872
delete project.directoriesWatchedForWildcards;
883-
this.configuredProjects = copyListRemovingItem(project, this.configuredProjects);
873+
unorderedRemoveItem(this.configuredProjects, project);
884874
}
885875
else {
886876
for (const directory of project.directoriesWatchedForTsconfig) {
@@ -892,7 +882,7 @@ namespace ts.server {
892882
delete project.projectService.directoryWatchersForTsconfig[directory];
893883
}
894884
}
895-
this.inferredProjects = copyListRemovingItem(project, this.inferredProjects);
885+
unorderedRemoveItem(this.inferredProjects, project);
896886
}
897887

898888
const fileNames = project.getFileNames();
@@ -1017,7 +1007,7 @@ namespace ts.server {
10171007
}
10181008
}
10191009
else {
1020-
this.openFilesReferenced = copyListRemovingItem(info, this.openFilesReferenced);
1010+
unorderedRemoveItem(this.openFilesReferenced, info);
10211011
}
10221012
info.close();
10231013
}
@@ -1524,13 +1514,13 @@ namespace ts.server {
15241514
// openFileRoots or openFileReferenced.
15251515
if (info.isOpen) {
15261516
if (this.openFileRoots.indexOf(info) >= 0) {
1527-
this.openFileRoots = copyListRemovingItem(info, this.openFileRoots);
1517+
unorderedRemoveItem(this.openFileRoots, info);
15281518
if (info.defaultProject && !info.defaultProject.isConfiguredProject()) {
15291519
this.removeProject(info.defaultProject);
15301520
}
15311521
}
15321522
if (this.openFilesReferenced.indexOf(info) >= 0) {
1533-
this.openFilesReferenced = copyListRemovingItem(info, this.openFilesReferenced);
1523+
unorderedRemoveItem(this.openFilesReferenced, info);
15341524
}
15351525
this.openFileRootsConfigured.push(info);
15361526
info.defaultProject = project;

src/server/server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ namespace ts.server {
204204
// average async stat takes about 30 microseconds
205205
// set chunk size to do 30 files in < 1 millisecond
206206
function createPollingWatchedFileSet(interval = 2500, chunkSize = 30) {
207-
let watchedFiles: WatchedFile[] = [];
207+
const watchedFiles: WatchedFile[] = [];
208208
let nextFileToCheck = 0;
209209
let watchTimer: any;
210210

@@ -267,7 +267,7 @@ namespace ts.server {
267267
}
268268

269269
function removeFile(file: WatchedFile) {
270-
watchedFiles = copyListRemovingItem(file, watchedFiles);
270+
unorderedRemoveItem(watchedFiles, file);
271271
}
272272

273273
return {

0 commit comments

Comments
 (0)