Skip to content

Commit b725a17

Browse files
committed
Prefer direct channel
1 parent b386bae commit b725a17

File tree

1 file changed

+52
-45
lines changed

1 file changed

+52
-45
lines changed

src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalBackend.ts

Lines changed: 52 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ export class LocalTerminalBackendContribution implements IWorkbenchContribution
5050
class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBackend {
5151
private readonly _ptys: Map<number, LocalPty> = new Map();
5252

53+
private _ptyHostDirectProxy: IPtyService | undefined;
54+
5355
private readonly _onDidRequestDetach = this._register(new Emitter<{ requestId: number; workspaceId: string; instanceId: number }>());
5456
readonly onDidRequestDetach = this._onDidRequestDetach.event;
5557

@@ -71,96 +73,100 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke
7173
@IEnvironmentVariableService private readonly _environmentVariableService: IEnvironmentVariableService,
7274
@INotificationService notificationService: INotificationService,
7375
@IHistoryService historyService: IHistoryService,
74-
@INativeWorkbenchEnvironmentService environmentService: INativeWorkbenchEnvironmentService
76+
@INativeWorkbenchEnvironmentService private readonly _environmentService: INativeWorkbenchEnvironmentService
7577
) {
7678
super(_localPtyService, logService, notificationService, historyService, _configurationResolverService, workspaceContextService);
7779

80+
// TODO: If we connect async like this, there may be a race condition where messages go missing before the message port is established
81+
this._start();
82+
}
83+
84+
private async _start() {
85+
7886
// TODO: Use the direct connection
79-
(async () => {
80-
mark('code/willConnectPtyHost');
81-
logService.trace('Renderer->PtyHost#connect: before acquirePort');
82-
const port = await acquirePort('vscode:createPtyHostMessageChannel', 'vscode:createPtyHostMessageChannelResult');
83-
mark('code/didConnectPtyHost');
84-
logService.trace('Renderer->PtyHost#connect: connection established');
85-
86-
const client = new MessagePortClient(port, `window:${environmentService.window.id}`);
87-
const proxy = ProxyChannel.toService<IPtyService>(client.getChannel(TerminalIpcChannels.PtyHostWindow));
88-
89-
// Testing
90-
logService.info('latency: ', proxy.getLatency(0));
91-
proxy.onProcessData(e => {
92-
logService.info('message port process data: ' + e.event);
93-
});
94-
})();
87+
mark('code/willConnectPtyHost');
88+
this._logService.trace('Renderer->PtyHost#connect: before acquirePort');
89+
const port = await acquirePort('vscode:createPtyHostMessageChannel', 'vscode:createPtyHostMessageChannelResult');
90+
mark('code/didConnectPtyHost');
91+
this._logService.trace('Renderer->PtyHost#connect: connection established');
92+
93+
const client = new MessagePortClient(port, `window:${this._environmentService.window.id}`);
94+
this._ptyHostDirectProxy = ProxyChannel.toService<IPtyService>(client.getChannel(TerminalIpcChannels.PtyHostWindow));
95+
96+
// Testing
97+
// this._logService.info('latency: ', this._ptyHostDirectProxy.getLatency(0));
98+
// this._ptyHostDirectProxy.onProcessData(e => {
99+
// this._logService.info('message port process data: ' + e.event);
100+
// });
95101

96102
// Attach process listeners
97-
this._localPtyService.onProcessData(e => this._ptys.get(e.id)?.handleData(e.event));
98-
this._localPtyService.onDidChangeProperty(e => this._ptys.get(e.id)?.handleDidChangeProperty(e.property));
99-
this._localPtyService.onProcessExit(e => {
103+
this._ptyHostDirectProxy!.onProcessData(e => this._ptys.get(e.id)?.handleData(e.event));
104+
this._ptyHostDirectProxy!.onDidChangeProperty(e => this._ptys.get(e.id)?.handleDidChangeProperty(e.property));
105+
this._ptyHostDirectProxy!.onProcessExit(e => {
100106
const pty = this._ptys.get(e.id);
101107
if (pty) {
102108
pty.handleExit(e.event);
103109
this._ptys.delete(e.id);
104110
}
105111
});
106-
this._localPtyService.onProcessReady(e => this._ptys.get(e.id)?.handleReady(e.event));
107-
this._localPtyService.onProcessReplay(e => this._ptys.get(e.id)?.handleReplay(e.event));
108-
this._localPtyService.onProcessOrphanQuestion(e => this._ptys.get(e.id)?.handleOrphanQuestion());
109-
this._localPtyService.onDidRequestDetach(e => this._onDidRequestDetach.fire(e));
112+
this._ptyHostDirectProxy!.onProcessReady(e => this._ptys.get(e.id)?.handleReady(e.event));
113+
this._ptyHostDirectProxy!.onProcessReplay(e => this._ptys.get(e.id)?.handleReplay(e.event));
114+
this._ptyHostDirectProxy!.onProcessOrphanQuestion(e => this._ptys.get(e.id)?.handleOrphanQuestion());
115+
this._ptyHostDirectProxy!.onDidRequestDetach(e => this._onDidRequestDetach.fire(e));
110116

111117
// Listen for config changes
112-
const initialConfig = configurationService.getValue<ITerminalConfiguration>(TERMINAL_CONFIG_SECTION);
118+
const initialConfig = this._configurationService.getValue<ITerminalConfiguration>(TERMINAL_CONFIG_SECTION);
113119
for (const match of Object.keys(initialConfig.autoReplies)) {
114120
// Ensure the reply is value
115121
const reply = initialConfig.autoReplies[match] as string | null;
116122
if (reply) {
117-
this._localPtyService.installAutoReply(match, reply);
123+
this._ptyHostDirectProxy!.installAutoReply(match, reply);
118124
}
119125
}
120126
// TODO: Could simplify update to a single call
121-
this._register(configurationService.onDidChangeConfiguration(async e => {
127+
this._register(this._configurationService.onDidChangeConfiguration(async e => {
122128
if (e.affectsConfiguration(TerminalSettingId.AutoReplies)) {
123-
this._localPtyService.uninstallAllAutoReplies();
124-
const config = configurationService.getValue<ITerminalConfiguration>(TERMINAL_CONFIG_SECTION);
129+
this._ptyHostDirectProxy!.uninstallAllAutoReplies();
130+
const config = this._configurationService.getValue<ITerminalConfiguration>(TERMINAL_CONFIG_SECTION);
125131
for (const match of Object.keys(config.autoReplies)) {
126132
// Ensure the reply is value
127133
const reply = config.autoReplies[match] as string | null;
128134
if (reply) {
129-
await this._localPtyService.installAutoReply(match, reply);
135+
await this._ptyHostDirectProxy!.installAutoReply(match, reply);
130136
}
131137
}
132138
}
133139
}));
134140
}
135141

136142
async requestDetachInstance(workspaceId: string, instanceId: number): Promise<IProcessDetails | undefined> {
137-
return this._localPtyService.requestDetachInstance(workspaceId, instanceId);
143+
return this._ptyHostDirectProxy!.requestDetachInstance(workspaceId, instanceId);
138144
}
139145

140146
async acceptDetachInstanceReply(requestId: number, persistentProcessId?: number): Promise<void> {
141147
if (!persistentProcessId) {
142148
this._logService.warn('Cannot attach to feature terminals, custom pty terminals, or those without a persistentProcessId');
143149
return;
144150
}
145-
return this._localPtyService.acceptDetachInstanceReply(requestId, persistentProcessId);
151+
return this._ptyHostDirectProxy!.acceptDetachInstanceReply(requestId, persistentProcessId);
146152
}
147153

148154
async persistTerminalState(): Promise<void> {
149155
const ids = Array.from(this._ptys.keys());
150-
const serialized = await this._localPtyService.serializeTerminalState(ids);
156+
const serialized = await this._ptyHostDirectProxy!.serializeTerminalState(ids);
151157
this._storageService.store(TerminalStorageKeys.TerminalBufferState, serialized, StorageScope.WORKSPACE, StorageTarget.MACHINE);
152158
}
153159

154160
async updateTitle(id: number, title: string, titleSource: TitleEventSource): Promise<void> {
155-
await this._localPtyService.updateTitle(id, title, titleSource);
161+
await this._ptyHostDirectProxy!.updateTitle(id, title, titleSource);
156162
}
157163

158164
async updateIcon(id: number, userInitiated: boolean, icon: URI | { light: URI; dark: URI } | { id: string; color?: { id: string } }, color?: string): Promise<void> {
159-
await this._localPtyService.updateIcon(id, userInitiated, icon, color);
165+
await this._ptyHostDirectProxy!.updateIcon(id, userInitiated, icon, color);
160166
}
161167

162168
updateProperty<T extends ProcessPropertyType>(id: number, property: ProcessPropertyType, value: IProcessPropertyMap[T]): Promise<void> {
163-
return this._localPtyService.updateProperty(id, property, value);
169+
return this._ptyHostDirectProxy!.updateProperty(id, property, value);
164170
}
165171

166172
async createProcess(
@@ -174,15 +180,15 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke
174180
shouldPersist: boolean
175181
): Promise<ITerminalChildProcess> {
176182
const executableEnv = await this._shellEnvironmentService.getShellEnv();
177-
const id = await this._localPtyService.createProcess(shellLaunchConfig, cwd, cols, rows, unicodeVersion, env, executableEnv, options, shouldPersist, this._getWorkspaceId(), this._getWorkspaceName());
183+
const id = await this._ptyHostDirectProxy!.createProcess(shellLaunchConfig, cwd, cols, rows, unicodeVersion, env, executableEnv, options, shouldPersist, this._getWorkspaceId(), this._getWorkspaceName());
178184
const pty = this._instantiationService.createInstance(LocalPty, id, shouldPersist);
179185
this._ptys.set(id, pty);
180186
return pty;
181187
}
182188

183189
async attachToProcess(id: number): Promise<ITerminalChildProcess | undefined> {
184190
try {
185-
await this._localPtyService.attachToProcess(id);
191+
await this._ptyHostDirectProxy!.attachToProcess(id);
186192
const pty = this._instantiationService.createInstance(LocalPty, id, true);
187193
this._ptys.set(id, pty);
188194
return pty;
@@ -194,7 +200,7 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke
194200

195201
async attachToRevivedProcess(id: number): Promise<ITerminalChildProcess | undefined> {
196202
try {
197-
const newId = await this._localPtyService.getRevivedPtyNewId(id) ?? id;
203+
const newId = await this._ptyHostDirectProxy!.getRevivedPtyNewId(id) ?? id;
198204
return await this.attachToProcess(newId);
199205
} catch (e) {
200206
this._logService.warn(`Couldn't attach to process ${e.message}`);
@@ -203,39 +209,40 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke
203209
}
204210

205211
async listProcesses(): Promise<IProcessDetails[]> {
206-
return this._localPtyService.listProcesses();
212+
return this._ptyHostDirectProxy!.listProcesses();
207213
}
208214

209215
async reduceConnectionGraceTime(): Promise<void> {
210-
this._localPtyService.reduceConnectionGraceTime();
216+
this._ptyHostDirectProxy!.reduceConnectionGraceTime();
211217
}
212218

213219
async getDefaultSystemShell(osOverride?: OperatingSystem): Promise<string> {
214-
return this._localPtyService.getDefaultSystemShell(osOverride);
220+
return this._ptyHostDirectProxy!.getDefaultSystemShell(osOverride);
215221
}
216222

217223
async getProfiles(profiles: unknown, defaultProfile: unknown, includeDetectedProfiles?: boolean) {
224+
// TODO: Differentiate interfaces of direct to pty host and pty host service (or just move them all to pty host)
218225
return this._localPtyService.getProfiles?.(this._workspaceContextService.getWorkspace().id, profiles, defaultProfile, includeDetectedProfiles) || [];
219226
}
220227

221228
async getEnvironment(): Promise<IProcessEnvironment> {
222-
return this._localPtyService.getEnvironment();
229+
return this._ptyHostDirectProxy!.getEnvironment();
223230
}
224231

225232
async getShellEnvironment(): Promise<IProcessEnvironment> {
226233
return this._shellEnvironmentService.getShellEnv();
227234
}
228235

229236
async getWslPath(original: string, direction: 'unix-to-win' | 'win-to-unix'): Promise<string> {
230-
return this._localPtyService.getWslPath(original, direction);
237+
return this._ptyHostDirectProxy!.getWslPath(original, direction);
231238
}
232239

233240
async setTerminalLayoutInfo(layoutInfo?: ITerminalsLayoutInfoById): Promise<void> {
234241
const args: ISetTerminalLayoutInfoArgs = {
235242
workspaceId: this._getWorkspaceId(),
236243
tabs: layoutInfo ? layoutInfo.tabs : []
237244
};
238-
await this._localPtyService.setTerminalLayoutInfo(args);
245+
await this._ptyHostDirectProxy!.setTerminalLayoutInfo(args);
239246
// Store in the storage service as well to be used when reviving processes as normally this
240247
// is stored in memory on the pty host
241248
this._storageService.store(TerminalStorageKeys.TerminalLayoutInfo, JSON.stringify(args), StorageScope.WORKSPACE, StorageTarget.MACHINE);

0 commit comments

Comments
 (0)