@@ -513,69 +513,71 @@ export class Chromedriver extends events.EventEmitter {
513
513
514
514
/**
515
515
* Sync the WebDriver protocol if current on going protocol is W3C or MJSONWP.
516
- * Does nothing if this.driverVersion was null.
516
+ * Does nothing if this.driverVersion is null.
517
+ *
518
+ * @returns {typeof PROTOCOLS[keyof typeof PROTOCOLS] }
517
519
*/
518
520
syncProtocol ( ) {
519
- if ( this . driverVersion === null ) {
521
+ if ( ! this . driverVersion ) {
520
522
// Keep the default protocol if the driverVersion was unsure.
521
- return ;
523
+ return this . desiredProtocol ;
522
524
}
523
525
526
+ this . desiredProtocol = PROTOCOLS . MJSONWP ;
524
527
const coercedVersion = semver . coerce ( this . driverVersion ) ;
525
528
if ( ! coercedVersion || coercedVersion . major < MIN_CD_VERSION_WITH_W3C_SUPPORT ) {
526
- this . log . debug (
527
- `The WebDriver v. ${ this . driverVersion } does not fully support ${ PROTOCOLS . W3C } protocol. ` +
529
+ this . log . info (
530
+ `The ChromeDriver v. ${ this . driverVersion } does not fully support ${ PROTOCOLS . W3C } protocol. ` +
528
531
`Defaulting to ${ PROTOCOLS . MJSONWP } ` ,
529
532
) ;
530
- return ;
533
+ return this . desiredProtocol ;
531
534
}
532
-
533
535
// Check only chromeOptions for now.
534
536
const chromeOptions = getCapValue ( this . capabilities , 'chromeOptions' , { } ) ;
535
537
if ( chromeOptions . w3c === false ) {
536
538
this . log . info (
537
- `The WebDriver v. ${ this . driverVersion } supports ${ PROTOCOLS . W3C } protocol, ` +
539
+ `The ChromeDriver v. ${ this . driverVersion } supports ${ PROTOCOLS . W3C } protocol, ` +
538
540
`but ${ PROTOCOLS . MJSONWP } one has been explicitly requested` ,
539
541
) ;
540
- return ;
542
+ return this . desiredProtocol ;
541
543
}
544
+
542
545
this . desiredProtocol = PROTOCOLS . W3C ;
543
- // given caps might not be properly prefixed
544
- // so we try to fix them in order to properly init
545
- // the new W3C session
546
- this . capabilities = toW3cCapNames ( this . capabilities ) ;
546
+ this . log . info ( `Set ChromeDriver communication protocol to ${ PROTOCOLS . W3C } ` ) ;
547
+ return this . desiredProtocol ;
547
548
}
548
549
549
550
/**
550
551
* Sync the protocol by reading the given output
551
552
*
552
- * @param {string } out The output of WebDriver process start
553
+ * @param {string } line The output of ChromeDriver process
554
+ * @returns {typeof PROTOCOLS[keyof typeof PROTOCOLS] | null }
553
555
*/
554
- detectWebDriverProtocol ( out ) {
556
+ detectWebDriverProtocol ( line ) {
555
557
if ( this . driverVersion ) {
556
- // Nothing is done if the protocol was already detected
557
- return ;
558
+ return this . syncProtocol ( ) ;
558
559
}
559
560
560
561
// also print chromedriver version to logs
561
562
// will output something like
562
563
// Starting ChromeDriver 2.33.506106 (8a06c39c4582fbfbab6966dbb1c38a9173bfb1a2) on port 9515
563
564
// Or MSEdge:
564
565
// Starting Microsoft Edge WebDriver 111.0.1661.41 (57be51b50d1be232a9e8186a10017d9e06b1fd16) on port 9515
565
- const match = WEBDRIVER_VERSION_PATTERN . exec ( out ) ;
566
+ const match = WEBDRIVER_VERSION_PATTERN . exec ( line ) ;
566
567
if ( match && match . length === 3 ) {
567
568
this . log . debug ( `${ match [ 1 ] } version: '${ match [ 2 ] } '` ) ;
568
569
this . driverVersion = match [ 2 ] ;
569
570
try {
570
- this . syncProtocol ( ) ;
571
+ return this . syncProtocol ( ) ;
571
572
} catch ( e ) {
572
573
this . driverVersion = null ;
573
- this . log . error ( `Failed to sync the protocol as ' ${ e } '. Stopping the driver process. ` ) ;
574
+ this . log . error ( `Stopping the chromedriver process. Cannot determinate the protocol: ${ e } ` ) ;
574
575
this . stop ( ) ;
575
576
}
576
577
// Does not print else condition log since the log could be
577
578
// very noisy when this.verbose option is true.
578
579
}
580
+ return null ;
579
581
}
580
582
581
583
/**
@@ -615,7 +617,9 @@ export class Chromedriver extends events.EventEmitter {
615
617
const startDetector = /** @param {string } stdout */ ( stdout ) => stdout . startsWith ( 'Starting ' ) ;
616
618
617
619
let processIsAlive = false ;
620
+ /** @type {string|undefined } */
618
621
let webviewVersion ;
622
+ let didDetectProtocol = false ;
619
623
try {
620
624
const chromedriverPath = await this . initChromedriverPath ( ) ;
621
625
await this . killAll ( ) ;
@@ -625,40 +629,45 @@ export class Chromedriver extends events.EventEmitter {
625
629
processIsAlive = true ;
626
630
627
631
// handle log output
628
- this . proc . on ( 'output ', ( stdout , stderr ) => {
629
- // if the cd output is not printed, find the chrome version and print
630
- // will get a response like
631
- // DevTools response: {
632
- // "Android-Package": "io.appium.sampleapp",
633
- // "Browser ": "Chrome/55.0.2883.91 ",
634
- // "Protocol-Version ": "1.2 ",
635
- // "User-Agent ": "... ",
636
- // "WebKit-Version ": "537.36"
637
- // }
638
- const out = stdout + stderr ;
639
- let match = / " B r o w s e r " : " ( . * ) " / . exec ( out ) ;
640
- if ( match ) {
641
- webviewVersion = match [ 1 ] ;
642
- this . log . debug ( `Webview version: ' ${ webviewVersion } '` ) ;
643
- }
644
-
645
- this . detectWebDriverProtocol ( out ) ;
632
+ for ( const streamName of [ 'stderr ', ' stdout' ] ) {
633
+ this . proc . on ( `line- ${ streamName } ` , ( line ) => {
634
+ // if the cd output is not printed, find the chrome version and print
635
+ // will get a response like
636
+ // DevTools response: {
637
+ // "Android-Package ": "io.appium.sampleapp ",
638
+ // "Browser ": "Chrome/55.0.2883.91 ",
639
+ // "Protocol-Version ": "1.2 ",
640
+ // "User-Agent ": "...",
641
+ // "WebKit-Version": "537.36"
642
+ // }
643
+ if ( ! webviewVersion ) {
644
+ const match = / " B r o w s e r " : " ( [ ^ " ] + ) " / . exec ( line ) ;
645
+ if ( match ) {
646
+ webviewVersion = match [ 1 ] ;
647
+ this . log . debug ( `Webview version: ' ${ webviewVersion } '` ) ;
648
+ }
649
+ }
646
650
647
- // give the output if it is requested
648
- if ( this . verbose ) {
649
- for ( let line of ( stdout || '' ) . trim ( ) . split ( '\n' ) ) {
650
- if ( ! line . trim ( ) . length ) continue ; // eslint-disable-line curly
651
- this . log . debug ( `[STDOUT] ${ line } ` ) ;
651
+ if ( ! didDetectProtocol ) {
652
+ const proto = this . detectWebDriverProtocol ( line ) ;
653
+ if ( proto === PROTOCOLS . W3C ) {
654
+ // given caps might not be properly prefixed
655
+ // so we try to fix them in order to properly init
656
+ // the new W3C session
657
+ this . capabilities = toW3cCapNames ( this . capabilities ) ;
658
+ }
659
+ didDetectProtocol = true ;
652
660
}
653
- for ( let line of ( stderr || '' ) . trim ( ) . split ( '\n' ) ) {
654
- if ( ! line . trim ( ) . length ) continue ; // eslint-disable-line curly
655
- this . log . error ( `[STDERR] ${ line } ` ) ;
661
+
662
+ if ( this . verbose ) {
663
+ // give the output if it is requested
664
+ this . log . debug ( `[${ streamName . toUpperCase ( ) } ] ${ line } ` ) ;
656
665
}
657
- }
658
- } ) ;
666
+ } ) ;
667
+ }
659
668
660
669
// handle out-of-bound exit by simply emitting a stopped state
661
- this . proc . on ( 'exit' , ( code , signal ) => {
670
+ this . proc . once ( 'exit' , ( code , signal ) => {
662
671
this . driverVersion = null ;
663
672
processIsAlive = false ;
664
673
if (
@@ -670,6 +679,8 @@ export class Chromedriver extends events.EventEmitter {
670
679
this . log . error ( msg ) ;
671
680
this . changeState ( Chromedriver . STATE_STOPPED ) ;
672
681
}
682
+ this . proc ?. removeAllListeners ( ) ;
683
+ this . proc = null ;
673
684
} ) ;
674
685
this . log . info ( `Spawning chromedriver with: ${ this . chromedriver } ${ args . join ( ' ' ) } ` ) ;
675
686
// start subproc and wait for startDetector
@@ -685,6 +696,8 @@ export class Chromedriver extends events.EventEmitter {
685
696
if ( processIsAlive ) {
686
697
await this . proc ?. stop ( ) ;
687
698
}
699
+ this . proc ?. removeAllListeners ( ) ;
700
+ this . proc = null ;
688
701
689
702
let message = '' ;
690
703
// often the user's Chrome version is not supported by the version of Chromedriver
@@ -776,7 +789,11 @@ export class Chromedriver extends events.EventEmitter {
776
789
}
777
790
} ;
778
791
await runSafeStep ( ( ) => this . jwproxy . command ( '' , 'DELETE' ) ) ;
779
- await runSafeStep ( ( ) => this . proc ?. stop ( 'SIGTERM' , 20000 ) ) ;
792
+ await runSafeStep ( ( ) => {
793
+ this . proc ?. stop ( 'SIGTERM' , 20000 ) ;
794
+ this . proc ?. removeAllListeners ( ) ;
795
+ this . proc = null ;
796
+ } ) ;
780
797
this . log . prefix = generateLogPrefix ( this ) ;
781
798
if ( emitStates ) {
782
799
this . changeState ( Chromedriver . STATE_STOPPED ) ;
0 commit comments