fix(chromium): handle the case when new pending comes before old commit (#3370)

This commit is contained in:
Dmitry Gozman 2020-08-11 08:59:00 -07:00 committed by GitHub
parent ff2c2b299f
commit 9697ad635f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 11 deletions

View file

@ -20,7 +20,7 @@ import * as util from 'util';
import { ConsoleMessage } from './console';
import * as dom from './dom';
import { Events } from './events';
import { assert, helper, RegisteredListener, assertMaxArguments, debugAssert } from './helper';
import { assert, helper, RegisteredListener, assertMaxArguments } from './helper';
import * as js from './javascript';
import * as network from './network';
import { Page } from './page';
@ -172,14 +172,31 @@ export class FrameManager {
this.removeChildFramesRecursively(frame);
frame._url = url;
frame._name = name;
if (frame._pendingDocument && frame._pendingDocument.documentId === undefined)
frame._pendingDocument.documentId = documentId;
debugAssert(!frame._pendingDocument || frame._pendingDocument.documentId === documentId);
if (frame._pendingDocument && frame._pendingDocument.documentId === documentId)
frame._currentDocument = frame._pendingDocument;
else
let keepPending: DocumentInfo | undefined;
if (frame._pendingDocument) {
if (frame._pendingDocument.documentId === undefined) {
// Pending with unknown documentId - assume it is the one being committed.
frame._pendingDocument.documentId = documentId;
}
if (frame._pendingDocument.documentId === documentId) {
// Committing a pending document.
frame._currentDocument = frame._pendingDocument;
} else {
// Sometimes, we already have a new pending when the old one commits.
// An example would be Chromium error page followed by a new navigation request,
// where the error page commit arrives after Network.requestWillBeSent for the
// new navigation.
// We commit, but keep the pending request since it's not done yet.
keepPending = frame._pendingDocument;
frame._currentDocument = { documentId, request: undefined };
}
frame._pendingDocument = undefined;
} else {
// No pending - just commit a new document.
frame._currentDocument = { documentId, request: undefined };
frame._pendingDocument = undefined;
}
frame._onClearLifecycle();
const navigationEvent: NavigationEvent = { url, name, newDocument: frame._currentDocument };
frame._eventEmitter.emit(kNavigationEvent, navigationEvent);
@ -187,6 +204,8 @@ export class FrameManager {
this._page._logger.info(` navigated to "${url}"`);
this._page.emit(Events.Page.FrameNavigated, frame);
}
// Restore pending if any - see comments above about keepPending.
frame._pendingDocument = keepPending;
}
frameCommittedSameDocumentNavigation(frameId: string, url: string) {

View file

@ -17,7 +17,7 @@ require('./base.fixture');
const socks = require('socksv5');
const utils = require('./utils');
const {FFOX, CHROMIUM, WEBKIT, MAC} = testOptions;
const {FFOX, CHROMIUM, WEBKIT, MAC, HEADLESS} = testOptions;
it('should use proxy', async ({browserType, defaultBrowserOptions, server}) => {
server.setRoute('/target.html', async (req, res) => {
@ -40,7 +40,7 @@ it('should authenticate', async ({browserType, defaultBrowserOptions, server}) =
res.writeHead(407, 'Proxy Authentication Required', {
'Proxy-Authenticate': 'Basic realm="Access to internal site"'
});
res.end();
res.end();
} else {
res.end(`<html><title>${auth}</title></html>`);
}
@ -55,7 +55,8 @@ it('should authenticate', async ({browserType, defaultBrowserOptions, server}) =
await browser.close();
});
it('should exclude patterns', async ({browserType, defaultBrowserOptions, server}) => {
it.fail(CHROMIUM && !HEADLESS)('should exclude patterns', async ({browserType, defaultBrowserOptions, server}) => {
// Chromium headful crashes with CHECK(!in_frame_tree_) in RenderFrameImpl::OnDeleteFrame.
server.setRoute('/target.html', async (req, res) => {
res.end('<html><title>Served by the proxy</title></html>');
});
@ -83,6 +84,12 @@ it('should exclude patterns', async ({browserType, defaultBrowserOptions, server
expect(error.message).toBeTruthy();
}
if (CHROMIUM) {
// Should successfully navigate to the error page.
await page.waitForEvent('framenavigated', frame => frame.url() === 'chrome-error://chromewebdata/');
expect(page.url()).toBe('chrome-error://chromewebdata/');
}
await browser.close();
});