Skip to content
Open
Changes from all 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
50 changes: 17 additions & 33 deletions src/vs/workbench/api/browser/mainThreadTerminalService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { DisposableStore, Disposable, IDisposable, MutableDisposable, combinedDisposable, toDisposable } from '../../../base/common/lifecycle.js';
import { DisposableStore, Disposable, IDisposable, MutableDisposable, combinedDisposable, toDisposable, DisposableMap } from '../../../base/common/lifecycle.js';
import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, TerminalLaunchConfig, ITerminalDimensionsDto, ExtHostTerminalIdentifier, TerminalQuickFix, ITerminalCommandDto } from '../common/extHost.protocol.js';
import { extHostNamedCustomer, IExtHostContext } from '../../services/extensions/common/extHostCustomers.js';
import { URI } from '../../../base/common/uri.js';
Expand All @@ -28,6 +28,10 @@ import { ITerminalCompletionService } from '../../contrib/terminalContrib/sugges
import { IWorkbenchEnvironmentService } from '../../services/environment/common/environmentService.js';
import { hasKey } from '../../../base/common/types.js';

interface TerminalProcessProxyEntry extends IDisposable {
readonly proxy: ITerminalProcessExtHostProxy;
}

@extHostNamedCustomer(MainContext.MainThreadTerminalService)
export class MainThreadTerminalService extends Disposable implements MainThreadTerminalServiceShape {

Expand All @@ -39,10 +43,10 @@ export class MainThreadTerminalService extends Disposable implements MainThreadT
* This comes in play only when dealing with terminals created on the extension host side
*/
private readonly _extHostTerminals = new Map<string, Promise<ITerminalInstance>>();
private readonly _terminalProcessProxies = new Map<number, { proxy: ITerminalProcessExtHostProxy; store: DisposableStore }>();
private readonly _profileProviders = new Map<string, IDisposable>();
private readonly _completionProviders = new Map<string, IDisposable>();
private readonly _quickFixProviders = new Map<string, IDisposable>();
private readonly _terminalProcessProxies = this._register(new DisposableMap<number, TerminalProcessProxyEntry>());
private readonly _profileProviders = this._register(new DisposableMap<string, IDisposable>());
private readonly _completionProviders = this._register(new DisposableMap<string, IDisposable>());
private readonly _quickFixProviders = this._register(new DisposableMap<string, IDisposable>());
private readonly _dataEventTracker = this._register(new MutableDisposable<TerminalDataEventTracker>());
private readonly _sendCommandEventListener = this._register(new MutableDisposable());

Expand Down Expand Up @@ -112,28 +116,15 @@ export class MainThreadTerminalService extends Disposable implements MainThreadT
this._proxy.$initEnvironmentVariableCollections(serializedCollections);
}

this._store.add(toDisposable(() => {
for (const e of this._terminalProcessProxies.values()) {
e.proxy.dispose();
e.store.dispose();
}
this._terminalProcessProxies.clear();
}));


remoteAgentService.getEnvironment().then(async env => {
this._os = env?.os || OS;
this._updateDefaultProfile();
});
this._register(this._terminalProfileService.onDidChangeAvailableProfiles(() => this._updateDefaultProfile()));

this._register(toDisposable(() => {
for (const provider of this._profileProviders.values()) {
provider.dispose();
}
for (const provider of this._quickFixProviders.values()) {
provider.dispose();
}
}));

}

private async _updateDefaultProfile() {
Expand Down Expand Up @@ -313,8 +304,7 @@ export class MainThreadTerminalService extends Disposable implements MainThreadT
}

public $unregisterCompletionProvider(id: string): void {
this._completionProviders.get(id)?.dispose();
this._completionProviders.delete(id);
this._completionProviders.deleteAndDispose(id);
}

public $registerProfileProvider(id: string, extensionIdentifier: string): void {
Expand All @@ -327,8 +317,7 @@ export class MainThreadTerminalService extends Disposable implements MainThreadT
}

public $unregisterProfileProvider(id: string): void {
this._profileProviders.get(id)?.dispose();
this._profileProviders.delete(id);
this._profileProviders.deleteAndDispose(id);
}

public async $registerQuickFixProvider(id: string, extensionId: string): Promise<void> {
Expand Down Expand Up @@ -369,8 +358,7 @@ export class MainThreadTerminalService extends Disposable implements MainThreadT
}

public $unregisterQuickFixProvider(id: string): void {
this._quickFixProviders.get(id)?.dispose();
this._quickFixProviders.delete(id);
this._quickFixProviders.deleteAndDispose(id);
}

private _onActiveTerminalChanged(terminalId: number | null): void {
Expand Down Expand Up @@ -398,12 +386,7 @@ export class MainThreadTerminalService extends Disposable implements MainThreadT

private _onTerminalDisposed(terminalInstance: ITerminalInstance): void {
this._proxy.$acceptTerminalClosed(terminalInstance.instanceId, terminalInstance.exitCode, terminalInstance.exitReason ?? TerminalExitReason.Unknown);
const proxy = this._terminalProcessProxies.get(terminalInstance.instanceId);
if (proxy) {
proxy.proxy.dispose();
proxy.store.dispose();
this._terminalProcessProxies.delete(terminalInstance.instanceId);
}
this._terminalProcessProxies.deleteAndDispose(terminalInstance.instanceId);
}

private _onTerminalOpened(terminalInstance: ITerminalInstance): void {
Expand Down Expand Up @@ -438,7 +421,8 @@ export class MainThreadTerminalService extends Disposable implements MainThreadT
private _onRequestStartExtensionTerminal(request: IStartExtensionTerminalRequest): void {
const proxy = request.proxy;
const store = new DisposableStore();
this._terminalProcessProxies.set(proxy.instanceId, { proxy, store });
store.add(proxy);
this._terminalProcessProxies.set(proxy.instanceId, { proxy, dispose() { store.dispose(); } });

// Note that onResize is not being listened to here as it needs to fire when max dimensions
// change, excluding the dimension override
Expand Down