Skip to content

Commit

Permalink
api(exposeBinding): allow handles in the binding result (#2970)
Browse files Browse the repository at this point in the history
  • Loading branch information
dgozman authored Jul 16, 2020
1 parent aa4c893 commit 198ecee
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 21 deletions.
30 changes: 14 additions & 16 deletions src/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -686,36 +686,34 @@ export class PageBinding {

static async dispatch(page: Page, payload: string, context: dom.FrameExecutionContext) {
const {name, seq, args} = JSON.parse(payload);
let expression = null;
try {
let binding = page._pageBindings.get(name);
if (!binding)
binding = page._browserContext._pageBindings.get(name);
const result = await binding!.playwrightFunction({ frame: context.frame, page, context: page._browserContext }, ...args);
expression = helper.evaluationString(deliverResult, name, seq, result);
context.evaluateInternal(deliverResult, { name, seq, result }).catch(logError(page._logger));
} catch (error) {
if (error instanceof Error)
expression = helper.evaluationString(deliverError, name, seq, error.message, error.stack);
context.evaluateInternal(deliverError, { name, seq, message: error.message, stack: error.stack }).catch(logError(page._logger));
else
expression = helper.evaluationString(deliverErrorValue, name, seq, error);
context.evaluateInternal(deliverErrorValue, { name, seq, error }).catch(logError(page._logger));
}
context.evaluateInternal(expression).catch(logError(page._logger));

function deliverResult(name: string, seq: number, result: any) {
(window as any)[name]['callbacks'].get(seq).resolve(result);
(window as any)[name]['callbacks'].delete(seq);
function deliverResult(arg: { name: string, seq: number, result: any }) {
(window as any)[arg.name]['callbacks'].get(arg.seq).resolve(arg.result);
(window as any)[arg.name]['callbacks'].delete(arg.seq);
}

function deliverError(name: string, seq: number, message: string, stack: string) {
const error = new Error(message);
error.stack = stack;
(window as any)[name]['callbacks'].get(seq).reject(error);
(window as any)[name]['callbacks'].delete(seq);
function deliverError(arg: { name: string, seq: number, message: string, stack: string | undefined }) {
const error = new Error(arg.message);
error.stack = arg.stack;
(window as any)[arg.name]['callbacks'].get(arg.seq).reject(error);
(window as any)[arg.name]['callbacks'].delete(arg.seq);
}

function deliverErrorValue(name: string, seq: number, value: any) {
(window as any)[name]['callbacks'].get(seq).reject(value);
(window as any)[name]['callbacks'].delete(seq);
function deliverErrorValue(arg: { name: string, seq: number, error: any }) {
(window as any)[arg.name]['callbacks'].get(arg.seq).reject(arg.error);
(window as any)[arg.name]['callbacks'].delete(arg.seq);
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/rpc/client/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { ElementHandle } from './elementHandle';
import { Worker } from './worker';
import { Frame, FunctionWithSource, GotoOptions } from './frame';
import { Keyboard, Mouse } from './input';
import { Func1, FuncOn, SmartHandle } from './jsHandle';
import { Func1, FuncOn, SmartHandle, serializeArgument } from './jsHandle';
import { Request, Response, Route, RouteHandler } from './network';
import { FileChooser } from './fileChooser';
import { Buffer } from 'buffer';
Expand Down Expand Up @@ -535,7 +535,8 @@ export class BindingCall extends ChannelOwner<BindingCallChannel, BindingCallIni
page: frame._page!,
frame
};
this._channel.resolve({ result: await func(source, ...this._initializer.args) });
const result = await func(source, ...this._initializer.args);
this._channel.resolve({ result: serializeArgument(result) });
} catch (e) {
this._channel.reject({ error: serializeError(e) });
}
Expand Down
2 changes: 1 addition & 1 deletion src/rpc/server/pageDispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ export class BindingCallDispatcher extends Dispatcher<{}, BindingCallInitializer
}

resolve(params: { result: any }) {
this._resolve!(params.result);
this._resolve!(parseArgument(params.result));
}

reject(params: { error: types.Error }) {
Expand Down
8 changes: 6 additions & 2 deletions test/browsercontext.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -378,10 +378,14 @@ describe('BrowserContext.exposeFunction', () => {
const page = await context.newPage();
await page.exposeFunction('mul', (a, b) => a * b);
await context.exposeFunction('sub', (a, b) => a - b);
await context.exposeBinding('addHandle', async ({ frame }, a, b) => {
const handle = await frame.evaluateHandle(([a, b]) => a + b, [a, b]);
return handle;
});
const result = await page.evaluate(async function() {
return { mul: await mul(9, 4), add: await add(9, 4), sub: await sub(9, 4) };
return { mul: await mul(9, 4), add: await add(9, 4), sub: await sub(9, 4), addHandle: await addHandle(5, 6) };
});
expect(result).toEqual({ mul: 36, add: 13, sub: 5 });
expect(result).toEqual({ mul: 36, add: 13, sub: 5, addHandle: 11 });
await context.close();
});
it('should throw for duplicate registrations', async({browser, server}) => {
Expand Down
15 changes: 15 additions & 0 deletions test/page.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,21 @@ describe('Page.exposeFunction', function() {
});
expect(result).toBe(36);
});
it('should work with handles and complex objects', async({page, server}) => {
const fooHandle = await page.evaluateHandle(() => {
window.fooValue = { bar: 2 };
return window.fooValue;
});
await page.exposeFunction('handle', () => {
return [{ foo: fooHandle }];
});
const equals = await page.evaluate(async function() {
const value = await handle();
const [{ foo }] = value;
return foo === window.fooValue;
});
expect(equals).toBe(true);
});
it('should throw exception in page context', async({page, server}) => {
await page.exposeFunction('woof', function() {
throw new Error('WOOF WOOF');
Expand Down

0 comments on commit 198ecee

Please sign in to comment.