@@ -117,40 +117,26 @@ export class CodeServer {
117117   * directories. 
118118   */ 
119119  private  async  spawn ( ) : Promise < CodeServerProcess >  { 
120-     // This will be used both as the workspace and data directory to ensure 
121-     // instances don't bleed into each other. 
122120    const  dir  =  await  this . createWorkspace ( ) 
123- 
121+     const  args  =  await  this . argsWithDefaults ( [ 
122+       "--auth" , 
123+       "none" , 
124+       // The workspace to open. 
125+       ...( this . args . includes ( "--ignore-last-opened" )  ? [ ]  : [ dir ] ) , 
126+       ...this . args , 
127+       // Using port zero will spawn on a random port. 
128+       "--bind-addr" , 
129+       "127.0.0.1:0" , 
130+     ] ) 
124131    return  new  Promise ( ( resolve ,  reject )  =>  { 
125-       const  args  =  [ 
126-         this . entry , 
127-         "--extensions-dir" , 
128-         path . join ( dir ,  "extensions" ) , 
129-         "--auth" , 
130-         "none" , 
131-         // The workspace to open. 
132-         ...( this . args . includes ( "--ignore-last-opened" )  ? [ ]  : [ dir ] ) , 
133-         ...this . args , 
134-         // Using port zero will spawn on a random port. 
135-         "--bind-addr" , 
136-         "127.0.0.1:0" , 
137-         // Setting the XDG variables would be easier and more thorough but the 
138-         // modules we import ignores those variables for non-Linux operating 
139-         // systems so use these flags instead. 
140-         "--config" , 
141-         path . join ( dir ,  "config.yaml" ) , 
142-         "--user-data-dir" , 
143-         dir , 
144-       ] 
145132      this . logger . debug ( "spawning `node "  +  args . join ( " " )  +  "`" ) 
146133      const  proc  =  cp . spawn ( "node" ,  args ,  { 
147134        cwd : path . join ( __dirname ,  "../../.." ) , 
148135        env : { 
149136          ...process . env , 
150137          ...this . env , 
151-           // Set to empty string to prevent code-server from 
152-           // using the existing instance when running the e2e tests 
153-           // from an integrated terminal. 
138+           // Prevent code-server from using the existing instance when running 
139+           // the e2e tests from an integrated terminal. 
154140          VSCODE_IPC_HOOK_CLI : "" , 
155141          PASSWORD , 
156142        } , 
@@ -173,11 +159,15 @@ export class CodeServer {
173159        reject ( error ) 
174160      } ) 
175161
162+       // Tracks when the HTTP and session servers are ready. 
163+       let  httpAddress : string  |  undefined 
164+       let  sessionAddress : string  |  undefined 
165+ 
176166      let  resolved  =  false 
177167      proc . stdout . setEncoding ( "utf8" ) 
178168      onLine ( proc ,  ( line )  =>  { 
179169        // As long as we are actively getting input reset the timer.  If we stop 
180-         // getting input and still have not found the address  the timer will 
170+         // getting input and still have not found the addresses  the timer will 
181171        // reject. 
182172        timer . reset ( ) 
183173
@@ -186,20 +176,69 @@ export class CodeServer {
186176        if  ( resolved )  { 
187177          return 
188178        } 
189-         const  match  =  line . trim ( ) . match ( / H T T P S ?   s e r v e r   l i s t e n i n g   o n   ( h t t p s ? : \/ \/ [ . : \d ] + ) \/ ? $ / ) 
179+ 
180+         let  match  =  line . trim ( ) . match ( / H T T P S ?   s e r v e r   l i s t e n i n g   o n   ( h t t p s ? : \/ \/ [ . : \d ] + ) \/ ? $ / ) 
190181        if  ( match )  { 
191-           // Cookies don't seem to work on IP address  so swap to localhost. 
182+           // Cookies don't seem to work on IP addresses  so swap to localhost. 
192183          // TODO: Investigate whether this is a bug with code-server. 
193-           const  address  =  match [ 1 ] . replace ( "127.0.0.1" ,  "localhost" ) 
194-           this . logger . debug ( `spawned on ${ address }  ` ) 
184+           httpAddress  =  match [ 1 ] . replace ( "127.0.0.1" ,  "localhost" ) 
185+         } 
186+ 
187+         match  =  line . trim ( ) . match ( / S e s s i o n   s e r v e r   l i s t e n i n g   o n   ( .+ ) $ / ) 
188+         if  ( match )  { 
189+           sessionAddress  =  match [ 1 ] 
190+         } 
191+ 
192+         if  ( typeof  httpAddress  !==  "undefined"  &&  typeof  sessionAddress  !==  "undefined" )  { 
195193          resolved  =  true 
196194          timer . dispose ( ) 
197-           resolve ( {  process : proc ,  address } ) 
195+           this . logger . debug ( `code-server is ready: ${ httpAddress }   ${ sessionAddress }  ` ) 
196+           resolve ( {  process : proc ,  address : httpAddress  } ) 
198197        } 
199198      } ) 
200199    } ) 
201200  } 
202201
202+   /** 
203+    * Execute a short-lived command. 
204+    */ 
205+   async  run ( args : string [ ] ) : Promise < void >  { 
206+     args  =  await  this . argsWithDefaults ( args ) 
207+     this . logger . debug ( "executing `node "  +  args . join ( " " )  +  "`" ) 
208+     await  util . promisify ( cp . exec ) ( "node "  +  args . join ( " " ) ,  { 
209+       cwd : path . join ( __dirname ,  "../../.." ) , 
210+       env : { 
211+         ...process . env , 
212+         ...this . env , 
213+         // Prevent code-server from using the existing instance when running 
214+         // the e2e tests from an integrated terminal. 
215+         VSCODE_IPC_HOOK_CLI : "" , 
216+       } , 
217+     } ) 
218+   } 
219+ 
220+   /** 
221+    * Combine arguments with defaults. 
222+    */ 
223+   private  async  argsWithDefaults ( args : string [ ] ) : Promise < string [ ] >  { 
224+     // This will be used both as the workspace and data directory to ensure 
225+     // instances don't bleed into each other. 
226+     const  dir  =  await  this . workspaceDir 
227+     return  [ 
228+       this . entry , 
229+       "--extensions-dir" , 
230+       path . join ( dir ,  "extensions" ) , 
231+       ...args , 
232+       // Setting the XDG variables would be easier and more thorough but the 
233+       // modules we import ignores those variables for non-Linux operating 
234+       // systems so use these flags instead. 
235+       "--config" , 
236+       path . join ( dir ,  "config.yaml" ) , 
237+       "--user-data-dir" , 
238+       dir , 
239+     ] 
240+   } 
241+ 
203242  /** 
204243   * Close the code-server process. 
205244   */ 
@@ -364,6 +403,13 @@ export class CodeServerPage {
364403    await  this . waitForTab ( file ) 
365404  } 
366405
406+   /** 
407+    * Open a file through an external command. 
408+    */ 
409+   async  openFileExternally ( file : string )  { 
410+     await  this . codeServer . run ( [ "--reuse-window" ,  file ] ) 
411+   } 
412+ 
367413  /** 
368414   * Wait for a tab to open for the specified file. 
369415   */ 
0 commit comments