@@ -160,7 +160,7 @@ export class FrameManager {
160
160
frame . _pendingDocument = undefined ;
161
161
for ( const task of frame . _frameTasks )
162
162
task . onNewDocument ( frame . _currentDocument ) ;
163
- this . clearFrameLifecycle ( frame ) ;
163
+ frame . _onClearLifecycle ( ) ;
164
164
if ( ! initial )
165
165
this . _page . emit ( Events . Page . FrameNavigated , frame ) ;
166
166
}
@@ -200,25 +200,8 @@ export class FrameManager {
200
200
201
201
frameLifecycleEvent ( frameId : string , event : types . LifecycleEvent ) {
202
202
const frame = this . _frames . get ( frameId ) ;
203
- if ( ! frame )
204
- return ;
205
- if ( frame . _firedLifecycleEvents . has ( event ) )
206
- return ;
207
- frame . _firedLifecycleEvents . add ( event ) ;
208
- this . _notifyLifecycle ( frame , event ) ;
209
- if ( frame === this . _mainFrame && event === 'load' )
210
- this . _page . emit ( Events . Page . Load ) ;
211
- if ( frame === this . _mainFrame && event === 'domcontentloaded' )
212
- this . _page . emit ( Events . Page . DOMContentLoaded ) ;
213
- }
214
-
215
- clearFrameLifecycle ( frame : Frame ) {
216
- frame . _firedLifecycleEvents . clear ( ) ;
217
- // Keep the current navigation request if any.
218
- frame . _inflightRequests = new Set ( Array . from ( frame . _inflightRequests ) . filter ( request => request === frame . _currentDocument . request ) ) ;
219
- frame . _stopNetworkIdleTimer ( ) ;
220
- if ( frame . _inflightRequests . size === 0 )
221
- frame . _startNetworkIdleTimer ( ) ;
203
+ if ( frame )
204
+ frame . _onLifecycleEvent ( event ) ;
222
205
}
223
206
224
207
requestStarted ( request : network . Request ) {
@@ -259,13 +242,6 @@ export class FrameManager {
259
242
this . _page . emit ( Events . Page . RequestFailed , request ) ;
260
243
}
261
244
262
- private _notifyLifecycle ( frame : Frame , lifecycleEvent : types . LifecycleEvent ) {
263
- for ( let parent : Frame | null = frame ; parent ; parent = parent . parentFrame ( ) ) {
264
- for ( const frameTask of parent . _frameTasks )
265
- frameTask . onLifecycle ( frame , lifecycleEvent ) ;
266
- }
267
- }
268
-
269
245
removeChildFramesRecursively ( frame : Frame ) {
270
246
for ( const child of frame . childFrames ( ) )
271
247
this . _removeFramesRecursively ( child ) ;
@@ -313,7 +289,8 @@ export class FrameManager {
313
289
314
290
export class Frame {
315
291
_id : string ;
316
- readonly _firedLifecycleEvents : Set < types . LifecycleEvent > ;
292
+ private _firedLifecycleEvents = new Set < types . LifecycleEvent > ( ) ;
293
+ _subtreeLifecycleEvents = new Set < types . LifecycleEvent > ( ) ;
317
294
_currentDocument : DocumentInfo ;
318
295
_pendingDocument ?: DocumentInfo ;
319
296
_frameTasks = new Set < FrameTask > ( ) ;
@@ -332,7 +309,6 @@ export class Frame {
332
309
333
310
constructor ( page : Page , id : string , parentFrame : Frame | null ) {
334
311
this . _id = id ;
335
- this . _firedLifecycleEvents = new Set ( ) ;
336
312
this . _page = page ;
337
313
this . _parentFrame = parentFrame ;
338
314
this . _currentDocument = { documentId : undefined , request : undefined } ;
@@ -353,6 +329,51 @@ export class Frame {
353
329
return `${ subject } .${ method } ` ;
354
330
}
355
331
332
+ _onLifecycleEvent ( event : types . LifecycleEvent ) {
333
+ if ( this . _firedLifecycleEvents . has ( event ) )
334
+ return ;
335
+ this . _firedLifecycleEvents . add ( event ) ;
336
+ // Recalculate subtree lifecycle for the whole tree - it should not be that big.
337
+ this . _page . mainFrame ( ) . _recalculateLifecycle ( ) ;
338
+ }
339
+
340
+ _onClearLifecycle ( ) {
341
+ this . _firedLifecycleEvents . clear ( ) ;
342
+ // Recalculate subtree lifecycle for the whole tree - it should not be that big.
343
+ this . _page . mainFrame ( ) . _recalculateLifecycle ( ) ;
344
+ // Keep the current navigation request if any.
345
+ this . _inflightRequests = new Set ( Array . from ( this . _inflightRequests ) . filter ( request => request === this . _currentDocument . request ) ) ;
346
+ this . _stopNetworkIdleTimer ( ) ;
347
+ if ( this . _inflightRequests . size === 0 )
348
+ this . _startNetworkIdleTimer ( ) ;
349
+ }
350
+
351
+ private _recalculateLifecycle ( ) {
352
+ const events = new Set < types . LifecycleEvent > ( this . _firedLifecycleEvents ) ;
353
+ for ( const child of this . _childFrames ) {
354
+ child . _recalculateLifecycle ( ) ;
355
+ // We require a particular lifecycle event to be fired in the whole
356
+ // frame subtree, and then consider it done.
357
+ for ( const event of events ) {
358
+ if ( ! child . _subtreeLifecycleEvents . has ( event ) )
359
+ events . delete ( event ) ;
360
+ }
361
+ }
362
+ const mainFrame = this . _page . mainFrame ( ) ;
363
+ for ( const event of events ) {
364
+ // Checking whether we have already notified about this event.
365
+ if ( ! this . _subtreeLifecycleEvents . has ( event ) ) {
366
+ for ( const frameTask of this . _frameTasks )
367
+ frameTask . onLifecycle ( event ) ;
368
+ if ( this === mainFrame && event === 'load' )
369
+ this . _page . emit ( Events . Page . Load ) ;
370
+ if ( this === mainFrame && event === 'domcontentloaded' )
371
+ this . _page . emit ( Events . Page . DOMContentLoaded ) ;
372
+ }
373
+ }
374
+ this . _subtreeLifecycleEvents = events ;
375
+ }
376
+
356
377
async goto ( url : string , options : types . GotoOptions = { } ) : Promise < network . Response | null > {
357
378
return runNavigationTask ( this , options , this . _apiName ( 'goto' ) , async progress => {
358
379
progress . logger . info ( `navigating to "${ url } ", waiting until "${ options . waitUntil || 'load' } "` ) ;
@@ -553,7 +574,7 @@ export class Frame {
553
574
const lifecyclePromise = new Promise ( ( resolve , reject ) => {
554
575
this . _page . _frameManager . _consoleMessageTags . set ( tag , ( ) => {
555
576
// Clear lifecycle right after document.open() - see 'tag' below.
556
- this . _page . _frameManager . clearFrameLifecycle ( this ) ;
577
+ this . _onClearLifecycle ( ) ;
557
578
this . _waitForLoadState ( progress , waitUntil ) . then ( resolve ) . catch ( reject ) ;
558
579
} ) ;
559
580
} ) ;
@@ -939,7 +960,7 @@ export class Frame {
939
960
assert ( ! this . _networkIdleTimer ) ;
940
961
if ( this . _firedLifecycleEvents . has ( 'networkidle' ) )
941
962
return ;
942
- this . _networkIdleTimer = setTimeout ( ( ) => { this . _page . _frameManager . frameLifecycleEvent ( this . _id , 'networkidle' ) ; } , 500 ) ;
963
+ this . _networkIdleTimer = setTimeout ( ( ) => this . _onLifecycleEvent ( 'networkidle' ) , 500 ) ;
943
964
}
944
965
945
966
_stopNetworkIdleTimer ( ) {
@@ -1081,10 +1102,10 @@ class FrameTask {
1081
1102
}
1082
1103
}
1083
1104
1084
- onLifecycle ( frame : Frame , lifecycleEvent : types . LifecycleEvent ) {
1085
- if ( this . _progress && frame === this . _frame && frame . _url !== 'about:blank' )
1105
+ onLifecycle ( lifecycleEvent : types . LifecycleEvent ) {
1106
+ if ( this . _progress && this . _frame . _url !== 'about:blank' )
1086
1107
this . _progress . logger . info ( `"${ lifecycleEvent } " event fired` ) ;
1087
- if ( this . _onLifecycle && this . _checkLifecycleRecursively ( this . _frame , this . _onLifecycle . waitUntil ) )
1108
+ if ( this . _onLifecycle && this . _onLifecycle . waitUntil === lifecycleEvent )
1088
1109
this . _onLifecycle . resolve ( ) ;
1089
1110
}
1090
1111
@@ -1114,24 +1135,14 @@ class FrameTask {
1114
1135
waitUntil = 'networkidle' ;
1115
1136
if ( ! types . kLifecycleEvents . has ( waitUntil ) )
1116
1137
throw new Error ( `Unsupported waitUntil option ${ String ( waitUntil ) } ` ) ;
1117
- if ( this . _checkLifecycleRecursively ( this . _frame , waitUntil ) )
1138
+ if ( this . _frame . _subtreeLifecycleEvents . has ( waitUntil ) )
1118
1139
return Promise . resolve ( ) ;
1119
1140
return new Promise ( resolve => {
1120
1141
assert ( ! this . _onLifecycle ) ;
1121
1142
this . _onLifecycle = { waitUntil, resolve } ;
1122
1143
} ) ;
1123
1144
}
1124
1145
1125
- private _checkLifecycleRecursively ( frame : Frame , waitUntil : types . LifecycleEvent ) : boolean {
1126
- if ( ! frame . _firedLifecycleEvents . has ( waitUntil ) )
1127
- return false ;
1128
- for ( const child of frame . childFrames ( ) ) {
1129
- if ( ! this . _checkLifecycleRecursively ( child , waitUntil ) )
1130
- return false ;
1131
- }
1132
- return true ;
1133
- }
1134
-
1135
1146
done ( ) {
1136
1147
this . _frame . _frameTasks . delete ( this ) ;
1137
1148
}
0 commit comments