Skip to content

Commit 538da53

Browse files
authored
Dispose of file watchers when web TS server exits (microsoft#185815)
Dispose of file watchers when TS server exits
1 parent b866b29 commit 538da53

File tree

5 files changed

+48
-35
lines changed

5 files changed

+48
-35
lines changed

extensions/typescript-language-features/src/languageFeatures/diagnostics.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ export class DiagnosticsManager extends Disposable {
170170
public override dispose() {
171171
super.dispose();
172172

173-
for (const value of this._pendingUpdates.values) {
173+
for (const value of this._pendingUpdates.values()) {
174174
clearTimeout(value);
175175
}
176176
this._pendingUpdates.clear();
@@ -259,7 +259,7 @@ export class DiagnosticsManager extends Disposable {
259259

260260
private rebuildAll(): void {
261261
this._currentDiagnostics.clear();
262-
for (const fileDiagnostic of this._diagnostics.values) {
262+
for (const fileDiagnostic of this._diagnostics.values()) {
263263
this.rebuildFile(fileDiagnostic);
264264
}
265265
}

extensions/typescript-language-features/src/tsServer/bufferSyncSupport.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ class BufferSynchronizer {
146146
const closedFiles: string[] = [];
147147
const openFiles: Proto.OpenRequestArgs[] = [];
148148
const changedFiles: Proto.FileCodeEdits[] = [];
149-
for (const change of this._pending.values) {
149+
for (const change of this._pending.values()) {
150150
switch (change.type) {
151151
case BufferOperationType.Change: changedFiles.push(change.args); break;
152152
case BufferOperationType.Open: openFiles.push(change.args); break;
@@ -270,13 +270,13 @@ class SyncedBufferMap extends ResourceMap<SyncedBuffer> {
270270
}
271271

272272
public get allBuffers(): Iterable<SyncedBuffer> {
273-
return this.values;
273+
return this.values();
274274
}
275275
}
276276

277277
class PendingDiagnostics extends ResourceMap<number> {
278278
public getOrderedFileSet(): ResourceMap<void> {
279-
const orderedResources = Array.from(this.entries)
279+
const orderedResources = Array.from(this.entries())
280280
.sort((a, b) => a.value - b.value)
281281
.map(entry => entry.resource);
282282

@@ -313,7 +313,7 @@ class GetErrRequest {
313313
}
314314

315315
const supportsSyntaxGetErr = this.client.apiVersion.gte(API.v440);
316-
const allFiles = coalesce(Array.from(files.entries)
316+
const allFiles = coalesce(Array.from(files.entries())
317317
.filter(entry => supportsSyntaxGetErr || client.hasCapabilityForResource(entry.resource, ClientCapability.Semantic))
318318
.map(entry => client.toTsFilePath(entry.resource)));
319319

@@ -711,7 +711,7 @@ export default class BufferSyncSupport extends Disposable {
711711
if (this.pendingGetErr) {
712712
this.pendingGetErr.cancel();
713713

714-
for (const { resource } of this.pendingGetErr.files.entries) {
714+
for (const { resource } of this.pendingGetErr.files.entries()) {
715715
if (this.syncedBuffers.get(resource)) {
716716
orderedFileSet.set(resource, undefined);
717717
}
@@ -721,7 +721,7 @@ export default class BufferSyncSupport extends Disposable {
721721
}
722722

723723
// Add all open TS buffers to the geterr request. They might be visible
724-
for (const buffer of this.syncedBuffers.values) {
724+
for (const buffer of this.syncedBuffers.values()) {
725725
orderedFileSet.set(buffer.resource, undefined);
726726
}
727727

extensions/typescript-language-features/src/tsServer/fileWatchingManager.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ import { Logger } from '../logging/logger';
1010
import { disposeAll, IDisposable } from '../utils/dispose';
1111
import { ResourceMap } from '../utils/resourceMap';
1212

13-
type DirWatcherEntry = {
13+
interface DirWatcherEntry {
1414
readonly uri: vscode.Uri;
1515
readonly listeners: IDisposable[];
16-
};
16+
}
1717

1818

19-
export class FileWatcherManager {
19+
export class FileWatcherManager implements IDisposable {
2020

2121
private readonly _fileWatchers = new Map<number, {
2222
readonly uri: vscode.Uri;
@@ -34,6 +34,18 @@ export class FileWatcherManager {
3434
private readonly logger: Logger,
3535
) { }
3636

37+
dispose(): void {
38+
for (const entry of this._fileWatchers.values()) {
39+
entry.watcher.dispose();
40+
}
41+
this._fileWatchers.clear();
42+
43+
for (const entry of this._dirWatchers.values()) {
44+
entry.watcher.dispose();
45+
}
46+
this._dirWatchers.clear();
47+
}
48+
3749
create(id: number, uri: vscode.Uri, watchParentDirs: boolean, isRecursive: boolean, listeners: { create?: (uri: vscode.Uri) => void; change?: (uri: vscode.Uri) => void; delete?: (uri: vscode.Uri) => void }): void {
3850
this.logger.trace(`Creating file watcher for ${uri.toString()}`);
3951

extensions/typescript-language-features/src/tsServer/serverProcess.browser.ts

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,16 @@ class WorkerServerProcess implements TsServerProcess {
6262
private readonly _onDataHandlers = new Set<(data: Proto.Response) => void>();
6363
private readonly _onErrorHandlers = new Set<(err: Error) => void>();
6464
private readonly _onExitHandlers = new Set<(code: number | null, signal: string | null) => void>();
65-
private readonly _watches: FileWatcherManager;
6665

67-
private readonly worker: Worker;
66+
private readonly _worker: Worker;
67+
private readonly _watches: FileWatcherManager;
6868

6969
/** For communicating with TS server synchronously */
70-
private readonly tsserver: MessagePort;
70+
private readonly _tsserver: MessagePort;
7171
/** For communicating watches asynchronously */
72-
private readonly watcher: MessagePort;
72+
private readonly _watcher: MessagePort;
7373
/** For communicating with filesystem synchronously */
74-
private readonly syncFs: MessagePort;
74+
private readonly _syncFs: MessagePort;
7575

7676
public constructor(
7777
private readonly kind: TsServerProcessKind,
@@ -81,18 +81,18 @@ class WorkerServerProcess implements TsServerProcess {
8181
private readonly tsServerLog: TsServerLog | undefined,
8282
logger: Logger,
8383
) {
84-
this.worker = new Worker(tsServerPath, { name: `TS ${kind} server #${this.id}` });
84+
this._worker = new Worker(tsServerPath, { name: `TS ${kind} server #${this.id}` });
8585

8686
this._watches = new FileWatcherManager(logger);
8787

8888
const tsserverChannel = new MessageChannel();
8989
const watcherChannel = new MessageChannel();
9090
const syncChannel = new MessageChannel();
91-
this.tsserver = tsserverChannel.port2;
92-
this.watcher = watcherChannel.port2;
93-
this.syncFs = syncChannel.port2;
91+
this._tsserver = tsserverChannel.port2;
92+
this._watcher = watcherChannel.port2;
93+
this._syncFs = syncChannel.port2;
9494

95-
this.tsserver.onmessage = (event) => {
95+
this._tsserver.onmessage = (event) => {
9696
if (event.data.type === 'log') {
9797
console.error(`unexpected log message on tsserver channel: ${JSON.stringify(event)}`);
9898
return;
@@ -102,7 +102,7 @@ class WorkerServerProcess implements TsServerProcess {
102102
}
103103
};
104104

105-
this.watcher.onmessage = (event: MessageEvent<BrowserWatchEvent>) => {
105+
this._watcher.onmessage = (event: MessageEvent<BrowserWatchEvent>) => {
106106
switch (event.data.type) {
107107
case 'dispose': {
108108
this._watches.delete(event.data.id);
@@ -111,9 +111,9 @@ class WorkerServerProcess implements TsServerProcess {
111111
case 'watchDirectory':
112112
case 'watchFile': {
113113
this._watches.create(event.data.id, vscode.Uri.from(event.data.uri), /*watchParentDirs*/ true, !!event.data.recursive, {
114-
change: uri => this.watcher.postMessage({ type: 'watch', event: 'change', uri }),
115-
create: uri => this.watcher.postMessage({ type: 'watch', event: 'create', uri }),
116-
delete: uri => this.watcher.postMessage({ type: 'watch', event: 'delete', uri }),
114+
change: uri => this._watcher.postMessage({ type: 'watch', event: 'change', uri }),
115+
create: uri => this._watcher.postMessage({ type: 'watch', event: 'create', uri }),
116+
delete: uri => this._watcher.postMessage({ type: 'watch', event: 'delete', uri }),
117117
});
118118
break;
119119
}
@@ -122,7 +122,7 @@ class WorkerServerProcess implements TsServerProcess {
122122
}
123123
};
124124

125-
this.worker.onmessage = (msg: any) => {
125+
this._worker.onmessage = (msg: any) => {
126126
// for logging only
127127
if (msg.data.type === 'log') {
128128
this.appendLog(msg.data.body);
@@ -131,15 +131,15 @@ class WorkerServerProcess implements TsServerProcess {
131131
console.error(`unexpected message on main channel: ${JSON.stringify(msg)}`);
132132
};
133133

134-
this.worker.onerror = (err: ErrorEvent) => {
134+
this._worker.onerror = (err: ErrorEvent) => {
135135
console.error('error! ' + JSON.stringify(err));
136136
for (const handler of this._onErrorHandlers) {
137137
// TODO: The ErrorEvent type might be wrong; previously this was typed as Error and didn't have the property access.
138138
handler(err.error);
139139
}
140140
};
141141

142-
this.worker.postMessage(
142+
this._worker.postMessage(
143143
{ args, extensionUri },
144144
[syncChannel.port1, tsserverChannel.port1, watcherChannel.port1]
145145
);
@@ -150,7 +150,7 @@ class WorkerServerProcess implements TsServerProcess {
150150
}
151151

152152
write(serverRequest: Proto.Request): void {
153-
this.tsserver.postMessage(serverRequest);
153+
this._tsserver.postMessage(serverRequest);
154154
}
155155

156156
onData(handler: (response: Proto.Response) => void): void {
@@ -167,10 +167,11 @@ class WorkerServerProcess implements TsServerProcess {
167167
}
168168

169169
kill(): void {
170-
this.worker.terminate();
171-
this.tsserver.close();
172-
this.watcher.close();
173-
this.syncFs.close();
170+
this._worker.terminate();
171+
this._tsserver.close();
172+
this._watcher.close();
173+
this._syncFs.close();
174+
this._watches.dispose();
174175
}
175176

176177
private appendLog(msg: string) {

extensions/typescript-language-features/src/utils/resourceMap.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ export class ResourceMap<T> {
7373
this._map.clear();
7474
}
7575

76-
public get values(): Iterable<T> {
76+
public values(): Iterable<T> {
7777
return Array.from(this._map.values(), x => x.value);
7878
}
7979

80-
public get entries(): Iterable<{ resource: vscode.Uri; value: T }> {
80+
public entries(): Iterable<{ resource: vscode.Uri; value: T }> {
8181
return this._map.values();
8282
}
8383

0 commit comments

Comments
 (0)