mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
api(exposeBinding): allow handles in the binding result (#2970)
This commit is contained in:
parent
aa4c893b09
commit
198ecee875
34
src/page.ts
34
src/page.ts
@ -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(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);
|
||||
context.evaluateInternal(deliverErrorValue, { name, seq, error }).catch(logError(page._logger));
|
||||
}
|
||||
|
||||
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 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 deliverErrorValue(name: string, seq: number, value: any) {
|
||||
(window as any)[name]['callbacks'].get(seq).reject(value);
|
||||
(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(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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';
|
||||
@ -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) });
|
||||
}
|
||||
|
@ -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 }) {
|
||||
|
@ -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);
|
||||
const result = await page.evaluate(async function() {
|
||||
return { mul: await mul(9, 4), add: await add(9, 4), sub: await sub(9, 4) };
|
||||
await context.exposeBinding('addHandle', async ({ frame }, a, b) => {
|
||||
const handle = await frame.evaluateHandle(([a, b]) => a + b, [a, b]);
|
||||
return handle;
|
||||
});
|
||||
expect(result).toEqual({ mul: 36, add: 13, sub: 5 });
|
||||
const result = await page.evaluate(async function() {
|
||||
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, addHandle: 11 });
|
||||
await context.close();
|
||||
});
|
||||
it('should throw for duplicate registrations', async({browser, server}) => {
|
||||
|
@ -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');
|
||||
|
Loading…
x
Reference in New Issue
Block a user