mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
fix(handles): always create proper handle type (#4879)
This commit is contained in:
parent
31ffeb32e3
commit
c4df522555
@ -176,6 +176,8 @@ export class DispatcherConnection {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const validated = this._validateParams(dispatcher._type, method, params);
|
const validated = this._validateParams(dispatcher._type, method, params);
|
||||||
|
if (typeof (dispatcher as any)[method] !== 'function')
|
||||||
|
throw new Error(`Mismatching dispatcher: "${dispatcher._type}" does not implement "${method}"`);
|
||||||
const result = await (dispatcher as any)[method](validated, this._validateMetadata(metadata));
|
const result = await (dispatcher as any)[method](validated, this._validateMetadata(metadata));
|
||||||
this.onmessage({ id, result: this._replaceDispatchersWithGuids(result) });
|
this.onmessage({ id, result: this._replaceDispatchersWithGuids(result) });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -23,6 +23,7 @@ import { parseSerializedValue, serializeValue } from '../protocol/serializers';
|
|||||||
export class JSHandleDispatcher extends Dispatcher<js.JSHandle, channels.JSHandleInitializer> implements channels.JSHandleChannel {
|
export class JSHandleDispatcher extends Dispatcher<js.JSHandle, channels.JSHandleInitializer> implements channels.JSHandleChannel {
|
||||||
|
|
||||||
constructor(scope: DispatcherScope, jsHandle: js.JSHandle) {
|
constructor(scope: DispatcherScope, jsHandle: js.JSHandle) {
|
||||||
|
// Do not call this directly, use createHandle() instead.
|
||||||
super(scope, jsHandle, jsHandle.asElement() ? 'ElementHandle' : 'JSHandle', {
|
super(scope, jsHandle, jsHandle.asElement() ? 'ElementHandle' : 'JSHandle', {
|
||||||
preview: jsHandle.toString(),
|
preview: jsHandle.toString(),
|
||||||
});
|
});
|
||||||
@ -47,7 +48,7 @@ export class JSHandleDispatcher extends Dispatcher<js.JSHandle, channels.JSHandl
|
|||||||
const map = await this._object.getProperties();
|
const map = await this._object.getProperties();
|
||||||
const properties = [];
|
const properties = [];
|
||||||
for (const [name, value] of map)
|
for (const [name, value] of map)
|
||||||
properties.push({ name, value: new JSHandleDispatcher(this._scope, value) });
|
properties.push({ name, value: createHandle(this._scope, value) });
|
||||||
return { properties };
|
return { properties };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ import { DialogDispatcher } from './dialogDispatcher';
|
|||||||
import { DownloadDispatcher } from './downloadDispatcher';
|
import { DownloadDispatcher } from './downloadDispatcher';
|
||||||
import { FrameDispatcher } from './frameDispatcher';
|
import { FrameDispatcher } from './frameDispatcher';
|
||||||
import { RequestDispatcher, ResponseDispatcher, RouteDispatcher, WebSocketDispatcher } from './networkDispatchers';
|
import { RequestDispatcher, ResponseDispatcher, RouteDispatcher, WebSocketDispatcher } from './networkDispatchers';
|
||||||
import { serializeResult, parseArgument, JSHandleDispatcher } from './jsHandleDispatcher';
|
import { serializeResult, parseArgument } from './jsHandleDispatcher';
|
||||||
import { ElementHandleDispatcher, createHandle } from './elementHandlerDispatcher';
|
import { ElementHandleDispatcher, createHandle } from './elementHandlerDispatcher';
|
||||||
import { FileChooser } from '../server/fileChooser';
|
import { FileChooser } from '../server/fileChooser';
|
||||||
import { CRCoverage } from '../server/chromium/crCoverage';
|
import { CRCoverage } from '../server/chromium/crCoverage';
|
||||||
@ -274,7 +274,7 @@ export class BindingCallDispatcher extends Dispatcher<{}, channels.BindingCallIn
|
|||||||
frame: lookupDispatcher<FrameDispatcher>(source.frame),
|
frame: lookupDispatcher<FrameDispatcher>(source.frame),
|
||||||
name,
|
name,
|
||||||
args: needsHandle ? undefined : args.map(serializeResult),
|
args: needsHandle ? undefined : args.map(serializeResult),
|
||||||
handle: needsHandle ? new JSHandleDispatcher(scope, args[0] as JSHandle) : undefined,
|
handle: needsHandle ? createHandle(scope, args[0] as JSHandle) : undefined,
|
||||||
});
|
});
|
||||||
this._promise = new Promise((resolve, reject) => {
|
this._promise = new Promise((resolve, reject) => {
|
||||||
this._resolve = resolve;
|
this._resolve = resolve;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { it, expect } from './fixtures';
|
import { it, expect } from './fixtures';
|
||||||
|
import type { ElementHandle } from '..';
|
||||||
|
|
||||||
it('should work', async ({page}) => {
|
it('should work', async ({page}) => {
|
||||||
const aHandle = await page.evaluateHandle(() => ({
|
const aHandle = await page.evaluateHandle(() => ({
|
||||||
@ -94,3 +95,12 @@ it('getProperties should return even non-own properties', async ({page}) => {
|
|||||||
expect(await properties.get('a').jsonValue()).toBe('1');
|
expect(await properties.get('a').jsonValue()).toBe('1');
|
||||||
expect(await properties.get('b').jsonValue()).toBe('2');
|
expect(await properties.get('b').jsonValue()).toBe('2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('getProperties should work with elements', async ({page}) => {
|
||||||
|
await page.setContent(`<div>Hello</div>`);
|
||||||
|
const handle = await page.evaluateHandle(() => ({ body: document.body }));
|
||||||
|
const properties = await handle.getProperties();
|
||||||
|
const body = properties.get('body') as ElementHandle;
|
||||||
|
expect(body).toBeTruthy();
|
||||||
|
expect(await body.textContent()).toBe('Hello');
|
||||||
|
});
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
import { it, expect } from './fixtures';
|
import { it, expect } from './fixtures';
|
||||||
import { attachFrame } from './utils';
|
import { attachFrame } from './utils';
|
||||||
|
import type { ElementHandle } from '..';
|
||||||
|
|
||||||
it('exposeBinding should work', async ({page}) => {
|
it('exposeBinding should work', async ({page}) => {
|
||||||
let bindingSource;
|
let bindingSource;
|
||||||
@ -264,3 +265,19 @@ it('should work with internal bindings', (test, { mode, browserName }) => {
|
|||||||
expect(foo).toBe(789);
|
expect(foo).toBe(789);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('exposeBinding(handle) should work with element handles', async ({ page}) => {
|
||||||
|
let cb;
|
||||||
|
const promise = new Promise(f => cb = f);
|
||||||
|
await page.exposeBinding('clicked', async (source, element: ElementHandle) => {
|
||||||
|
cb(await element.innerText().catch(e => e));
|
||||||
|
}, { handle: true });
|
||||||
|
await page.goto('about:blank');
|
||||||
|
await page.setContent(`
|
||||||
|
<script>
|
||||||
|
document.addEventListener('click', event => window.clicked(event.target));
|
||||||
|
</script>
|
||||||
|
<div id="a1">Click me</div>
|
||||||
|
`);
|
||||||
|
await page.click('#a1');
|
||||||
|
expect(await promise).toBe('Click me');
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user