@@ -36,6 +36,13 @@ type ContextData = {
36
36
rerunnableTasks : Set < RerunnableTask > ;
37
37
} ;
38
38
39
+ type DocumentInfo = {
40
+ // Unfortunately, we don't have documentId when we find out about
41
+ // a pending navigation from things like frameScheduledNavigaiton.
42
+ documentId : string | undefined ,
43
+ request : network . Request | undefined ,
44
+ } ;
45
+
39
46
export type GotoResult = {
40
47
newDocumentId ?: string ,
41
48
} ;
@@ -125,32 +132,34 @@ export class FrameManager {
125
132
barrier . release ( ) ;
126
133
}
127
134
128
- frameRequestedNavigation ( frameId : string , documentId : string ) {
135
+ frameRequestedNavigation ( frameId : string , documentId ? : string ) {
129
136
const frame = this . _frames . get ( frameId ) ;
130
137
if ( ! frame )
131
138
return ;
132
139
for ( const barrier of this . _signalBarriers )
133
140
barrier . addFrameNavigation ( frame ) ;
134
- frame . _pendingDocumentId = documentId ;
135
- }
136
-
137
- frameUpdatedDocumentIdForNavigation ( frameId : string , documentId : string ) {
138
- const frame = this . _frames . get ( frameId ) ;
139
- if ( ! frame )
141
+ if ( frame . _pendingDocument && frame . _pendingDocument . documentId === documentId ) {
142
+ // Do not override request with undefined.
140
143
return ;
141
- frame . _pendingDocumentId = documentId ;
144
+ }
145
+ frame . _pendingDocument = { documentId, request : undefined } ;
142
146
}
143
147
144
148
frameCommittedNewDocumentNavigation ( frameId : string , url : string , name : string , documentId : string , initial : boolean ) {
145
149
const frame = this . _frames . get ( frameId ) ! ;
146
150
this . removeChildFramesRecursively ( frame ) ;
147
151
frame . _url = url ;
148
152
frame . _name = name ;
149
- debugAssert ( ! frame . _pendingDocumentId || frame . _pendingDocumentId === documentId ) ;
150
- frame . _lastDocumentId = documentId ;
151
- frame . _pendingDocumentId = '' ;
153
+ if ( frame . _pendingDocument && frame . _pendingDocument . documentId === undefined )
154
+ frame . _pendingDocument . documentId = documentId ;
155
+ debugAssert ( ! frame . _pendingDocument || frame . _pendingDocument . documentId === documentId ) ;
156
+ if ( frame . _pendingDocument && frame . _pendingDocument . documentId === documentId )
157
+ frame . _currentDocument = frame . _pendingDocument ;
158
+ else
159
+ frame . _currentDocument = { documentId, request : undefined } ;
160
+ frame . _pendingDocument = undefined ;
152
161
for ( const task of frame . _frameTasks )
153
- task . onNewDocument ( documentId ) ;
162
+ task . onNewDocument ( frame . _currentDocument ) ;
154
163
this . clearFrameLifecycle ( frame ) ;
155
164
if ( ! initial )
156
165
this . _page . emit ( Events . Page . FrameNavigated , frame ) ;
@@ -166,6 +175,18 @@ export class FrameManager {
166
175
this . _page . emit ( Events . Page . FrameNavigated , frame ) ;
167
176
}
168
177
178
+ frameAbortedNavigation ( frameId : string , errorText : string , documentId ?: string ) {
179
+ const frame = this . _frames . get ( frameId ) ;
180
+ if ( ! frame || ! frame . _pendingDocument )
181
+ return ;
182
+ if ( documentId !== undefined && frame . _pendingDocument . documentId !== documentId )
183
+ return ;
184
+ const pending = frame . _pendingDocument ;
185
+ frame . _pendingDocument = undefined ;
186
+ for ( const task of frame . _frameTasks )
187
+ task . onNewDocument ( pending , new Error ( errorText ) ) ;
188
+ }
189
+
169
190
frameDetached ( frameId : string ) {
170
191
const frame = this . _frames . get ( frameId ) ;
171
192
if ( frame )
@@ -194,16 +215,17 @@ export class FrameManager {
194
215
clearFrameLifecycle ( frame : Frame ) {
195
216
frame . _firedLifecycleEvents . clear ( ) ;
196
217
// Keep the current navigation request if any.
197
- frame . _inflightRequests = new Set ( Array . from ( frame . _inflightRequests ) . filter ( request => request . _documentId === frame . _lastDocumentId ) ) ;
218
+ frame . _inflightRequests = new Set ( Array . from ( frame . _inflightRequests ) . filter ( request => request === frame . _currentDocument . request ) ) ;
198
219
frame . _stopNetworkIdleTimer ( ) ;
199
220
if ( frame . _inflightRequests . size === 0 )
200
221
frame . _startNetworkIdleTimer ( ) ;
201
222
}
202
223
203
224
requestStarted ( request : network . Request ) {
225
+ const frame = request . frame ( ) ;
204
226
this . _inflightRequestStarted ( request ) ;
205
- for ( const task of request . frame ( ) . _frameTasks )
206
- task . onRequest ( request ) ;
227
+ if ( request . _documentId )
228
+ frame . _pendingDocument = { documentId : request . _documentId , request } ;
207
229
if ( request . _isFavicon ) {
208
230
const route = request . _route ( ) ;
209
231
if ( route )
@@ -225,27 +247,18 @@ export class FrameManager {
225
247
}
226
248
227
249
requestFailed ( request : network . Request , canceled : boolean ) {
250
+ const frame = request . frame ( ) ;
228
251
this . _inflightRequestFinished ( request ) ;
229
- if ( request . _documentId ) {
230
- const isPendingDocument = request . frame ( ) . _pendingDocumentId === request . _documentId ;
231
- if ( isPendingDocument ) {
232
- request . frame ( ) . _pendingDocumentId = '' ;
233
- let errorText = request . failure ( ) ! . errorText ;
234
- if ( canceled )
235
- errorText += '; maybe frame was detached?' ;
236
- for ( const task of request . frame ( ) . _frameTasks )
237
- task . onNewDocument ( request . _documentId , new Error ( errorText ) ) ;
238
- }
252
+ if ( frame . _pendingDocument && frame . _pendingDocument . request === request ) {
253
+ let errorText = request . failure ( ) ! . errorText ;
254
+ if ( canceled )
255
+ errorText += '; maybe frame was detached?' ;
256
+ this . frameAbortedNavigation ( frame . _id , errorText , frame . _pendingDocument . documentId ) ;
239
257
}
240
258
if ( ! request . _isFavicon )
241
259
this . _page . emit ( Events . Page . RequestFailed , request ) ;
242
260
}
243
261
244
- provisionalLoadFailed ( frame : Frame , documentId : string , error : string ) {
245
- for ( const task of frame . _frameTasks )
246
- task . onNewDocument ( documentId , new Error ( error ) ) ;
247
- }
248
-
249
262
private _notifyLifecycle ( frame : Frame , lifecycleEvent : types . LifecycleEvent ) {
250
263
for ( let parent : Frame | null = frame ; parent ; parent = parent . parentFrame ( ) ) {
251
264
for ( const frameTask of parent . _frameTasks )
@@ -301,8 +314,8 @@ export class FrameManager {
301
314
export class Frame {
302
315
_id : string ;
303
316
readonly _firedLifecycleEvents : Set < types . LifecycleEvent > ;
304
- _lastDocumentId = '' ;
305
- _pendingDocumentId = '' ;
317
+ _currentDocument : DocumentInfo ;
318
+ _pendingDocument ?: DocumentInfo ;
306
319
_frameTasks = new Set < FrameTask > ( ) ;
307
320
readonly _page : Page ;
308
321
private _parentFrame : Frame | null ;
@@ -322,6 +335,7 @@ export class Frame {
322
335
this . _firedLifecycleEvents = new Set ( ) ;
323
336
this . _page = page ;
324
337
this . _parentFrame = parentFrame ;
338
+ this . _currentDocument = { documentId : undefined , request : undefined } ;
325
339
326
340
this . _detachedPromise = new Promise < void > ( x => this . _detachedCallback = x ) ;
327
341
@@ -358,14 +372,14 @@ export class Frame {
358
372
sameDocumentPromise . catch ( e => { } ) ;
359
373
throw e ;
360
374
} ) ;
375
+ let request : network . Request | undefined ;
361
376
if ( navigateResult . newDocumentId ) {
362
377
// Do not leave sameDocumentPromise unhandled.
363
378
sameDocumentPromise . catch ( e => { } ) ;
364
- await frameTask . waitForSpecificDocument ( navigateResult . newDocumentId ) ;
379
+ request = await frameTask . waitForSpecificDocument ( navigateResult . newDocumentId ) ;
365
380
} else {
366
381
await sameDocumentPromise ;
367
382
}
368
- const request = ( navigateResult && navigateResult . newDocumentId ) ? frameTask . request ( navigateResult . newDocumentId ) : null ;
369
383
await frameTask . waitForLifecycle ( options . waitUntil === undefined ? 'load' : options . waitUntil ) ;
370
384
frameTask . done ( ) ;
371
385
return request ? request . _finalRequest ( ) . response ( ) : null ;
@@ -377,12 +391,11 @@ export class Frame {
377
391
const toUrl = typeof options . url === 'string' ? ` to "${ options . url } "` : '' ;
378
392
progress . logger . info ( `waiting for navigation${ toUrl } until "${ options . waitUntil || 'load' } "` ) ;
379
393
const frameTask = new FrameTask ( this , progress ) ;
380
- let documentId : string | undefined ;
394
+ let request : network . Request | undefined ;
381
395
await Promise . race ( [
382
- frameTask . waitForNewDocument ( options . url ) . then ( id => documentId = id ) ,
396
+ frameTask . waitForNewDocument ( options . url ) . then ( r => request = r ) ,
383
397
frameTask . waitForSameDocumentNavigation ( options . url ) ,
384
398
] ) ;
385
- const request = documentId ? frameTask . request ( documentId ) : null ;
386
399
await frameTask . waitForLifecycle ( options . waitUntil === undefined ? 'load' : options . waitUntil ) ;
387
400
frameTask . done ( ) ;
388
401
return request ? request . _finalRequest ( ) . response ( ) : null ;
@@ -1026,11 +1039,10 @@ class SignalBarrier {
1026
1039
1027
1040
class FrameTask {
1028
1041
private readonly _frame : Frame ;
1029
- private readonly _requestMap = new Map < string , network . Request > ( ) ;
1030
1042
private readonly _progress : Progress | null = null ;
1031
1043
private _onSameDocument ?: { url ?: types . URLMatch , resolve : ( ) => void } ;
1032
- private _onSpecificDocument ?: { expectedDocumentId : string , resolve : ( ) => void , reject : ( error : Error ) => void } ;
1033
- private _onNewDocument ?: { url ?: types . URLMatch , resolve : ( documentId : string ) => void , reject : ( error : Error ) => void } ;
1044
+ private _onSpecificDocument ?: { expectedDocumentId : string , resolve : ( request : network . Request | undefined ) => void , reject : ( error : Error ) => void } ;
1045
+ private _onNewDocument ?: { url ?: types . URLMatch , resolve : ( request : network . Request | undefined ) => void , reject : ( error : Error ) => void } ;
1034
1046
private _onLifecycle ?: { waitUntil : types . LifecycleEvent , resolve : ( ) => void } ;
1035
1047
1036
1048
constructor ( frame : Frame , progress : Progress | null ) {
@@ -1041,32 +1053,22 @@ class FrameTask {
1041
1053
progress . cleanupWhenAborted ( ( ) => this . done ( ) ) ;
1042
1054
}
1043
1055
1044
- onRequest ( request : network . Request ) {
1045
- if ( ! request . _documentId || request . redirectedFrom ( ) )
1046
- return ;
1047
- this . _requestMap . set ( request . _documentId , request ) ;
1048
- }
1049
-
1050
- request ( documentId : string ) : network . Request | undefined {
1051
- return this . _requestMap . get ( documentId ) ;
1052
- }
1053
-
1054
1056
onSameDocument ( ) {
1055
1057
if ( this . _progress )
1056
1058
this . _progress . logger . info ( `navigated to "${ this . _frame . _url } "` ) ;
1057
1059
if ( this . _onSameDocument && helper . urlMatches ( this . _frame . url ( ) , this . _onSameDocument . url ) )
1058
1060
this . _onSameDocument . resolve ( ) ;
1059
1061
}
1060
1062
1061
- onNewDocument ( documentId : string , error ?: Error ) {
1063
+ onNewDocument ( documentInfo : DocumentInfo , error ?: Error ) {
1062
1064
if ( this . _progress && ! error )
1063
1065
this . _progress . logger . info ( `navigated to "${ this . _frame . _url } "` ) ;
1064
1066
if ( this . _onSpecificDocument ) {
1065
- if ( documentId === this . _onSpecificDocument . expectedDocumentId ) {
1067
+ if ( documentInfo . documentId === this . _onSpecificDocument . expectedDocumentId ) {
1066
1068
if ( error )
1067
1069
this . _onSpecificDocument . reject ( error ) ;
1068
1070
else
1069
- this . _onSpecificDocument . resolve ( ) ;
1071
+ this . _onSpecificDocument . resolve ( documentInfo . request ) ;
1070
1072
} else if ( ! error ) {
1071
1073
this . _onSpecificDocument . reject ( new Error ( 'Navigation interrupted by another one' ) ) ;
1072
1074
}
@@ -1075,7 +1077,7 @@ class FrameTask {
1075
1077
if ( error )
1076
1078
this . _onNewDocument . reject ( error ) ;
1077
1079
else if ( helper . urlMatches ( this . _frame . url ( ) , this . _onNewDocument . url ) )
1078
- this . _onNewDocument . resolve ( documentId ) ;
1080
+ this . _onNewDocument . resolve ( documentInfo . request ) ;
1079
1081
}
1080
1082
}
1081
1083
@@ -1093,14 +1095,14 @@ class FrameTask {
1093
1095
} ) ;
1094
1096
}
1095
1097
1096
- waitForSpecificDocument ( expectedDocumentId : string ) : Promise < void > {
1098
+ waitForSpecificDocument ( expectedDocumentId : string ) : Promise < network . Request | undefined > {
1097
1099
return new Promise ( ( resolve , reject ) => {
1098
1100
assert ( ! this . _onSpecificDocument ) ;
1099
1101
this . _onSpecificDocument = { expectedDocumentId, resolve, reject } ;
1100
1102
} ) ;
1101
1103
}
1102
1104
1103
- waitForNewDocument ( url ?: types . URLMatch ) : Promise < string > {
1105
+ waitForNewDocument ( url ?: types . URLMatch ) : Promise < network . Request | undefined > {
1104
1106
return new Promise ( ( resolve , reject ) => {
1105
1107
assert ( ! this . _onNewDocument ) ;
1106
1108
this . _onNewDocument = { url, resolve, reject } ;
0 commit comments