From 460527d8cbf0e3b240f5084c069448a0d4054380 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Tue, 28 Jan 2020 14:00:36 -0800 Subject: [PATCH] fix(webkit): do not poll readyState if target is paused before first navigation (#721) --- src/webkit/wkPage.ts | 28 +++++++++++++++------------- src/webkit/wkPageProxy.ts | 32 ++++++++++++++++++++++---------- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/webkit/wkPage.ts b/src/webkit/wkPage.ts index 7b47396725..486c7657c5 100644 --- a/src/webkit/wkPage.ts +++ b/src/webkit/wkPage.ts @@ -84,11 +84,11 @@ export class WKPage implements PageDelegate { this._workers.setSession(session); } - async initialize(session: WKSession) { + async initialize(session: WKSession, pagePausedOnStart: boolean) { this._setSession(session); await Promise.all([ this._initializePageProxySession(), - this._initializeSession(this._session, ({frameTree}) => this._handleFrameTree(frameTree)), + this._initializeSession(this._session, ({frameTree}) => this._handleFrameTree(frameTree, pagePausedOnStart)), ]); } @@ -234,24 +234,26 @@ export class WKPage implements PageDelegate { this._page._frameManager.frameLifecycleEvent(frameId, event); } - private _handleFrameTree(frameTree: Protocol.Page.FrameResourceTree) { + private _handleFrameTree(frameTree: Protocol.Page.FrameResourceTree, pagePausedOnStart: boolean) { const frame = this._onFrameAttached(frameTree.frame.id, frameTree.frame.parentId || null); this._onFrameNavigated(frameTree.frame, true); - frame._utilityContext().then(async context => { - const readyState = await context.evaluate(() => document.readyState).catch(e => 'loading'); - if (frame.isDetached()) - return; - if (readyState === 'interactive' || readyState === 'complete') - this._page._frameManager.frameLifecycleEvent(frame._id, 'domcontentloaded'); - if (readyState === 'complete') - this._page._frameManager.frameLifecycleEvent(frame._id, 'load'); - }); + if (!pagePausedOnStart) { + frame._utilityContext().then(async context => { + const readyState = await context.evaluate(() => document.readyState).catch(e => 'loading'); + if (frame.isDetached()) + return; + if (readyState === 'interactive' || readyState === 'complete') + this._page._frameManager.frameLifecycleEvent(frame._id, 'domcontentloaded'); + if (readyState === 'complete') + this._page._frameManager.frameLifecycleEvent(frame._id, 'load'); + }); + } if (!frameTree.childFrames) return; for (const child of frameTree.childFrames) - this._handleFrameTree(child); + this._handleFrameTree(child, pagePausedOnStart); } _onFrameAttached(frameId: string, parentFrameId: string | null): frames.Frame { diff --git a/src/webkit/wkPageProxy.ts b/src/webkit/wkPageProxy.ts index 37dd5d410d..d7d4794b8f 100644 --- a/src/webkit/wkPageProxy.ts +++ b/src/webkit/wkPageProxy.ts @@ -32,6 +32,7 @@ export class WKPageProxy { private _wkPage: WKPage | null = null; private readonly _firstTargetPromise: Promise; private _firstTargetCallback?: () => void; + private _pagePausedOnStart: boolean = false; private readonly _sessions = new Map(); private readonly _eventListeners: RegisteredListener[]; @@ -121,7 +122,11 @@ export class WKPageProxy { } assert(session, 'One non-provisional target session must exist'); this._wkPage = new WKPage(this._browserContext, this._pageProxySession); - await this._wkPage.initialize(session!); + await this._wkPage.initialize(session!, this._pagePausedOnStart); + if (this._pagePausedOnStart) { + this._resumeTarget(session!.sessionId); + this._pagePausedOnStart = false; + } return this._wkPage._page; } @@ -140,19 +145,26 @@ export class WKPageProxy { this._firstTargetCallback(); this._firstTargetCallback = undefined; } - if (targetInfo.isProvisional) + if (targetInfo.isProvisional) { (session as any)[isPovisionalSymbol] = true; - if (targetInfo.isProvisional && this._wkPage) - this._wkPage.onProvisionalLoadStarted(session); - if (targetInfo.isPaused) { - const resume = () => this._pageProxySession.send('Target.resume', { targetId: targetInfo.targetId }).catch(debugError); - if (targetInfo.isProvisional || !this._pagePromise) - resume(); - else - this._pagePromise.then(resume); + if (this._wkPage) + this._wkPage.onProvisionalLoadStarted(session); + if (targetInfo.isPaused) + this._resumeTarget(targetInfo.targetId); + } else if (this._pagePromise) { + assert(!this._pagePausedOnStart); + // This is the first time page target is created, will resume + // after finishing intialization. + this._pagePausedOnStart = !!targetInfo.isPaused; + } else if (targetInfo.isPaused) { + this._resumeTarget(targetInfo.targetId); } } + private _resumeTarget(targetId: string) { + this._pageProxySession.send('Target.resume', { targetId }).catch(debugError); + } + private _onTargetDestroyed(event: Protocol.Target.targetDestroyedPayload) { const { targetId, crashed } = event; const session = this._sessions.get(targetId);