@@ -54,13 +54,15 @@ export type LifecycleEvent = 'load' | 'domcontentloaded' | 'networkidle0' | 'net
54
54
const kLifecycleEvents : Set < LifecycleEvent > = new Set ( [ 'load' , 'domcontentloaded' , 'networkidle0' , 'networkidle2' ] ) ;
55
55
56
56
export type WaitForOptions = types . TimeoutOptions & { waitFor ?: types . Visibility | 'nowait' } ;
57
+ type ConsoleTagHandler = ( ) => void ;
57
58
58
59
export class FrameManager {
59
60
private _page : Page ;
60
61
private _frames = new Map < string , Frame > ( ) ;
61
62
private _webSockets = new Map < string , network . WebSocket > ( ) ;
62
63
private _mainFrame : Frame ;
63
64
readonly _lifecycleWatchers = new Set < LifecycleWatcher > ( ) ;
65
+ readonly _consoleMessageTags = new Map < string , ConsoleTagHandler > ( ) ;
64
66
65
67
constructor ( page : Page ) {
66
68
this . _page = page ;
@@ -116,8 +118,7 @@ export class FrameManager {
116
118
frame . _url = url ;
117
119
frame . _name = name ;
118
120
frame . _lastDocumentId = documentId ;
119
- this . frameLifecycleEvent ( frameId , 'clear' ) ;
120
- this . clearInflightRequests ( frame ) ;
121
+ this . clearFrameLifecycle ( frame ) ;
121
122
this . clearWebSockets ( frame ) ;
122
123
if ( ! initial ) {
123
124
for ( const watcher of this . _lifecycleWatchers )
@@ -158,24 +159,21 @@ export class FrameManager {
158
159
this . _page . emit ( Events . Page . Load ) ;
159
160
}
160
161
161
- frameLifecycleEvent ( frameId : string , event : LifecycleEvent | 'clear' ) {
162
+ frameLifecycleEvent ( frameId : string , event : LifecycleEvent ) {
162
163
const frame = this . _frames . get ( frameId ) ;
163
164
if ( ! frame )
164
165
return ;
165
- if ( event === 'clear' ) {
166
- frame . _firedLifecycleEvents . clear ( ) ;
167
- } else {
168
- frame . _firedLifecycleEvents . add ( event ) ;
169
- for ( const watcher of this . _lifecycleWatchers )
170
- watcher . _onLifecycleEvent ( frame ) ;
171
- }
166
+ frame . _firedLifecycleEvents . add ( event ) ;
167
+ for ( const watcher of this . _lifecycleWatchers )
168
+ watcher . _onLifecycleEvent ( frame ) ;
172
169
if ( frame === this . _mainFrame && event === 'load' )
173
170
this . _page . emit ( Events . Page . Load ) ;
174
171
if ( frame === this . _mainFrame && event === 'domcontentloaded' )
175
172
this . _page . emit ( Events . Page . DOMContentLoaded ) ;
176
173
}
177
174
178
- clearInflightRequests ( frame : Frame ) {
175
+ clearFrameLifecycle ( frame : Frame ) {
176
+ frame . _firedLifecycleEvents . clear ( ) ;
179
177
// Keep the current navigation request if any.
180
178
frame . _inflightRequests = new Set ( Array . from ( frame . _inflightRequests ) . filter ( request => request . _documentId === frame . _lastDocumentId ) ) ;
181
179
this . _stopNetworkIdleTimer ( frame , 'networkidle0' ) ;
@@ -330,6 +328,18 @@ export class FrameManager {
330
328
clearTimeout ( timeoutId ) ;
331
329
frame . _networkIdleTimers . delete ( event ) ;
332
330
}
331
+
332
+ interceptConsoleMessage ( message : ConsoleMessage ) : boolean {
333
+ if ( message . type ( ) !== 'debug' )
334
+ return false ;
335
+ const tag = message . text ( ) ;
336
+ const handler = this . _consoleMessageTags . get ( tag ) ;
337
+ if ( ! handler )
338
+ return false ;
339
+ this . _consoleMessageTags . delete ( tag ) ;
340
+ handler ( ) ;
341
+ return true ;
342
+ }
333
343
}
334
344
335
345
export class Frame {
@@ -345,6 +355,7 @@ export class Frame {
345
355
_name = '' ;
346
356
_inflightRequests = new Set < network . Request > ( ) ;
347
357
readonly _networkIdleTimers = new Map < LifecycleEvent , NodeJS . Timer > ( ) ;
358
+ private _setContentCounter = 0 ;
348
359
349
360
constructor ( page : Page , id : string , parentFrame : Frame | null ) {
350
361
this . _id = id ;
@@ -510,23 +521,27 @@ export class Frame {
510
521
}
511
522
512
523
async setContent ( html : string , options ?: NavigateOptions ) : Promise < void > {
524
+ const tag = `--playwright--set--content--${ this . _id } --${ ++ this . _setContentCounter } --` ;
513
525
const context = await this . _utilityContext ( ) ;
514
- if ( this . _page . _delegate . needsLifecycleResetOnSetContent ( ) ) {
515
- this . _page . _frameManager . frameLifecycleEvent ( this . _id , 'clear' ) ;
516
- this . _page . _frameManager . clearInflightRequests ( this ) ;
517
- }
518
- await context . evaluate ( html => {
526
+ let watcher : LifecycleWatcher ;
527
+ this . _page . _frameManager . _consoleMessageTags . set ( tag , ( ) => {
528
+ // Clear lifecycle right after document.open() - see 'tag' below.
529
+ this . _page . _frameManager . clearFrameLifecycle ( this ) ;
530
+ watcher = new LifecycleWatcher ( this , options , false /* supportUrlMatch */ ) ;
531
+ } ) ;
532
+ await context . evaluate ( ( html , tag ) => {
519
533
window . stop ( ) ;
520
534
document . open ( ) ;
535
+ console . debug ( tag ) ; // eslint-disable-line no-console
521
536
document . write ( html ) ;
522
537
document . close ( ) ;
523
- } , html ) ;
524
- const watcher = new LifecycleWatcher ( this , options , false /* supportUrlMatch */ ) ;
538
+ } , html , tag ) ;
539
+ assert ( watcher ! , 'Was not able to clear lifecycle in setContent' ) ;
525
540
const error = await Promise . race ( [
526
- watcher . timeoutOrTerminationPromise ,
527
- watcher . lifecyclePromise ,
541
+ watcher ! . timeoutOrTerminationPromise ,
542
+ watcher ! . lifecyclePromise ,
528
543
] ) ;
529
- watcher . dispose ( ) ;
544
+ watcher ! . dispose ( ) ;
530
545
if ( error )
531
546
throw error ;
532
547
}
@@ -1092,4 +1107,4 @@ function selectorToString(selector: string, visibility: types.Visibility): strin
1092
1107
label = '' ; break ;
1093
1108
}
1094
1109
return `${ label } ${ selector } ` ;
1095
- }
1110
+ }
0 commit comments