@@ -24,13 +24,11 @@ import * as browserPaths from '../install/browserPaths';
24
24
import { Logger , RootLogger , InnerLogger } from '../logger' ;
25
25
import { ConnectionTransport , WebSocketTransport } from '../transport' ;
26
26
import { BrowserBase , BrowserOptions , Browser } from '../browser' ;
27
- import { assert , helper } from '../helper' ;
28
- import { TimeoutSettings } from '../timeoutSettings' ;
27
+ import { assert } from '../helper' ;
29
28
import { launchProcess , Env , waitForLine } from './processLauncher' ;
30
29
import { Events } from '../events' ;
31
- import { rewriteErrorMessage } from '../debug/stackTrace' ;
32
- import { TimeoutError } from '../errors' ;
33
30
import { PipeTransport } from './pipeTransport' ;
31
+ import { Progress } from '../progress' ;
34
32
35
33
export type BrowserArgOptions = {
36
34
headless ?: boolean ,
@@ -102,56 +100,36 @@ export abstract class BrowserTypeBase implements BrowserType {
102
100
async launch ( options : LaunchOptions = { } ) : Promise < Browser > {
103
101
assert ( ! ( options as any ) . userDataDir , 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead' ) ;
104
102
assert ( ! ( options as any ) . port , 'Cannot specify a port without launching as a server.' ) ;
105
- return this . _innerLaunch ( options , undefined ) ;
103
+ const logger = new RootLogger ( options . logger ) ;
104
+ const browser = await Progress . runCancelableTask ( progress => this . _innerLaunch ( progress , options , logger , undefined ) , options , logger ) ;
105
+ return browser ;
106
106
}
107
107
108
108
async launchPersistentContext ( userDataDir : string , options : LaunchOptions & PersistentContextOptions = { } ) : Promise < BrowserContext > {
109
109
assert ( ! ( options as any ) . port , 'Cannot specify a port without launching as a server.' ) ;
110
110
const persistent = validatePersistentContextOptions ( options ) ;
111
- const browser = await this . _innerLaunch ( options , persistent , userDataDir ) ;
112
- return browser . _defaultContext ! ;
113
- }
114
-
115
- async _innerLaunch ( options : LaunchOptions , persistent : PersistentContextOptions | undefined , userDataDir ?: string ) : Promise < BrowserBase > {
116
- const deadline = TimeoutSettings . computeDeadline ( options . timeout ) ;
117
111
const logger = new RootLogger ( options . logger ) ;
118
- logger . startLaunchRecording ( ) ;
119
-
120
- let browserServer : BrowserServer | undefined ;
121
- try {
122
- const launched = await this . _launchServer ( options , ! ! persistent , logger , deadline , userDataDir ) ;
123
- browserServer = launched . browserServer ;
124
- const browserOptions : BrowserOptions = {
125
- slowMo : options . slowMo ,
126
- persistent,
127
- headful : ! processBrowserArgOptions ( options ) . headless ,
128
- logger,
129
- downloadsPath : launched . downloadsPath ,
130
- ownedServer : browserServer ,
131
- } ;
132
- copyTestHooks ( options , browserOptions ) ;
133
- const hasCustomArguments = ! ! options . ignoreDefaultArgs && ! Array . isArray ( options . ignoreDefaultArgs ) ;
134
- const promise = this . _innerCreateBrowser ( launched . transport , browserOptions , hasCustomArguments ) ;
135
- const browser = await helper . waitWithDeadline ( promise , 'the browser to launch' , deadline , 'pw:browser*' ) ;
136
- return browser ;
137
- } catch ( e ) {
138
- rewriteErrorMessage ( e , e . message + '\n=============== Process output during launch: ===============\n' +
139
- logger . launchRecording ( ) +
140
- '\n=============================================================' ) ;
141
- if ( browserServer )
142
- await browserServer . _closeOrKill ( deadline ) ;
143
- throw e ;
144
- } finally {
145
- logger . stopLaunchRecording ( ) ;
146
- }
112
+ const browser = await Progress . runCancelableTask ( progress => this . _innerLaunch ( progress , options , logger , persistent , userDataDir ) , options , logger ) ;
113
+ return browser . _defaultContext ! ;
147
114
}
148
115
149
- async _innerCreateBrowser ( transport : ConnectionTransport , browserOptions : BrowserOptions , hasCustomArguments : boolean ) : Promise < BrowserBase > {
150
- if ( ( browserOptions as any ) . __testHookBeforeCreateBrowser )
151
- await ( browserOptions as any ) . __testHookBeforeCreateBrowser ( ) ;
116
+ async _innerLaunch ( progress : Progress , options : LaunchOptions , logger : RootLogger , persistent : PersistentContextOptions | undefined , userDataDir ?: string ) : Promise < BrowserBase > {
117
+ const { browserServer, downloadsPath, transport } = await this . _launchServer ( progress , options , ! ! persistent , logger , userDataDir ) ;
118
+ if ( ( options as any ) . __testHookBeforeCreateBrowser )
119
+ await ( options as any ) . __testHookBeforeCreateBrowser ( ) ;
120
+ const browserOptions : BrowserOptions = {
121
+ slowMo : options . slowMo ,
122
+ persistent,
123
+ headful : ! processBrowserArgOptions ( options ) . headless ,
124
+ logger,
125
+ downloadsPath,
126
+ ownedServer : browserServer ,
127
+ } ;
128
+ copyTestHooks ( options , browserOptions ) ;
152
129
const browser = await this . _connectToTransport ( transport , browserOptions ) ;
153
130
// We assume no control when using custom arguments, and do not prepare the default context in that case.
154
- if ( browserOptions . persistent && ! hasCustomArguments )
131
+ const hasCustomArguments = ! ! options . ignoreDefaultArgs && ! Array . isArray ( options . ignoreDefaultArgs ) ;
132
+ if ( persistent && ! hasCustomArguments )
155
133
await browser . _defaultContext ! . _loadDefaultContext ( ) ;
156
134
return browser ;
157
135
}
@@ -160,44 +138,26 @@ export abstract class BrowserTypeBase implements BrowserType {
160
138
assert ( ! ( options as any ) . userDataDir , 'userDataDir option is not supported in `browserType.launchServer`. Use `browserType.launchPersistentContext` instead' ) ;
161
139
const { port = 0 } = options ;
162
140
const logger = new RootLogger ( options . logger ) ;
163
- const { browserServer, transport } = await this . _launchServer ( options , false , logger , TimeoutSettings . computeDeadline ( options . timeout ) ) ;
164
- browserServer . _webSocketWrapper = this . _wrapTransportWithWebSocket ( transport , logger , port ) ;
165
- return browserServer ;
141
+ return Progress . runCancelableTask ( async progress => {
142
+ const { browserServer, transport } = await this . _launchServer ( progress , options , false , logger ) ;
143
+ browserServer . _webSocketWrapper = this . _wrapTransportWithWebSocket ( transport , logger , port ) ;
144
+ return browserServer ;
145
+ } , options , logger ) ;
166
146
}
167
147
168
148
async connect ( options : ConnectOptions ) : Promise < Browser > {
169
- const deadline = TimeoutSettings . computeDeadline ( options . timeout ) ;
170
149
const logger = new RootLogger ( options . logger ) ;
171
- logger . startLaunchRecording ( ) ;
172
-
173
- let transport : ConnectionTransport | undefined ;
174
- try {
175
- transport = await WebSocketTransport . connect ( options . wsEndpoint , logger , deadline ) ;
176
- const browserOptions : BrowserOptions = {
177
- slowMo : options . slowMo ,
178
- logger,
179
- } ;
180
- copyTestHooks ( options , browserOptions ) ;
181
- const promise = this . _innerCreateBrowser ( transport , browserOptions , false ) ;
182
- const browser = await helper . waitWithDeadline ( promise , 'connect to browser' , deadline , 'pw:browser*' ) ;
183
- logger . stopLaunchRecording ( ) ;
150
+ return Progress . runCancelableTask ( async progress => {
151
+ const transport = await WebSocketTransport . connect ( progress , options . wsEndpoint ) ;
152
+ progress . cleanupWhenCanceled ( ( ) => transport . closeAndWait ( ) ) ;
153
+ if ( ( options as any ) . __testHookBeforeCreateBrowser )
154
+ await ( options as any ) . __testHookBeforeCreateBrowser ( ) ;
155
+ const browser = await this . _connectToTransport ( transport , { slowMo : options . slowMo , logger } ) ;
184
156
return browser ;
185
- } catch ( e ) {
186
- rewriteErrorMessage ( e , e . message + '\n=============== Process output during connect: ===============\n' +
187
- logger . launchRecording ( ) +
188
- '\n=============================================================' ) ;
189
- try {
190
- if ( transport )
191
- transport . close ( ) ;
192
- } catch ( e ) {
193
- }
194
- throw e ;
195
- } finally {
196
- logger . stopLaunchRecording ( ) ;
197
- }
157
+ } , options , logger ) ;
198
158
}
199
159
200
- private async _launchServer ( options : LaunchServerOptions , isPersistent : boolean , logger : RootLogger , deadline : number , userDataDir ?: string ) : Promise < { browserServer : BrowserServer , downloadsPath : string , transport : ConnectionTransport } > {
160
+ private async _launchServer ( progress : Progress , options : LaunchServerOptions , isPersistent : boolean , logger : RootLogger , userDataDir ?: string ) : Promise < { browserServer : BrowserServer , downloadsPath : string , transport : ConnectionTransport } > {
201
161
const {
202
162
ignoreDefaultArgs = false ,
203
163
args = [ ] ,
@@ -238,7 +198,7 @@ export abstract class BrowserTypeBase implements BrowserType {
238
198
handleSIGINT,
239
199
handleSIGTERM,
240
200
handleSIGHUP,
241
- logger ,
201
+ progress ,
242
202
pipe : ! this . _webSocketRegexNotPipe ,
243
203
tempDirectories,
244
204
attemptToGracefullyClose : async ( ) => {
@@ -254,23 +214,17 @@ export abstract class BrowserTypeBase implements BrowserType {
254
214
browserServer . emit ( Events . BrowserServer . Close , exitCode , signal ) ;
255
215
} ,
256
216
} ) ;
257
-
258
- try {
259
- if ( this . _webSocketRegexNotPipe ) {
260
- const timeoutError = new TimeoutError ( `Timed out while trying to connect to the browser!` ) ;
261
- const match = await waitForLine ( launchedProcess , launchedProcess . stdout , this . _webSocketRegexNotPipe , helper . timeUntilDeadline ( deadline ) , timeoutError ) ;
262
- const innerEndpoint = match [ 1 ] ;
263
- transport = await WebSocketTransport . connect ( innerEndpoint , logger , deadline ) ;
264
- } else {
265
- const stdio = launchedProcess . stdio as unknown as [ NodeJS . ReadableStream , NodeJS . WritableStream , NodeJS . WritableStream , NodeJS . WritableStream , NodeJS . ReadableStream ] ;
266
- transport = new PipeTransport ( stdio [ 3 ] , stdio [ 4 ] , logger ) ;
267
- }
268
- } catch ( e ) {
269
- // If we can't establish a connection, kill the process and exit.
270
- helper . killProcess ( launchedProcess ) ;
271
- throw e ;
272
- }
273
217
browserServer = new BrowserServer ( launchedProcess , gracefullyClose , kill ) ;
218
+ progress . cleanupWhenCanceled ( ( ) => browserServer && browserServer . _closeOrKill ( progress . deadline ) ) ;
219
+
220
+ if ( this . _webSocketRegexNotPipe ) {
221
+ const match = await waitForLine ( progress , launchedProcess , launchedProcess . stdout , this . _webSocketRegexNotPipe ) ;
222
+ const innerEndpoint = match [ 1 ] ;
223
+ transport = await WebSocketTransport . connect ( progress , innerEndpoint ) ;
224
+ } else {
225
+ const stdio = launchedProcess . stdio as unknown as [ NodeJS . ReadableStream , NodeJS . WritableStream , NodeJS . WritableStream , NodeJS . WritableStream , NodeJS . ReadableStream ] ;
226
+ transport = new PipeTransport ( stdio [ 3 ] , stdio [ 4 ] , logger ) ;
227
+ }
274
228
return { browserServer, downloadsPath, transport } ;
275
229
}
276
230
0 commit comments