@@ -8,12 +8,16 @@ import {
88 request ,
99 Response
1010} from '@theintern/common' ;
11- import { spawn , ChildProcess } from 'child_process' ;
11+ import { ChildProcess } from 'child_process' ;
1212import { join } from 'path' ;
1313import { format as formatUrl , Url } from 'url' ;
14- import { fileExists , kill , on } from './lib/util' ;
14+ import { fileExists , on } from './lib/util' ;
1515import { JobState } from './interfaces' ;
1616import * as decompress from 'decompress' ;
17+ import {
18+ makeChildWithCommand ,
19+ stopChildProcess
20+ } from './lib/tunnelChildProcesses' ;
1721
1822/**
1923 * A Tunnel is a mechanism for connecting to a WebDriver service provider that
@@ -121,6 +125,12 @@ export default class Tunnel extends Evented<TunnelEvents, string>
121125 /** Whether or not to tell the tunnel to provide verbose logging output. */
122126 verbose ! : boolean ;
123127
128+ /**
129+ * The directory in which the tunnel implementations will download
130+ * any necessary applications.
131+ */
132+ basePath : string = __dirname ;
133+
124134 protected _startTask : CancellablePromise < any > | undefined ;
125135 protected _stopTask : Promise < number | void > | undefined ;
126136 protected _handle : Handle | undefined ;
@@ -259,8 +269,8 @@ export default class Tunnel extends Evented<TunnelEvents, string>
259269 /**
260270 * Sends information about a job to the tunnel provider.
261271 *
262- * @param jobId The job to send data about. This is usually a session ID.
263- * @param data Data to send to the tunnel provider about the job.
272+ * @param _jobId The job to send data about. This is usually a session ID.
273+ * @param _data Data to send to the tunnel provider about the job.
264274 * @returns A promise that resolves once the job state request is complete.
265275 */
266276 sendJobState ( _jobId : string , _data : JobState ) : CancellablePromise < void > {
@@ -446,89 +456,12 @@ export default class Tunnel extends Evented<TunnelEvents, string>
446456 executor : ChildExecutor ,
447457 ...values : string [ ]
448458 ) : CancellablePromise {
449- const command = this . executable ;
450- const args = this . _makeArgs ( ...values ) ;
451- const options = this . _makeOptions ( ...values ) ;
452- const child = spawn ( command , args , options ) ;
453-
454- child . stdout . setEncoding ( 'utf8' ) ;
455- child . stderr . setEncoding ( 'utf8' ) ;
456-
457- let handle : Handle ;
458- let canceled = false ;
459-
460- // Ensure child process is killed when parent exits
461- process . on ( 'exit' , ( ) => kill ( child . pid ) ) ;
462- process . on ( 'SIGINT' , ( ) => kill ( child . pid ) ) ;
463-
464- const task = new Task (
465- ( resolve , reject ) => {
466- let errorMessage = '' ;
467- let exitCode : number | undefined ;
468- let stderrClosed = false ;
469- let exitted = false ;
470-
471- function handleChildExit ( ) {
472- reject (
473- new Error (
474- `Tunnel failed to start: ${ errorMessage ||
475- `Exit code: ${ exitCode } ` } `
476- )
477- ) ;
478- }
479-
480- handle = createCompositeHandle (
481- on ( child , 'error' , reject ) ,
482-
483- on ( child . stderr , 'data' , ( data : string ) => {
484- errorMessage += data ;
485- } ) ,
486-
487- on ( child , 'exit' , ( ) => {
488- exitted = true ;
489- if ( stderrClosed ) {
490- handleChildExit ( ) ;
491- }
492- } ) ,
493-
494- // stderr might still have data in buffer at the time the
495- // exit event is sent, so we have to store data from stderr
496- // and the exit code and reject only once stderr closes
497- on ( child . stderr , 'close' , ( ) => {
498- stderrClosed = true ;
499- if ( exitted ) {
500- handleChildExit ( ) ;
501- }
502- } )
503- ) ;
504-
505- const result = executor ( child , resolve , reject ) ;
506- if ( result ) {
507- handle = createCompositeHandle ( handle , result ) ;
508- }
509- } ,
510- ( ) => {
511- canceled = true ;
512-
513- // Make a best effort to kill the process, but don't throw
514- // exceptions
515- try {
516- kill ( child . pid ) ;
517- } catch ( error ) { }
518- }
459+ return makeChildWithCommand (
460+ this . executable ,
461+ executor ,
462+ this . _makeArgs ( ...values ) ,
463+ this . _makeOptions ( ...values )
519464 ) ;
520-
521- return task . finally ( ( ) => {
522- handle . destroy ( ) ;
523- if ( canceled ) {
524- // We only want this to run when cancelation has occurred
525- return new Promise ( resolve => {
526- child . once ( 'exit' , ( ) => {
527- resolve ( ) ;
528- } ) ;
529- } ) ;
530- }
531- } ) ;
532465 }
533466
534467 /**
@@ -620,21 +553,7 @@ export default class Tunnel extends Evented<TunnelEvents, string>
620553 */
621554 protected _stop ( ) {
622555 return new Promise < number | void > ( ( resolve , reject ) => {
623- const childProcess = this . _process ;
624- if ( ! childProcess ) {
625- resolve ( ) ;
626- return ;
627- }
628-
629- childProcess . once ( 'exit' , code => {
630- resolve ( code == null ? undefined : code ) ;
631- } ) ;
632-
633- try {
634- kill ( childProcess . pid ) ;
635- } catch ( error ) {
636- reject ( error ) ;
637- }
556+ stopChildProcess ( this . _process , resolve , reject ) ;
638557 } ) ;
639558 }
640559}
@@ -768,6 +687,9 @@ export interface TunnelProperties extends DownloadProperties {
768687
769688 /** [[Tunnel.Tunnel.verbose|More info]] */
770689 verbose : boolean ;
690+
691+ /** [[Tunnel.Tunnel.basePath|More info]] */
692+ basePath : string | undefined ;
771693}
772694
773695export type TunnelOptions = Partial < TunnelProperties > ;
0 commit comments