Skip to content

Commit 1b84ec9

Browse files
authored
fix(binding): dispatch binding after the page has been initialized (#2938)
... but not after it was closed.
1 parent 89ca2db commit 1b84ec9

File tree

6 files changed

+67
-9
lines changed

6 files changed

+67
-9
lines changed

src/chromium/crPage.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -643,9 +643,11 @@ class FrameSession {
643643
]);
644644
}
645645

646-
_onBindingCalled(event: Protocol.Runtime.bindingCalledPayload) {
646+
async _onBindingCalled(event: Protocol.Runtime.bindingCalledPayload) {
647647
const context = this._contextIdToContext.get(event.executionContextId)!;
648-
this._page._onBindingCalled(event.payload, context);
648+
const pageOrError = await this._crPage.pageOrError();
649+
if (!(pageOrError instanceof Error))
650+
this._page._onBindingCalled(event.payload, context);
649651
}
650652

651653
_onDialog(event: Protocol.Page.javascriptDialogOpeningPayload) {

src/firefox/ffPage.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,11 @@ export class FFPage implements PageDelegate {
195195
params.defaultValue));
196196
}
197197

198-
_onBindingCalled(event: Protocol.Page.bindingCalledPayload) {
198+
async _onBindingCalled(event: Protocol.Page.bindingCalledPayload) {
199199
const context = this._contextIdToContext.get(event.executionContextId)!;
200-
this._page._onBindingCalled(event.payload, context);
200+
const pageOrError = await this.pageOrError();
201+
if (!(pageOrError instanceof Error))
202+
this._page._onBindingCalled(event.payload, context);
201203
}
202204

203205
async _onFileChooserOpened(payload: Protocol.Page.fileChooserOpenedPayload) {

src/page.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,8 @@ export class Page extends EventEmitter {
293293
}
294294

295295
async _onBindingCalled(payload: string, context: dom.FrameExecutionContext) {
296+
if (this._disconnected || this._closedState === 'closed')
297+
return;
296298
await PageBinding.dispatch(this, payload, context);
297299
}
298300

src/webkit/wkPage.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,10 @@ export class WKPage implements PageDelegate {
455455
if (level === 'debug' && parameters && parameters[0].value === BINDING_CALL_MESSAGE) {
456456
const parsedObjectId = JSON.parse(parameters[1].objectId!);
457457
const context = this._contextIdToContext.get(parsedObjectId.injectedScriptId)!;
458-
this._page._onBindingCalled(parameters[2].value, context);
458+
this.pageOrError().then(pageOrError => {
459+
if (!(pageOrError instanceof Error))
460+
this._page._onBindingCalled(parameters[2].value, context);
461+
});
459462
return;
460463
}
461464
if (level === 'error' && source === 'javascript') {

test/browsercontext.spec.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ describe('BrowserContext', function() {
131131
});
132132
it('should not report frameless pages on error', async({browser, server}) => {
133133
const context = await browser.newContext();
134-
page = await context.newPage();
134+
const page = await context.newPage();
135135
server.setRoute('/empty.html', (req, res) => {
136136
res.end(`<a href="${server.EMPTY_PAGE}" target="_blank">Click me</a>`);
137137
});
@@ -145,6 +145,22 @@ describe('BrowserContext', function() {
145145
expect(popup.isClosed()).toBeTruthy();
146146
expect(popup.mainFrame()).toBeTruthy();
147147
}
148+
});
149+
it('should not call binding on errored pages', async({browser, server}) => {
150+
const context = await browser.newContext();
151+
let gotBinding = 0;
152+
await context.exposeFunction('add', (a, b) => {
153+
gotBinding++;
154+
return a + b;
155+
});
156+
const page = await context.newPage();
157+
server.setRoute('/empty.html', (req, res) => {
158+
res.end(`<script>window.add(2, 3)</script><a href="${server.EMPTY_PAGE}" target="_blank">Click me</a>`);
159+
});
160+
await page.goto(server.EMPTY_PAGE);
161+
await page.click('"Click me"');
162+
await context.close();
163+
expect(gotBinding).toBe(1);
148164
})
149165
});
150166

test/popup.spec.js

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,18 +200,51 @@ describe('window.open', function() {
200200
expect(await popup.evaluate('injected')).toBe(123);
201201
await context.close();
202202
});
203-
204203
it('should expose function from browser context', async function({browser, server}) {
205204
const context = await browser.newContext();
206-
await context.exposeFunction('add', (a, b) => a + b);
205+
const messages = [];
206+
await context.exposeFunction('add', (a, b) => {
207+
messages.push('binding');
208+
return a + b;
209+
});
207210
const page = await context.newPage();
211+
context.on('page', () => messages.push('page'));
208212
await page.goto(server.EMPTY_PAGE);
209213
const added = await page.evaluate(async () => {
210214
const win = window.open('about:blank');
211215
return win.add(9, 4);
212216
});
213217
await context.close();
214218
expect(added).toBe(13);
219+
expect(messages.join('|')).toBe('page|binding');
220+
});
221+
it('should not dispatch binding on a closed page', async function({browser, server}) {
222+
const context = await browser.newContext();
223+
const messages = [];
224+
await context.exposeFunction('add', (a, b) => {
225+
messages.push('binding');
226+
return a + b;
227+
});
228+
const page = await context.newPage();
229+
await page.goto(server.EMPTY_PAGE);
230+
await Promise.all([
231+
page.waitForEvent('popup').then(popup => {
232+
if (popup.isClosed())
233+
messages.push('alreadyclosed');
234+
else
235+
return popup.waitForEvent('close').then(() => messages.push('close'));
236+
}),
237+
page.evaluate(async () => {
238+
const win = window.open('about:blank');
239+
win.add(9, 4);
240+
win.close();
241+
}),
242+
]);
243+
await context.close();
244+
if (FFOX)
245+
expect(messages.join('|')).toBe('alreadyclosed');
246+
else
247+
expect(messages.join('|')).toBe('binding|close');
215248
});
216249
});
217250

@@ -252,7 +285,7 @@ describe('Page.Events.Popup', function() {
252285
expect(popup).toBeTruthy();
253286
await context.close();
254287
});
255-
it('should emit for immediately closed popups', async({browser, server}) => {
288+
it('should emit for immediately closed popups 2', async({browser, server}) => {
256289
const context = await browser.newContext();
257290
const page = await context.newPage();
258291
await page.goto(server.EMPTY_PAGE);

0 commit comments

Comments
 (0)