Skip to content

Commit 650d734

Browse files
authored
fix(actions): do not wait for the created popups (#2219)
Since we are recommending Promise.all pattern anyway, this special logic just adds to the possibility of timeout if something goes wrong. For example, Firefox sometimes send Page.willOpenNewWindowAsynchronously later than the new target arrives and input action just hangs.
1 parent 884860b commit 650d734

File tree

7 files changed

+10
-81
lines changed

7 files changed

+10
-81
lines changed

src/chromium/crBrowser.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,6 @@ export class CRBrowser extends BrowserBase {
152152
const opener = targetInfo.openerId ? this._crPages.get(targetInfo.openerId) || null : null;
153153
const crPage = new CRPage(session, targetInfo.targetId, context, opener, this._isHeadful);
154154
this._crPages.set(targetInfo.targetId, crPage);
155-
if (opener && opener._initializedPage) {
156-
for (const signalBarrier of opener._initializedPage._frameManager._signalBarriers)
157-
signalBarrier.addPopup(crPage.pageOrError());
158-
}
159155
crPage.pageOrError().then(() => {
160156
context!.emit(CommonEvents.BrowserContext.Page, crPage._page);
161157
if (opener) {

src/firefox/ffBrowser.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,6 @@ export class FFBrowser extends BrowserBase {
9999
const ffPage = new FFPage(session, context, opener);
100100
this._ffPages.set(targetId, ffPage);
101101

102-
if (opener && opener._initializedPage) {
103-
for (const signalBarrier of opener._initializedPage._frameManager._signalBarriers)
104-
signalBarrier.addPopup(ffPage.pageOrError());
105-
}
106102
ffPage.pageOrError().then(async () => {
107103
const page = ffPage._page;
108104
context.emit(Events.BrowserContext.Page, page);

src/firefox/ffPage.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export class FFPage implements PageDelegate {
6262
this._page = new Page(this, browserContext);
6363
this._networkManager = new FFNetworkManager(session, this._page);
6464
this._page.on(Events.Page.FrameDetached, frame => this._removeContextsForFrame(frame));
65+
// TODO: remove Page.willOpenNewWindowAsynchronously from the protocol.
6566
this._eventListeners = [
6667
helper.addEventListener(this._session, 'Page.eventFired', this._onEventFired.bind(this)),
6768
helper.addEventListener(this._session, 'Page.frameAttached', this._onFrameAttached.bind(this)),
@@ -73,7 +74,6 @@ export class FFPage implements PageDelegate {
7374
helper.addEventListener(this._session, 'Runtime.executionContextCreated', this._onExecutionContextCreated.bind(this)),
7475
helper.addEventListener(this._session, 'Runtime.executionContextDestroyed', this._onExecutionContextDestroyed.bind(this)),
7576
helper.addEventListener(this._session, 'Page.linkClicked', event => this._onLinkClicked(event.phase)),
76-
helper.addEventListener(this._session, 'Page.willOpenNewWindowAsynchronously', this._onWillOpenNewWindowAsynchronously.bind(this)),
7777
helper.addEventListener(this._session, 'Page.uncaughtError', this._onUncaughtError.bind(this)),
7878
helper.addEventListener(this._session, 'Runtime.console', this._onConsole.bind(this)),
7979
helper.addEventListener(this._session, 'Page.dialogOpened', this._onDialogOpened.bind(this)),
@@ -136,11 +136,6 @@ export class FFPage implements PageDelegate {
136136
this._page._frameManager.frameDidPotentiallyRequestNavigation();
137137
}
138138

139-
_onWillOpenNewWindowAsynchronously() {
140-
for (const barrier of this._page._frameManager._signalBarriers)
141-
barrier.expectPopup();
142-
}
143-
144139
_onNavigationStarted(params: Protocol.Page.navigationStartedPayload) {
145140
this._page._frameManager.frameRequestedNavigation(params.frameId, params.navigationId);
146141
}

src/frames.ts

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -954,10 +954,8 @@ function selectorToString(selector: string, state: 'attached' | 'detached' | 'vi
954954
}
955955

956956
export class SignalBarrier {
957-
private _frameIds = new Map<string, number>();
958957
private _options: types.NavigatingActionWaitOptions;
959958
private _protectCount = 0;
960-
private _expectedPopups = 0;
961959
private _promise: Promise<void>;
962960
private _promiseCallback = () => {};
963961
private _deadline: number;
@@ -981,23 +979,6 @@ export class SignalBarrier {
981979
this.release();
982980
}
983981

984-
async expectPopup() {
985-
++this._expectedPopups;
986-
}
987-
988-
async unexpectPopup() {
989-
--this._expectedPopups;
990-
this._maybeResolve();
991-
}
992-
993-
async addPopup(pageOrError: Promise<Page | Error>) {
994-
if (this._expectedPopups)
995-
--this._expectedPopups;
996-
this.retain();
997-
await pageOrError;
998-
this.release();
999-
}
1000-
1001982
retain() {
1002983
++this._protectCount;
1003984
}
@@ -1008,7 +989,7 @@ export class SignalBarrier {
1008989
}
1009990

1010991
private async _maybeResolve() {
1011-
if (!this._protectCount && !this._expectedPopups && !this._frameIds.size)
992+
if (!this._protectCount)
1012993
this._promiseCallback();
1013994
}
1014995
}

src/webkit/wkBrowser.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,6 @@ export class WKBrowser extends BrowserBase {
142142
const wkPage = new WKPage(context, pageProxySession, opener || null);
143143
this._wkPages.set(pageProxyId, wkPage);
144144

145-
if (opener && opener._initializedPage) {
146-
for (const signalBarrier of opener._initializedPage._frameManager._signalBarriers)
147-
signalBarrier.addPopup(wkPage.pageOrError());
148-
}
149145
wkPage.pageOrError().then(async () => {
150146
const page = wkPage._page;
151147
context!.emit(Events.BrowserContext.Page, page);

src/webkit/wkPage.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ export class WKPage implements PageDelegate {
309309
}
310310

311311
private _addSessionListeners() {
312+
// TODO: remove Page.willRequestOpenWindow and Page.didRequestOpenWindow from the protocol.
312313
this._sessionListeners = [
313314
helper.addEventListener(this._session, 'Page.frameNavigated', event => this._onFrameNavigated(event.frame, false)),
314315
helper.addEventListener(this._session, 'Page.navigatedWithinDocument', event => this._onFrameNavigatedWithinDocument(event.frameId, event.url)),
@@ -318,8 +319,6 @@ export class WKPage implements PageDelegate {
318319
helper.addEventListener(this._session, 'Page.frameStoppedLoading', event => this._onFrameStoppedLoading(event.frameId)),
319320
helper.addEventListener(this._session, 'Page.loadEventFired', event => this._onLifecycleEvent(event.frameId, 'load')),
320321
helper.addEventListener(this._session, 'Page.domContentEventFired', event => this._onLifecycleEvent(event.frameId, 'domcontentloaded')),
321-
helper.addEventListener(this._session, 'Page.willRequestOpenWindow', event => this._onWillRequestOpenWindow()),
322-
helper.addEventListener(this._session, 'Page.didRequestOpenWindow', event => this._onDidRequestOpenWindow(event)),
323322
helper.addEventListener(this._session, 'Runtime.executionContextCreated', event => this._onExecutionContextCreated(event.context)),
324323
helper.addEventListener(this._session, 'Console.messageAdded', event => this._onConsoleMessage(event)),
325324
helper.addEventListener(this._session, 'Console.messageRepeatCountUpdated', event => this._onConsoleRepeatCountUpdated(event)),
@@ -363,18 +362,6 @@ export class WKPage implements PageDelegate {
363362
this._page._frameManager.frameLifecycleEvent(frameId, event);
364363
}
365364

366-
private _onWillRequestOpenWindow() {
367-
for (const barrier of this._page._frameManager._signalBarriers)
368-
barrier.expectPopup();
369-
}
370-
371-
private _onDidRequestOpenWindow(event: Protocol.Page.didRequestOpenWindowPayload) {
372-
if (!event.opened) {
373-
for (const barrier of this._page._frameManager._signalBarriers)
374-
barrier.unexpectPopup();
375-
}
376-
}
377-
378365
private _handleFrameTree(frameTree: Protocol.Page.FrameResourceTree) {
379366
this._onFrameAttached(frameTree.frame.id, frameTree.frame.parentId || null);
380367
this._onFrameNavigated(frameTree.frame, true);

test/autowaiting.spec.js

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,6 @@ describe('Auto waiting', () => {
3434
]);
3535
expect(messages.join('|')).toBe('route|navigated|click');
3636
});
37-
it('should await popup when clicking anchor', async function({page, server}) {
38-
await page.goto(server.EMPTY_PAGE);
39-
await page.setContent('<a target=_blank rel=opener href="/empty.html">link</a>');
40-
const messages = [];
41-
await Promise.all([
42-
page.waitForEvent('popup').then(() => messages.push('popup')),
43-
page.click('a').then(() => messages.push('click')),
44-
]);
45-
expect(messages.join('|')).toBe('popup|click');
46-
});
47-
it('should await popup when clicking anchor with noopener', async function({page, server}) {
48-
await page.goto(server.EMPTY_PAGE);
49-
await page.setContent('<a target=_blank rel=noopener href="/empty.html">link</a>');
50-
const messages = [];
51-
await Promise.all([
52-
page.waitForEvent('popup').then(() => messages.push('popup')),
53-
page.click('a').then(() => messages.push('click')),
54-
]);
55-
expect(messages.join('|')).toBe('popup|click');
56-
});
5737
it('should await cross-process navigation when clicking anchor', async({page, server}) => {
5838
const messages = [];
5939
server.setRoute('/empty.html', async (req, res) => {
@@ -150,15 +130,6 @@ describe('Auto waiting', () => {
150130
]);
151131
expect(messages.join('|')).toBe('route|navigated|evaluate');
152132
});
153-
it('should await new popup when evaluating', async function({page, server}) {
154-
await page.goto(server.EMPTY_PAGE);
155-
const messages = [];
156-
await Promise.all([
157-
page.waitForEvent('popup').then(() => messages.push('popup')),
158-
page.evaluate(() => window._popup = window.open(window.location.href)).then(() => messages.push('evaluate')),
159-
]);
160-
expect(messages.join('|')).toBe('popup|evaluate');
161-
});
162133
it('should await navigating specified target', async({page, server}) => {
163134
const messages = [];
164135
server.setRoute('/empty.html', async (req, res) => {
@@ -254,5 +225,12 @@ describe('Auto waiting should not hang when', () => {
254225
popup.close();
255226
});
256227
});
228+
it('opening a popup', async function({page, server}) {
229+
await page.goto(server.EMPTY_PAGE);
230+
await Promise.all([
231+
page.waitForEvent('popup'),
232+
page.evaluate(() => window._popup = window.open(window.location.href)),
233+
]);
234+
});
257235
});
258236

0 commit comments

Comments
 (0)