Skip to content

Commit cf31308

Browse files
authored
Merge pull request microsoft#184452 from microsoft/tyriar/184323
Clean up lifecycle of MainThreadTerminalService
2 parents 909e55f + 87ba176 commit cf31308

File tree

1 file changed

+39
-29
lines changed

1 file changed

+39
-29
lines changed

src/vs/workbench/api/browser/mainThreadTerminalService.ts

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { DisposableStore, Disposable, IDisposable } from 'vs/base/common/lifecycle';
6+
import { DisposableStore, Disposable, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
77
import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, TerminalLaunchConfig, ITerminalDimensionsDto, ExtHostTerminalIdentifier, TerminalQuickFix } from 'vs/workbench/api/common/extHost.protocol';
88
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
99
import { URI } from 'vs/base/common/uri';
@@ -33,18 +33,19 @@ import { ITerminalQuickFixService, ITerminalQuickFixOptions, ITerminalQuickFix }
3333
@extHostNamedCustomer(MainContext.MainThreadTerminalService)
3434
export class MainThreadTerminalService implements MainThreadTerminalServiceShape {
3535

36-
private _proxy: ExtHostTerminalServiceShape;
36+
private readonly _store = new DisposableStore();
37+
private readonly _proxy: ExtHostTerminalServiceShape;
38+
3739
/**
3840
* Stores a map from a temporary terminal id (a UUID generated on the extension host side)
3941
* to a numeric terminal id (an id generated on the renderer side)
4042
* This comes in play only when dealing with terminals created on the extension host side
4143
*/
42-
private _extHostTerminals = new Map<string, Promise<ITerminalInstance>>();
43-
private readonly _toDispose = new DisposableStore();
44+
private readonly _extHostTerminals = new Map<string, Promise<ITerminalInstance>>();
4445
private readonly _terminalProcessProxies = new Map<number, ITerminalProcessExtHostProxy>();
4546
private readonly _profileProviders = new Map<string, IDisposable>();
4647
private readonly _quickFixProviders = new Map<string, IDisposable>();
47-
private _dataEventTracker: TerminalDataEventTracker | undefined;
48+
private readonly _dataEventTracker = new MutableDisposable<TerminalDataEventTracker>();
4849
/**
4950
* A single shared terminal link provider for the exthost. When an ext registers a link
5051
* provider, this is registered with the terminal on the renderer side and all links are
@@ -72,25 +73,25 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
7273
this._proxy = _extHostContext.getProxy(ExtHostContext.ExtHostTerminalService);
7374

7475
// ITerminalService listeners
75-
this._toDispose.add(_terminalService.onDidCreateInstance((instance) => {
76+
this._store.add(_terminalService.onDidCreateInstance((instance) => {
7677
this._onTerminalOpened(instance);
7778
this._onInstanceDimensionsChanged(instance);
7879
}));
7980

80-
this._toDispose.add(_terminalService.onDidDisposeInstance(instance => this._onTerminalDisposed(instance)));
81-
this._toDispose.add(_terminalService.onDidReceiveProcessId(instance => this._onTerminalProcessIdReady(instance)));
82-
this._toDispose.add(_terminalService.onDidChangeInstanceDimensions(instance => this._onInstanceDimensionsChanged(instance)));
83-
this._toDispose.add(_terminalService.onDidMaximumDimensionsChange(instance => this._onInstanceMaximumDimensionsChanged(instance)));
84-
this._toDispose.add(_terminalService.onDidRequestStartExtensionTerminal(e => this._onRequestStartExtensionTerminal(e)));
85-
this._toDispose.add(_terminalService.onDidChangeActiveInstance(instance => this._onActiveTerminalChanged(instance ? instance.instanceId : null)));
86-
this._toDispose.add(_terminalService.onDidChangeInstanceTitle(instance => instance && this._onTitleChanged(instance.instanceId, instance.title)));
87-
this._toDispose.add(_terminalService.onDidInputInstanceData(instance => this._proxy.$acceptTerminalInteraction(instance.instanceId)));
81+
this._store.add(_terminalService.onDidDisposeInstance(instance => this._onTerminalDisposed(instance)));
82+
this._store.add(_terminalService.onDidReceiveProcessId(instance => this._onTerminalProcessIdReady(instance)));
83+
this._store.add(_terminalService.onDidChangeInstanceDimensions(instance => this._onInstanceDimensionsChanged(instance)));
84+
this._store.add(_terminalService.onDidMaximumDimensionsChange(instance => this._onInstanceMaximumDimensionsChanged(instance)));
85+
this._store.add(_terminalService.onDidRequestStartExtensionTerminal(e => this._onRequestStartExtensionTerminal(e)));
86+
this._store.add(_terminalService.onDidChangeActiveInstance(instance => this._onActiveTerminalChanged(instance ? instance.instanceId : null)));
87+
this._store.add(_terminalService.onDidChangeInstanceTitle(instance => instance && this._onTitleChanged(instance.instanceId, instance.title)));
88+
this._store.add(_terminalService.onDidInputInstanceData(instance => this._proxy.$acceptTerminalInteraction(instance.instanceId)));
8889

8990
// Set initial ext host state
90-
this._terminalService.instances.forEach(t => {
91-
this._onTerminalOpened(t);
92-
t.processReady.then(() => this._onTerminalProcessIdReady(t));
93-
});
91+
for (const instance of this._terminalService.instances) {
92+
this._onTerminalOpened(instance);
93+
instance.processReady.then(() => this._onTerminalProcessIdReady(instance));
94+
}
9495
const activeInstance = this._terminalService.activeInstance;
9596
if (activeInstance) {
9697
this._proxy.$acceptActiveTerminalChanged(activeInstance.instanceId);
@@ -107,12 +108,18 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
107108
this._os = env?.os || OS;
108109
this._updateDefaultProfile();
109110
});
110-
this._terminalProfileService.onDidChangeAvailableProfiles(() => this._updateDefaultProfile());
111+
this._store.add(this._terminalProfileService.onDidChangeAvailableProfiles(() => this._updateDefaultProfile()));
111112
}
112113

113114
public dispose(): void {
114-
this._toDispose.dispose();
115+
this._store.dispose();
115116
this._linkProvider?.dispose();
117+
for (const provider of this._profileProviders.values()) {
118+
provider.dispose();
119+
}
120+
for (const provider of this._quickFixProviders.values()) {
121+
provider.dispose();
122+
}
116123
}
117124

118125
private async _updateDefaultProfile() {
@@ -161,7 +168,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
161168
});
162169
this._extHostTerminals.set(extHostTerminalId, terminal);
163170
const terminalInstance = await terminal;
164-
this._toDispose.add(terminalInstance.onDisposed(() => {
171+
this._store.add(terminalInstance.onDisposed(() => {
165172
this._extHostTerminals.delete(extHostTerminalId);
166173
}));
167174
}
@@ -208,20 +215,21 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
208215
}
209216

210217
public $startSendingDataEvents(): void {
211-
if (!this._dataEventTracker) {
212-
this._dataEventTracker = this._instantiationService.createInstance(TerminalDataEventTracker, (id, data) => {
218+
if (!this._dataEventTracker.value) {
219+
this._dataEventTracker.value = this._instantiationService.createInstance(TerminalDataEventTracker, (id, data) => {
213220
this._onTerminalData(id, data);
214221
});
215222
// Send initial events if they exist
216-
this._terminalService.instances.forEach(t => {
217-
t.initialDataEvents?.forEach(d => this._onTerminalData(t.instanceId, d));
218-
});
223+
for (const instance of this._terminalService.instances) {
224+
for (const data of instance.initialDataEvents || []) {
225+
this._onTerminalData(instance.instanceId, data);
226+
}
227+
}
219228
}
220229
}
221230

222231
public $stopSendingDataEvents(): void {
223-
this._dataEventTracker?.dispose();
224-
this._dataEventTracker = undefined;
232+
this._dataEventTracker.clear();
225233
}
226234

227235
public $startLinkProvider(): void {
@@ -429,7 +437,9 @@ class TerminalDataEventTracker extends Disposable {
429437

430438
this._register(this._bufferer = new TerminalDataBufferer(this._callback));
431439

432-
this._terminalService.instances.forEach(instance => this._registerInstance(instance));
440+
for (const instance of this._terminalService.instances) {
441+
this._registerInstance(instance);
442+
}
433443
this._register(this._terminalService.onDidCreateInstance(instance => this._registerInstance(instance)));
434444
this._register(this._terminalService.onDidDisposeInstance(instance => this._bufferer.stopBuffering(instance.instanceId)));
435445
}

0 commit comments

Comments
 (0)