diff --git a/src/frames.ts b/src/frames.ts index 6ca12779bd..15d30b9cf8 100644 --- a/src/frames.ts +++ b/src/frames.ts @@ -945,6 +945,11 @@ class LifecycleWatcher { } _onCommittedNewDocumentNavigation(frame: Frame) { + if (frame === this._frame && this._expectedDocumentId !== undefined && this._navigationRequest && + frame._lastDocumentId !== this._expectedDocumentId) { + this._navigationAbortedCallback(new Error('Navigation to ' + this._targetUrl + ' was canceled by another one')); + return; + } if (frame === this._frame && this._expectedDocumentId === undefined && this._urlMatches(frame.url())) { this._expectedDocumentId = frame._lastDocumentId; this._targetUrl = frame.url(); diff --git a/test/interception.spec.js b/test/interception.spec.js index 4845865c11..76fd08c767 100644 --- a/test/interception.spec.js +++ b/test/interception.spec.js @@ -384,6 +384,49 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p await page.goto(server.EMPTY_PAGE); expect(error.message).toContain('Request Interception is not enabled'); }); + it.skip(WEBKIT)('should intercept main resource during cross-process navigation', async({page, server}) => { + await page.goto(server.EMPTY_PAGE); + await page.setRequestInterception(true); + let intercepted = false; + page.on('request', request => { + if (request.url().includes(server.CROSS_PROCESS_PREFIX + '/empty.html')) + intercepted = true; + request.continue(); + }); + const response = await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html'); + expect(response.ok()).toBe(true); + expect(intercepted).toBe(true); + }); + it('should not throw when continued after navigation', async({page, server}) => { + await page.setRequestInterception(true); + page.on('request', request => { + if (request.url() !== server.PREFIX + '/one-style.css') + request.continue(); + }); + // For some reason, Firefox issues load event with one outstanding request. + const failed = page.goto(server.PREFIX + '/one-style.html', { waitUntil: FFOX ? 'networkidle0' : 'load' }).catch(e => e); + const request = await page.waitForRequest(server.PREFIX + '/one-style.css'); + await page.goto(server.PREFIX + '/empty.html'); + const error = await failed; + expect(error.message).toBe('Navigation to ' + server.PREFIX + '/one-style.html was canceled by another one'); + const notAnError = await request.continue().then(() => null).catch(e => e); + expect(notAnError).toBe(null); + }); + it.skip(WEBKIT)('should not throw when continued after cross-process navigation', async({page, server}) => { + await page.setRequestInterception(true); + page.on('request', request => { + if (request.url() !== server.PREFIX + '/one-style.css') + request.continue(); + }); + // For some reason, Firefox issues load event with one outstanding request. + const failed = page.goto(server.PREFIX + '/one-style.html', { waitUntil: FFOX ? 'networkidle0' : 'load' }).catch(e => e); + const request = await page.waitForRequest(server.PREFIX + '/one-style.css'); + await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html'); + const error = await failed; + expect(error.message).toBe('Navigation to ' + server.PREFIX + '/one-style.html was canceled by another one'); + const notAnError = await request.continue().then(() => null).catch(e => e); + expect(notAnError).toBe(null); + }); }); describe('Interception.continue', function() { diff --git a/test/navigation.spec.js b/test/navigation.spec.js index 36f6b668c2..af1a336780 100644 --- a/test/navigation.spec.js +++ b/test/navigation.spec.js @@ -353,6 +353,15 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROME expect(request2.headers['referer']).toBe(undefined); expect(page.url()).toBe(server.PREFIX + '/grid.html'); }); + it('should fail when canceled by another navigation', async({page, server}) => { + server.setRoute('/one-style.css', (req, res) => {}); + // For some reason, Firefox issues load event with one outstanding request. + const failed = page.goto(server.PREFIX + '/one-style.html', { waitUntil: FFOX ? 'networkidle0' : 'load' }).catch(e => e); + await server.waitForRequest('/one-style.css'); + await page.goto(server.PREFIX + '/empty.html'); + const error = await failed; + expect(error.message).toBe('Navigation to ' + server.PREFIX + '/one-style.html was canceled by another one'); + }); describe('network idle', function() { it('should navigate to empty page with networkidle0', async({page, server}) => {