fix: delete contexts from the map on navigation (#602)

This commit is contained in:
Yury Semikhatsky 2020-01-23 14:58:30 -08:00 committed by Dmitry Gozman
parent ac2ba3cbd9
commit 044ebd7fd8
3 changed files with 36 additions and 7 deletions

View File

@ -52,6 +52,7 @@ export class FFPage implements PageDelegate {
this._contextIdToContext = new Map(); this._contextIdToContext = new Map();
this._page = new Page(this, browserContext); this._page = new Page(this, browserContext);
this._networkManager = new FFNetworkManager(session, this._page); this._networkManager = new FFNetworkManager(session, this._page);
this._page.on(Events.Page.FrameDetached, frame => this._removeContextsForFrame(frame));
this._eventListeners = [ this._eventListeners = [
helper.addEventListener(this._session, 'Page.eventFired', this._onEventFired.bind(this)), helper.addEventListener(this._session, 'Page.eventFired', this._onEventFired.bind(this)),
helper.addEventListener(this._session, 'Page.frameAttached', this._onFrameAttached.bind(this)), helper.addEventListener(this._session, 'Page.frameAttached', this._onFrameAttached.bind(this)),
@ -122,6 +123,13 @@ export class FFPage implements PageDelegate {
context.frame._contextDestroyed(context as dom.FrameExecutionContext); context.frame._contextDestroyed(context as dom.FrameExecutionContext);
} }
private _removeContextsForFrame(frame: frames.Frame) {
for (const [contextId, context] of this._contextIdToContext) {
if (context.frame === frame)
this._contextIdToContext.delete(contextId);
}
}
_onNavigationStarted() { _onNavigationStarted() {
} }

View File

@ -59,6 +59,7 @@ export class WKPage implements PageDelegate {
this._page = new Page(this, browserContext); this._page = new Page(this, browserContext);
this._workers = new WKWorkers(this._page); this._workers = new WKWorkers(this._page);
this._session = undefined as any as WKSession; this._session = undefined as any as WKSession;
this._page.on(Events.Page.FrameDetached, frame => this._removeContextsForFrame(frame, false));
} }
private async _initializePageProxySession() { private async _initializePageProxySession() {
@ -248,13 +249,8 @@ export class WKPage implements PageDelegate {
private _onFrameNavigated(framePayload: Protocol.Page.Frame, initial: boolean) { private _onFrameNavigated(framePayload: Protocol.Page.Frame, initial: boolean) {
const frame = this._page._frameManager.frame(framePayload.id); const frame = this._page._frameManager.frame(framePayload.id);
for (const [contextId, context] of this._contextIdToContext) { assert(frame);
if (context.frame === frame) { this._removeContextsForFrame(frame!, true);
(context._delegate as WKExecutionContext)._dispose();
this._contextIdToContext.delete(contextId);
frame._contextDestroyed(context);
}
}
if (!framePayload.parentId) if (!framePayload.parentId)
this._workers.clear(); this._workers.clear();
this._page._frameManager.frameCommittedNewDocumentNavigation(framePayload.id, framePayload.url, framePayload.name || '', framePayload.loaderId, initial); this._page._frameManager.frameCommittedNewDocumentNavigation(framePayload.id, framePayload.url, framePayload.name || '', framePayload.loaderId, initial);
@ -268,6 +264,17 @@ export class WKPage implements PageDelegate {
this._page._frameManager.frameDetached(frameId); this._page._frameManager.frameDetached(frameId);
} }
private _removeContextsForFrame(frame: frames.Frame, notifyFrame: boolean) {
for (const [contextId, context] of this._contextIdToContext) {
if (context.frame === frame) {
(context._delegate as WKExecutionContext)._dispose();
this._contextIdToContext.delete(contextId);
if (notifyFrame)
frame._contextDestroyed(context);
}
}
}
private _onExecutionContextCreated(contextPayload : Protocol.Runtime.ExecutionContextDescription) { private _onExecutionContextCreated(contextPayload : Protocol.Runtime.ExecutionContextDescription) {
if (this._contextIdToContext.has(contextPayload.id)) if (this._contextIdToContext.has(contextPayload.id))
return; return;

View File

@ -331,6 +331,20 @@ module.exports.describe = function({testRunner, expect, FFOX, CHROMIUM, WEBKIT})
expect(await page.frames()[0].evaluate(() => document.body.textContent.trim())).toBe(''); expect(await page.frames()[0].evaluate(() => document.body.textContent.trim())).toBe('');
expect(await page.frames()[1].evaluate(() => document.body.textContent.trim())).toBe(`Hi, I'm frame`); expect(await page.frames()[1].evaluate(() => document.body.textContent.trim())).toBe(`Hi, I'm frame`);
}); });
it('should dispose context on navigation', async({page, server}) => {
await page.goto(server.PREFIX + '/frames/one-frame.html');
expect(page.frames().length).toBe(2);
expect(page._delegate._contextIdToContext.size).toBe(4);
await page.goto(server.EMPTY_PAGE);
expect(page._delegate._contextIdToContext.size).toBe(2);
});
it('should dispose context on cross-origin navigation', async({page, server}) => {
await page.goto(server.PREFIX + '/frames/one-frame.html');
expect(page.frames().length).toBe(2);
expect(page._delegate._contextIdToContext.size).toBe(4);
await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html');
expect(page._delegate._contextIdToContext.size).toBe(2);
});
it('should execute after cross-site navigation', async({page, server}) => { it('should execute after cross-site navigation', async({page, server}) => {
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
const mainFrame = page.mainFrame(); const mainFrame = page.mainFrame();