@@ -20,7 +20,8 @@ import * as browserPaths from '../install/browserPaths';
20
20
import { Logger , RootLogger } from '../logger' ;
21
21
import { ConnectionTransport , WebSocketTransport } from '../transport' ;
22
22
import { BrowserBase , BrowserOptions , Browser } from '../browser' ;
23
- import { assert } from '../helper' ;
23
+ import { assert , helper } from '../helper' ;
24
+ import { TimeoutSettings } from '../timeoutSettings' ;
24
25
25
26
export type BrowserArgOptions = {
26
27
headless ?: boolean ,
@@ -48,6 +49,7 @@ export type ConnectOptions = {
48
49
wsEndpoint : string ,
49
50
slowMo ?: number ,
50
51
logger ?: Logger ,
52
+ timeout ?: number ,
51
53
} ;
52
54
export type LaunchType = 'local' | 'server' | 'persistent' ;
53
55
export type LaunchOptions = LaunchOptionsBase & { slowMo ?: number } ;
@@ -86,42 +88,88 @@ export abstract class BrowserTypeBase implements BrowserType {
86
88
87
89
async launch ( options : LaunchOptions = { } ) : Promise < Browser > {
88
90
assert ( ! ( options as any ) . userDataDir , 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead' ) ;
89
- const browserServer = new BrowserServer ( options ) ;
90
- const { transport, downloadsPath } = await this . _launchServer ( options , 'local' , browserServer ) ;
91
- return await browserServer . _initializeOrClose ( async ( ) => {
92
- return this . _connectToServer ( browserServer , false , transport ! , downloadsPath ) ;
93
- } ) ;
91
+ return this . _innerLaunch ( 'local' , options ) ;
94
92
}
95
93
96
94
async launchPersistentContext ( userDataDir : string , options : LaunchOptions = { } ) : Promise < BrowserContext > {
97
- const browserServer = new BrowserServer ( options ) ;
98
- const { transport, downloadsPath } = await this . _launchServer ( options , 'persistent' , browserServer , userDataDir ) ;
95
+ const browser = await this . _innerLaunch ( 'persistent' , options , userDataDir ) ;
96
+ return browser . _defaultContext ! ;
97
+ }
98
+
99
+ async _innerLaunch ( launchType : LaunchType , options : LaunchOptions , userDataDir ?: string ) : Promise < BrowserBase > {
100
+ const deadline = TimeoutSettings . computeDeadline ( options . timeout , 30000 ) ;
101
+ const logger = new RootLogger ( options . logger ) ;
102
+ logger . startLaunchRecording ( ) ;
103
+
104
+ let browserServer : BrowserServer | undefined ;
105
+ try {
106
+ browserServer = await this . _launchServer ( options , launchType , logger , deadline , userDataDir ) ;
107
+ const promise = this . _innerLaunchPromise ( browserServer , launchType , options ) ;
108
+ const browser = await helper . waitWithDeadline ( promise , 'the browser to launch' , deadline , 'pw:browser*' ) ;
109
+ return browser ;
110
+ } catch ( e ) {
111
+ e . message += '\n=============== Process output during launch: ===============\n' +
112
+ logger . launchRecording ( ) +
113
+ '\n=============================================================' ;
114
+ if ( browserServer )
115
+ await browserServer . _closeOrKill ( deadline ) ;
116
+ throw e ;
117
+ } finally {
118
+ logger . stopLaunchRecording ( ) ;
119
+ }
120
+ }
99
121
100
- return await browserServer . _initializeOrClose ( async ( ) => {
101
- const browser = await this . _connectToServer ( browserServer , true , transport ! , downloadsPath ) ;
122
+ async _innerLaunchPromise ( browserServer : BrowserServer , launchType : LaunchType , options : LaunchOptions ) : Promise < BrowserBase > {
123
+ if ( ( options as any ) . __testHookBeforeCreateBrowser )
124
+ await ( options as any ) . __testHookBeforeCreateBrowser ( ) ;
125
+
126
+ const browser = await this . _connectToServer ( browserServer , launchType === 'persistent' ) ;
127
+ if ( launchType === 'persistent' && ( ! options . ignoreDefaultArgs || Array . isArray ( options . ignoreDefaultArgs ) ) ) {
102
128
const context = browser . _defaultContext ! ;
103
- if ( ! options . ignoreDefaultArgs || Array . isArray ( options . ignoreDefaultArgs ) )
104
- await context . _loadDefaultContext ( ) ;
105
- return context ;
106
- } ) ;
129
+ await context . _loadDefaultContext ( ) ;
130
+ }
131
+ return browser ;
107
132
}
108
133
109
134
async launchServer ( options : LaunchServerOptions = { } ) : Promise < BrowserServer > {
110
- const browserServer = new BrowserServer ( options ) ;
111
- await this . _launchServer ( options , 'server' , browserServer ) ;
112
- return browserServer ;
135
+ const logger = new RootLogger ( options . logger ) ;
136
+ return this . _launchServer ( options , 'server' , logger , TimeoutSettings . computeDeadline ( options . timeout , 30000 ) ) ;
113
137
}
114
138
115
139
async connect ( options : ConnectOptions ) : Promise < Browser > {
140
+ const deadline = TimeoutSettings . computeDeadline ( options . timeout , 30000 ) ;
116
141
const logger = new RootLogger ( options . logger ) ;
117
- return await WebSocketTransport . connect ( options . wsEndpoint , async transport => {
118
- if ( ( options as any ) . __testHookBeforeCreateBrowser )
119
- await ( options as any ) . __testHookBeforeCreateBrowser ( ) ;
120
- return this . _connectToTransport ( transport , { slowMo : options . slowMo , logger, downloadsPath : '' } ) ;
121
- } , logger ) ;
142
+ logger . startLaunchRecording ( ) ;
143
+
144
+ let transport : ConnectionTransport | undefined ;
145
+ try {
146
+ transport = await WebSocketTransport . connect ( options . wsEndpoint , logger , deadline ) ;
147
+ const promise = this . _innerConnectPromise ( transport , options , logger ) ;
148
+ const browser = await helper . waitWithDeadline ( promise , 'connect to browser' , deadline , 'pw:browser*' ) ;
149
+ logger . stopLaunchRecording ( ) ;
150
+ return browser ;
151
+ } catch ( e ) {
152
+ e . message += '\n=============== Process output during connect: ===============\n' +
153
+ logger . launchRecording ( ) +
154
+ '\n=============================================================' ;
155
+ try {
156
+ if ( transport )
157
+ transport . close ( ) ;
158
+ } catch ( e ) {
159
+ }
160
+ throw e ;
161
+ } finally {
162
+ logger . stopLaunchRecording ( ) ;
163
+ }
164
+ }
165
+
166
+ async _innerConnectPromise ( transport : ConnectionTransport , options : ConnectOptions , logger : RootLogger ) : Promise < Browser > {
167
+ if ( ( options as any ) . __testHookBeforeCreateBrowser )
168
+ await ( options as any ) . __testHookBeforeCreateBrowser ( ) ;
169
+ return this . _connectToTransport ( transport , { slowMo : options . slowMo , logger, downloadsPath : '' } ) ;
122
170
}
123
171
124
- abstract _launchServer ( options : LaunchServerOptions , launchType : LaunchType , browserServer : BrowserServer , userDataDir ?: string ) : Promise < { transport ?: ConnectionTransport , downloadsPath : string } > ;
125
- abstract _connectToServer ( browserServer : BrowserServer , persistent : boolean , transport : ConnectionTransport , downloadsPath : string ) : Promise < BrowserBase > ;
172
+ abstract _launchServer ( options : LaunchServerOptions , launchType : LaunchType , logger : RootLogger , deadline : number , userDataDir ?: string ) : Promise < BrowserServer > ;
173
+ abstract _connectToServer ( browserServer : BrowserServer , persistent : boolean ) : Promise < BrowserBase > ;
126
174
abstract _connectToTransport ( transport : ConnectionTransport , options : BrowserOptions ) : Promise < BrowserBase > ;
127
175
}
0 commit comments