@@ -72,6 +72,49 @@ function doFindFreePort(startPort: number, giveUpAfter: number, clb: (port: numb
7272 client . connect ( startPort , '127.0.0.1' ) ;
7373}
7474
75+ /**
76+ * Uses listen instead of connect. Is faster, but if there is another listener on 0.0.0.0 then this will take 127.0.0.1 from that listener.
77+ */
78+ export function findFreePortFaster ( startPort : number , giveUpAfter : number , timeout : number ) : Promise < number > {
79+ let resolved : boolean = false ;
80+ let timeoutHandle : NodeJS . Timeout | undefined = undefined ;
81+ let countTried : number = 1 ;
82+ const server = net . createServer ( { pauseOnConnect : true } ) ;
83+ function doResolve ( port : number , resolve : ( port : number ) => void ) {
84+ if ( ! resolved ) {
85+ resolved = true ;
86+ server . removeAllListeners ( ) ;
87+ server . close ( ) ;
88+ if ( timeoutHandle ) {
89+ clearTimeout ( timeoutHandle ) ;
90+ }
91+ resolve ( port ) ;
92+ }
93+ }
94+ return new Promise < number > ( resolve => {
95+ timeoutHandle = setTimeout ( ( ) => {
96+ doResolve ( 0 , resolve ) ;
97+ } , timeout ) ;
98+
99+ server . on ( 'listening' , ( ) => {
100+ doResolve ( startPort , resolve ) ;
101+ } ) ;
102+ server . on ( 'error' , err => {
103+ if ( err && ( ( < any > err ) . code === 'EADDRINUSE' || ( < any > err ) . code === 'EACCES' ) && ( countTried < giveUpAfter ) ) {
104+ startPort ++ ;
105+ countTried ++ ;
106+ server . listen ( startPort , '127.0.0.1' ) ;
107+ } else {
108+ doResolve ( 0 , resolve ) ;
109+ }
110+ } ) ;
111+ server . on ( 'close' , ( ) => {
112+ doResolve ( 0 , resolve ) ;
113+ } ) ;
114+ server . listen ( startPort , '127.0.0.1' ) ;
115+ } ) ;
116+ }
117+
75118function dispose ( socket : net . Socket ) : void {
76119 try {
77120 socket . removeAllListeners ( 'connect' ) ;
0 commit comments