@@ -39,24 +39,34 @@ import { mark } from 'vs/base/common/performance';
3939export class LocalTerminalBackendContribution implements IWorkbenchContribution {
4040 constructor (
4141 @IInstantiationService instantiationService : IInstantiationService ,
42+ @ILogService logService : ILogService ,
4243 @ITerminalInstanceService terminalInstanceService : ITerminalInstanceService
4344 ) {
44- const backend = instantiationService . createInstance ( LocalTerminalBackend , undefined ) ;
45- Registry . as < ITerminalBackendRegistry > ( TerminalExtensions . Backend ) . registerTerminalBackend ( backend ) ;
46- terminalInstanceService . didRegisterBackend ( backend . remoteAuthority ) ;
45+ mark ( 'code/willConnectPtyHost' ) ;
46+ logService . trace ( 'Renderer->PtyHost#connect: before acquirePort' ) ;
47+ acquirePort ( 'vscode:createPtyHostMessageChannel' , 'vscode:createPtyHostMessageChannelResult' ) . then ( port => {
48+ mark ( 'code/didConnectPtyHost' ) ;
49+ logService . trace ( 'Renderer->PtyHost#connect: connection established' ) ;
50+
51+ const backend = instantiationService . createInstance ( LocalTerminalBackend , port ) ;
52+ Registry . as < ITerminalBackendRegistry > ( TerminalExtensions . Backend ) . registerTerminalBackend ( backend ) ;
53+ terminalInstanceService . didRegisterBackend ( backend . remoteAuthority ) ;
54+ } ) ;
4755 }
4856}
4957
5058class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBackend {
59+ readonly remoteAuthority = undefined ;
60+
5161 private readonly _ptys : Map < number , LocalPty > = new Map ( ) ;
5262
53- private _ptyHostDirectProxy : IPtyService | undefined ;
63+ private _ptyHostDirectProxy : IPtyService ;
5464
5565 private readonly _onDidRequestDetach = this . _register ( new Emitter < { requestId : number ; workspaceId : string ; instanceId : number } > ( ) ) ;
5666 readonly onDidRequestDetach = this . _onDidRequestDetach . event ;
5767
5868 constructor (
59- readonly remoteAuthority : string | undefined ,
69+ port : MessagePort ,
6070 @IInstantiationService private readonly _instantiationService : IInstantiationService ,
6171 @IWorkspaceContextService workspaceContextService : IWorkspaceContextService ,
6272 @ILogService logService : ILogService ,
@@ -76,90 +86,81 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke
7686 ) {
7787 super ( _localPtyService , logService , notificationService , historyService , _configurationResolverService , workspaceContextService ) ;
7888
79- // TODO: If we connect async like this, there may be a race condition where messages go missing before the message port is established
80- this . _start ( ) ;
81- }
82-
83- private async _start ( ) {
84-
85- // TODO: Use the direct connection
86- mark ( 'code/willConnectPtyHost' ) ;
87- this . _logService . trace ( 'Renderer->PtyHost#connect: before acquirePort' ) ;
88- const port = await acquirePort ( 'vscode:createPtyHostMessageChannel' , 'vscode:createPtyHostMessageChannelResult' ) ;
89- mark ( 'code/didConnectPtyHost' ) ;
90- this . _logService . trace ( 'Renderer->PtyHost#connect: connection established' ) ;
91-
89+ // There are two connections to the pty host; one to the regular shared process
90+ // _localPtyService, and one directly via message port _ptyHostDirectProxy. The former is
91+ // used for pty host management messages, it would make sense in the future to use a
92+ // separate interface/service for this one.
9293 const client = new MessagePortClient ( port , `window:${ this . _environmentService . window . id } ` ) ;
9394 this . _ptyHostDirectProxy = ProxyChannel . toService < IPtyService > ( client . getChannel ( TerminalIpcChannels . PtyHostWindow ) ) ;
9495
9596 // Attach process listeners
96- this . _ptyHostDirectProxy ! . onProcessData ( e => this . _ptys . get ( e . id ) ?. handleData ( e . event ) ) ;
97- this . _ptyHostDirectProxy ! . onDidChangeProperty ( e => this . _ptys . get ( e . id ) ?. handleDidChangeProperty ( e . property ) ) ;
98- this . _ptyHostDirectProxy ! . onProcessExit ( e => {
97+ this . _ptyHostDirectProxy . onProcessData ( e => this . _ptys . get ( e . id ) ?. handleData ( e . event ) ) ;
98+ this . _ptyHostDirectProxy . onDidChangeProperty ( e => this . _ptys . get ( e . id ) ?. handleDidChangeProperty ( e . property ) ) ;
99+ this . _ptyHostDirectProxy . onProcessExit ( e => {
99100 const pty = this . _ptys . get ( e . id ) ;
100101 if ( pty ) {
101102 pty . handleExit ( e . event ) ;
102103 this . _ptys . delete ( e . id ) ;
103104 }
104105 } ) ;
105- this . _ptyHostDirectProxy ! . onProcessReady ( e => this . _ptys . get ( e . id ) ?. handleReady ( e . event ) ) ;
106- this . _ptyHostDirectProxy ! . onProcessReplay ( e => this . _ptys . get ( e . id ) ?. handleReplay ( e . event ) ) ;
107- this . _ptyHostDirectProxy ! . onProcessOrphanQuestion ( e => this . _ptys . get ( e . id ) ?. handleOrphanQuestion ( ) ) ;
108- this . _ptyHostDirectProxy ! . onDidRequestDetach ( e => this . _onDidRequestDetach . fire ( e ) ) ;
106+ this . _ptyHostDirectProxy . onProcessReady ( e => this . _ptys . get ( e . id ) ?. handleReady ( e . event ) ) ;
107+ this . _ptyHostDirectProxy . onProcessReplay ( e => this . _ptys . get ( e . id ) ?. handleReplay ( e . event ) ) ;
108+ this . _ptyHostDirectProxy . onProcessOrphanQuestion ( e => this . _ptys . get ( e . id ) ?. handleOrphanQuestion ( ) ) ;
109+ this . _ptyHostDirectProxy . onDidRequestDetach ( e => this . _onDidRequestDetach . fire ( e ) ) ;
109110
110111 // Listen for config changes
111112 const initialConfig = this . _configurationService . getValue < ITerminalConfiguration > ( TERMINAL_CONFIG_SECTION ) ;
112113 for ( const match of Object . keys ( initialConfig . autoReplies ) ) {
113114 // Ensure the reply is value
114115 const reply = initialConfig . autoReplies [ match ] as string | null ;
115116 if ( reply ) {
116- this . _ptyHostDirectProxy ! . installAutoReply ( match , reply ) ;
117+ this . _ptyHostDirectProxy . installAutoReply ( match , reply ) ;
117118 }
118119 }
119120 // TODO: Could simplify update to a single call
120121 this . _register ( this . _configurationService . onDidChangeConfiguration ( async e => {
121122 if ( e . affectsConfiguration ( TerminalSettingId . AutoReplies ) ) {
122- this . _ptyHostDirectProxy ! . uninstallAllAutoReplies ( ) ;
123+ this . _ptyHostDirectProxy . uninstallAllAutoReplies ( ) ;
123124 const config = this . _configurationService . getValue < ITerminalConfiguration > ( TERMINAL_CONFIG_SECTION ) ;
124125 for ( const match of Object . keys ( config . autoReplies ) ) {
125126 // Ensure the reply is value
126127 const reply = config . autoReplies [ match ] as string | null ;
127128 if ( reply ) {
128- await this . _ptyHostDirectProxy ! . installAutoReply ( match , reply ) ;
129+ await this . _ptyHostDirectProxy . installAutoReply ( match , reply ) ;
129130 }
130131 }
131132 }
132133 } ) ) ;
133134 }
134135
135136 async requestDetachInstance ( workspaceId : string , instanceId : number ) : Promise < IProcessDetails | undefined > {
136- return this . _ptyHostDirectProxy ! . requestDetachInstance ( workspaceId , instanceId ) ;
137+ return this . _ptyHostDirectProxy . requestDetachInstance ( workspaceId , instanceId ) ;
137138 }
138139
139140 async acceptDetachInstanceReply ( requestId : number , persistentProcessId ?: number ) : Promise < void > {
140141 if ( ! persistentProcessId ) {
141142 this . _logService . warn ( 'Cannot attach to feature terminals, custom pty terminals, or those without a persistentProcessId' ) ;
142143 return ;
143144 }
144- return this . _ptyHostDirectProxy ! . acceptDetachInstanceReply ( requestId , persistentProcessId ) ;
145+ return this . _ptyHostDirectProxy . acceptDetachInstanceReply ( requestId , persistentProcessId ) ;
145146 }
146147
147148 async persistTerminalState ( ) : Promise < void > {
148149 const ids = Array . from ( this . _ptys . keys ( ) ) ;
149- const serialized = await this . _ptyHostDirectProxy ! . serializeTerminalState ( ids ) ;
150+ const serialized = await this . _ptyHostDirectProxy . serializeTerminalState ( ids ) ;
150151 this . _storageService . store ( TerminalStorageKeys . TerminalBufferState , serialized , StorageScope . WORKSPACE , StorageTarget . MACHINE ) ;
151152 }
152153
153154 async updateTitle ( id : number , title : string , titleSource : TitleEventSource ) : Promise < void > {
154- await this . _ptyHostDirectProxy ! . updateTitle ( id , title , titleSource ) ;
155+ await this . _ptyHostDirectProxy . updateTitle ( id , title , titleSource ) ;
155156 }
156157
157158 async updateIcon ( id : number , userInitiated : boolean , icon : URI | { light : URI ; dark : URI } | { id : string ; color ?: { id : string } } , color ?: string ) : Promise < void > {
158- await this . _ptyHostDirectProxy ! . updateIcon ( id , userInitiated , icon , color ) ;
159+ await this . _ptyHostDirectProxy . updateIcon ( id , userInitiated , icon , color ) ;
159160 }
160161
161162 updateProperty < T extends ProcessPropertyType > ( id : number , property : ProcessPropertyType , value : IProcessPropertyMap [ T ] ) : Promise < void > {
162- return this . _ptyHostDirectProxy ! . updateProperty ( id , property , value ) ;
163+ return this . _ptyHostDirectProxy . updateProperty ( id , property , value ) ;
163164 }
164165
165166 async createProcess (
@@ -173,15 +174,15 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke
173174 shouldPersist : boolean
174175 ) : Promise < ITerminalChildProcess > {
175176 const executableEnv = await this . _shellEnvironmentService . getShellEnv ( ) ;
176- const id = await this . _ptyHostDirectProxy ! . createProcess ( shellLaunchConfig , cwd , cols , rows , unicodeVersion , env , executableEnv , options , shouldPersist , this . _getWorkspaceId ( ) , this . _getWorkspaceName ( ) ) ;
177+ const id = await this . _ptyHostDirectProxy . createProcess ( shellLaunchConfig , cwd , cols , rows , unicodeVersion , env , executableEnv , options , shouldPersist , this . _getWorkspaceId ( ) , this . _getWorkspaceName ( ) ) ;
177178 const pty = this . _instantiationService . createInstance ( LocalPty , id , shouldPersist ) ;
178179 this . _ptys . set ( id , pty ) ;
179180 return pty ;
180181 }
181182
182183 async attachToProcess ( id : number ) : Promise < ITerminalChildProcess | undefined > {
183184 try {
184- await this . _ptyHostDirectProxy ! . attachToProcess ( id ) ;
185+ await this . _ptyHostDirectProxy . attachToProcess ( id ) ;
185186 const pty = this . _instantiationService . createInstance ( LocalPty , id , true ) ;
186187 this . _ptys . set ( id , pty ) ;
187188 return pty ;
@@ -193,7 +194,7 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke
193194
194195 async attachToRevivedProcess ( id : number ) : Promise < ITerminalChildProcess | undefined > {
195196 try {
196- const newId = await this . _ptyHostDirectProxy ! . getRevivedPtyNewId ( id ) ?? id ;
197+ const newId = await this . _ptyHostDirectProxy . getRevivedPtyNewId ( id ) ?? id ;
197198 return await this . attachToProcess ( newId ) ;
198199 } catch ( e ) {
199200 this . _logService . warn ( `Couldn't attach to process ${ e . message } ` ) ;
@@ -202,15 +203,15 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke
202203 }
203204
204205 async listProcesses ( ) : Promise < IProcessDetails [ ] > {
205- return this . _ptyHostDirectProxy ! . listProcesses ( ) ;
206+ return this . _ptyHostDirectProxy . listProcesses ( ) ;
206207 }
207208
208209 async reduceConnectionGraceTime ( ) : Promise < void > {
209- this . _ptyHostDirectProxy ! . reduceConnectionGraceTime ( ) ;
210+ this . _ptyHostDirectProxy . reduceConnectionGraceTime ( ) ;
210211 }
211212
212213 async getDefaultSystemShell ( osOverride ?: OperatingSystem ) : Promise < string > {
213- return this . _ptyHostDirectProxy ! . getDefaultSystemShell ( osOverride ) ;
214+ return this . _ptyHostDirectProxy . getDefaultSystemShell ( osOverride ) ;
214215 }
215216
216217 async getProfiles ( profiles : unknown , defaultProfile : unknown , includeDetectedProfiles ?: boolean ) {
@@ -219,23 +220,23 @@ class LocalTerminalBackend extends BaseTerminalBackend implements ITerminalBacke
219220 }
220221
221222 async getEnvironment ( ) : Promise < IProcessEnvironment > {
222- return this . _ptyHostDirectProxy ! . getEnvironment ( ) ;
223+ return this . _ptyHostDirectProxy . getEnvironment ( ) ;
223224 }
224225
225226 async getShellEnvironment ( ) : Promise < IProcessEnvironment > {
226227 return this . _shellEnvironmentService . getShellEnv ( ) ;
227228 }
228229
229230 async getWslPath ( original : string , direction : 'unix-to-win' | 'win-to-unix' ) : Promise < string > {
230- return this . _ptyHostDirectProxy ! . getWslPath ( original , direction ) ;
231+ return this . _ptyHostDirectProxy . getWslPath ( original , direction ) ;
231232 }
232233
233234 async setTerminalLayoutInfo ( layoutInfo ?: ITerminalsLayoutInfoById ) : Promise < void > {
234235 const args : ISetTerminalLayoutInfoArgs = {
235236 workspaceId : this . _getWorkspaceId ( ) ,
236237 tabs : layoutInfo ? layoutInfo . tabs : [ ]
237238 } ;
238- await this . _ptyHostDirectProxy ! . setTerminalLayoutInfo ( args ) ;
239+ await this . _ptyHostDirectProxy . setTerminalLayoutInfo ( args ) ;
239240 // Store in the storage service as well to be used when reviving processes as normally this
240241 // is stored in memory on the pty host
241242 this . _storageService . store ( TerminalStorageKeys . TerminalLayoutInfo , JSON . stringify ( args ) , StorageScope . WORKSPACE , StorageTarget . MACHINE ) ;
0 commit comments