chore: fix internal binding (#4598)

This commit is contained in:
Joel Einbinder 2020-12-08 08:38:29 -08:00 committed by GitHub
parent 1e754a4d80
commit ea833daa89
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 5 deletions

View file

@ -128,7 +128,7 @@ export class CRPage implements PageDelegate {
async exposeBinding(binding: PageBinding) { async exposeBinding(binding: PageBinding) {
await this._forAllFrameSessions(frame => frame._initBinding(binding)); await this._forAllFrameSessions(frame => frame._initBinding(binding));
await Promise.all(this._page.frames().map(frame => frame._evaluateExpression(binding.source, false, {}).catch(e => {}))); await Promise.all(this._page.frames().map(frame => frame._evaluateExpression(binding.source, false, {}, binding.world).catch(e => {})));
} }
async updateExtraHTTPHeaders(): Promise<void> { async updateExtraHTTPHeaders(): Promise<void> {

View file

@ -879,7 +879,7 @@ export function waitForSelectorTask(selector: SelectorInfo, state: 'attached' |
export function dispatchEventTask(selector: SelectorInfo, type: string, eventInit: Object): SchedulableTask<undefined> { export function dispatchEventTask(selector: SelectorInfo, type: string, eventInit: Object): SchedulableTask<undefined> {
return injectedScript => injectedScript.evaluateHandle((injected, { parsed, type, eventInit }) => { return injectedScript => injectedScript.evaluateHandle((injected, { parsed, type, eventInit }) => {
return injected.pollRaf((progress, continuePolling) => { return injected.pollRaf<undefined>((progress, continuePolling) => {
const element = injected.querySelector(parsed, document); const element = injected.querySelector(parsed, document);
if (!element) if (!element)
return continuePolling; return continuePolling;

View file

@ -257,13 +257,13 @@ export class Page extends EventEmitter {
this._timeoutSettings.setDefaultTimeout(timeout); this._timeoutSettings.setDefaultTimeout(timeout);
} }
async exposeBinding(name: string, needsHandle: boolean, playwrightBinding: frames.FunctionWithSource) { async exposeBinding(name: string, needsHandle: boolean, playwrightBinding: frames.FunctionWithSource, world: types.World = 'main') {
const identifier = PageBinding.identifier(name, 'main'); const identifier = PageBinding.identifier(name, world);
if (this._pageBindings.has(identifier)) if (this._pageBindings.has(identifier))
throw new Error(`Function "${name}" has been already registered`); throw new Error(`Function "${name}" has been already registered`);
if (this._browserContext._pageBindings.has(identifier)) if (this._browserContext._pageBindings.has(identifier))
throw new Error(`Function "${name}" has been already registered in the browser context`); throw new Error(`Function "${name}" has been already registered in the browser context`);
const binding = new PageBinding(name, playwrightBinding, needsHandle, 'main'); const binding = new PageBinding(name, playwrightBinding, needsHandle, world);
this._pageBindings.set(identifier, binding); this._pageBindings.set(identifier, binding);
await this._delegate.exposeBinding(binding); await this._delegate.exposeBinding(binding);
} }

View file

@ -16,6 +16,7 @@
*/ */
import { it, expect } from './fixtures'; import { it, expect } from './fixtures';
import { attachFrame } from './utils';
it('exposeBinding should work', async ({browser}) => { it('exposeBinding should work', async ({browser}) => {
const context = await browser.newContext(); const context = await browser.newContext();
@ -236,3 +237,33 @@ it('should not result in unhandled rejection', async ({page}) => {
// Make a round-trip to be sure we did not throw immediately after closing. // Make a round-trip to be sure we did not throw immediately after closing.
expect(await page.evaluate('1 + 1').catch(e => e)).toBeInstanceOf(Error); expect(await page.evaluate('1 + 1').catch(e => e)).toBeInstanceOf(Error);
}); });
it('should work with internal bindings', (test, { mode, browserName }) => {
test.skip(mode !== 'default');
test.skip(browserName !== 'chromium');
}, async ({page, toImpl, server}) => {
const implPage: import('../src/server/page').Page = toImpl(page);
let foo;
await implPage.exposeBinding('foo', false, ({}, arg) => {
foo = arg;
}, 'utility');
expect(await page.evaluate('!!window.foo')).toBe(false);
expect(await implPage.mainFrame()._evaluateExpression('!!window.foo', false, {}, 'utility')).toBe(true);
expect(foo).toBe(undefined);
await implPage.mainFrame()._evaluateExpression('window.foo(123)', false, {}, 'utility');
expect(foo).toBe(123);
// should work after reload
await page.goto(server.EMPTY_PAGE);
expect(await page.evaluate('!!window.foo')).toBe(false);
await implPage.mainFrame()._evaluateExpression('window.foo(456)', false, {}, 'utility');
expect(foo).toBe(456);
// should work inside frames
const frame = await attachFrame(page, 'myframe', server.CROSS_PROCESS_PREFIX + '/empty.html');
expect(await frame.evaluate('!!window.foo')).toBe(false);
const implFrame: import('../src/server/frames').Frame = toImpl(frame);
await implFrame._evaluateExpression('window.foo(789)', false, {}, 'utility');
expect(foo).toBe(789);
});