fix(oopif): store child frame id between frameDetached and attachedToTarget (#4410)
This commit is contained in:
parent
52147b3046
commit
eee82a7fca
|
|
@ -43,6 +43,8 @@ import { VideoRecorder } from './videoRecorder';
|
||||||
|
|
||||||
const UTILITY_WORLD_NAME = '__playwright_utility_world__';
|
const UTILITY_WORLD_NAME = '__playwright_utility_world__';
|
||||||
|
|
||||||
|
const swappingOutChildFrames = Symbol('swappingOutChildFrames');
|
||||||
|
|
||||||
export class CRPage implements PageDelegate {
|
export class CRPage implements PageDelegate {
|
||||||
readonly _mainFrameSession: FrameSession;
|
readonly _mainFrameSession: FrameSession;
|
||||||
readonly _sessions = new Map<Protocol.Target.TargetID, FrameSession>();
|
readonly _sessions = new Map<Protocol.Target.TargetID, FrameSession>();
|
||||||
|
|
@ -542,12 +544,35 @@ class FrameSession {
|
||||||
this._page._frameManager.frameCommittedSameDocumentNavigation(frameId, url);
|
this._page._frameManager.frameCommittedSameDocumentNavigation(frameId, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _takeParentForSwappingOutFrame(targetId: string) {
|
||||||
|
for (const frame of this._page.frames()) {
|
||||||
|
if (!(frame as any)[swappingOutChildFrames])
|
||||||
|
continue;
|
||||||
|
if ((frame as any)[swappingOutChildFrames].delete(targetId))
|
||||||
|
return frame._id;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _frameMaybeSwappingOut(frameId: string) {
|
||||||
|
const frame = this._page._frameManager.frame(frameId);
|
||||||
|
if (!frame)
|
||||||
|
return;
|
||||||
|
const parent = frame.parentFrame() as any;
|
||||||
|
if (!parent)
|
||||||
|
return;
|
||||||
|
if (!parent[swappingOutChildFrames])
|
||||||
|
parent[swappingOutChildFrames] = new Set<string>();
|
||||||
|
parent[swappingOutChildFrames].add(frameId);
|
||||||
|
}
|
||||||
|
|
||||||
_onFrameDetached(frameId: string) {
|
_onFrameDetached(frameId: string) {
|
||||||
if (this._crPage._sessions.has(frameId)) {
|
if (this._crPage._sessions.has(frameId)) {
|
||||||
// This is a local -> remote frame transtion.
|
// This is a local -> remote frame transtion.
|
||||||
// We already got a new target and handled frame reattach - nothing to do here.
|
// We already got a new target and handled frame reattach - nothing to do here.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this._frameMaybeSwappingOut(frameId);
|
||||||
this._page._frameManager.frameDetached(frameId);
|
this._page._frameManager.frameDetached(frameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -583,8 +608,16 @@ class FrameSession {
|
||||||
if (event.targetInfo.type === 'iframe') {
|
if (event.targetInfo.type === 'iframe') {
|
||||||
// Frame id equals target id.
|
// Frame id equals target id.
|
||||||
const targetId = event.targetInfo.targetId;
|
const targetId = event.targetInfo.targetId;
|
||||||
const frame = this._page._frameManager.frame(targetId)!;
|
const frame = this._page._frameManager.frame(targetId);
|
||||||
this._page._frameManager.removeChildFramesRecursively(frame);
|
if (frame) {
|
||||||
|
this._page._frameManager.removeChildFramesRecursively(frame);
|
||||||
|
} else {
|
||||||
|
// There is a race between Page.frameDetached and Target.attachedToTarget. If the frame
|
||||||
|
// has already been detached we look up its last parent frame.
|
||||||
|
const parentFrameId = this._takeParentForSwappingOutFrame(targetId);
|
||||||
|
assert(parentFrameId, 'Cannot find parent for iframe: ' + targetId);
|
||||||
|
this._page._frameManager.frameAttached(targetId, parentFrameId);
|
||||||
|
}
|
||||||
const frameSession = new FrameSession(this._crPage, session, targetId, this);
|
const frameSession = new FrameSession(this._crPage, session, targetId, this);
|
||||||
this._crPage._sessions.set(targetId, frameSession);
|
this._crPage._sessions.set(targetId, frameSession);
|
||||||
frameSession._initialize(false).catch(e => e);
|
frameSession._initialize(false).catch(e => e);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue