chore: fix BiDi deserializer (#11264)
This commit is contained in:
parent
22aeff1eac
commit
0d4aab828a
@ -18,11 +18,6 @@ import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
|||||||
|
|
||||||
import {debugError} from '../common/util.js';
|
import {debugError} from '../common/util.js';
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
class UnsupportedTypeError extends Error {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
@ -45,43 +40,30 @@ export class BidiDeserializer {
|
|||||||
static deserializeLocalValue(result: Bidi.Script.RemoteValue): unknown {
|
static deserializeLocalValue(result: Bidi.Script.RemoteValue): unknown {
|
||||||
switch (result.type) {
|
switch (result.type) {
|
||||||
case 'array':
|
case 'array':
|
||||||
if (result.value) {
|
return result.value?.map(value => {
|
||||||
return result.value.map(value => {
|
return BidiDeserializer.deserializeLocalValue(value);
|
||||||
return BidiDeserializer.deserializeLocalValue(value);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'set':
|
case 'set':
|
||||||
if (result.value) {
|
return result.value?.reduce((acc: Set<unknown>, value) => {
|
||||||
return result.value.reduce((acc: Set<unknown>, value) => {
|
return acc.add(BidiDeserializer.deserializeLocalValue(value));
|
||||||
return acc.add(BidiDeserializer.deserializeLocalValue(value));
|
}, new Set());
|
||||||
}, new Set());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'object':
|
case 'object':
|
||||||
if (result.value) {
|
return result.value?.reduce((acc: Record<any, unknown>, tuple) => {
|
||||||
return result.value.reduce((acc: Record<any, unknown>, tuple) => {
|
const {key, value} = BidiDeserializer.deserializeTuple(tuple);
|
||||||
const {key, value} = BidiDeserializer.deserializeTuple(tuple);
|
acc[key as any] = value;
|
||||||
acc[key as any] = value;
|
return acc;
|
||||||
return acc;
|
}, {});
|
||||||
}, {});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'map':
|
case 'map':
|
||||||
if (result.value) {
|
return result.value?.reduce((acc: Map<unknown, unknown>, tuple) => {
|
||||||
return result.value?.reduce((acc: Map<unknown, unknown>, tuple) => {
|
const {key, value} = BidiDeserializer.deserializeTuple(tuple);
|
||||||
const {key, value} = BidiDeserializer.deserializeTuple(tuple);
|
return acc.set(key, value);
|
||||||
return acc.set(key, value);
|
}, new Map());
|
||||||
}, new Map());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'promise':
|
case 'promise':
|
||||||
return {};
|
return {};
|
||||||
case 'regexp':
|
case 'regexp':
|
||||||
return new RegExp(result.value.pattern, result.value.flags);
|
return new RegExp(result.value.pattern, result.value.flags);
|
||||||
case 'date':
|
case 'date':
|
||||||
return new Date(result.value);
|
return new Date(result.value);
|
||||||
|
|
||||||
case 'undefined':
|
case 'undefined':
|
||||||
return undefined;
|
return undefined;
|
||||||
case 'null':
|
case 'null':
|
||||||
@ -96,9 +78,8 @@ export class BidiDeserializer {
|
|||||||
return result.value;
|
return result.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnsupportedTypeError(
|
debugError(`Deserialization of type ${result.type} not supported.`);
|
||||||
`Deserialization of type ${result.type} not supported.`
|
return undefined;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static deserializeTuple([serializedKey, serializedValue]: [
|
static deserializeTuple([serializedKey, serializedValue]: [
|
||||||
@ -120,14 +101,6 @@ export class BidiDeserializer {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
return BidiDeserializer.deserializeLocalValue(result);
|
||||||
return BidiDeserializer.deserializeLocalValue(result);
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof UnsupportedTypeError) {
|
|
||||||
debugError(error.message);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -551,6 +551,24 @@
|
|||||||
"parameters": ["webDriverBiDi"],
|
"parameters": ["webDriverBiDi"],
|
||||||
"expectations": ["PASS"]
|
"expectations": ["PASS"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should fail for circular object",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["webDriverBiDi"],
|
||||||
|
"expectations": ["FAIL"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should replace symbols with undefined",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["cdp"],
|
||||||
|
"expectations": ["FAIL"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should return properly serialize objects with unknown type fields",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["cdp"],
|
||||||
|
"expectations": ["FAIL"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should throw if elementHandles are from other frames",
|
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should throw if elementHandles are from other frames",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
@ -107,14 +107,14 @@ describe('Evaluation specs', function () {
|
|||||||
await page.goto(server.PREFIX + '/global-var.html');
|
await page.goto(server.PREFIX + '/global-var.html');
|
||||||
expect(await page.evaluate('globalVar')).toBe(123);
|
expect(await page.evaluate('globalVar')).toBe(123);
|
||||||
});
|
});
|
||||||
it('should return undefined for objects with symbols', async () => {
|
it('should replace symbols with undefined', async () => {
|
||||||
const {page} = await getTestState();
|
const {page} = await getTestState();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await page.evaluate(() => {
|
await page.evaluate(() => {
|
||||||
return [Symbol('foo4')];
|
return [Symbol('foo4'), 'foo'];
|
||||||
})
|
})
|
||||||
).toBe(undefined);
|
).toEqual([undefined, 'foo']);
|
||||||
});
|
});
|
||||||
it('should work with function shorthands', async () => {
|
it('should work with function shorthands', async () => {
|
||||||
const {page} = await getTestState();
|
const {page} = await getTestState();
|
||||||
@ -455,6 +455,28 @@ describe('Evaluation specs', function () {
|
|||||||
});
|
});
|
||||||
expect(error.message).toContain('Error in promise');
|
expect(error.message).toContain('Error in promise');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return properly serialize objects with unknown type fields', async () => {
|
||||||
|
const {page} = await getTestState();
|
||||||
|
await page.setContent(
|
||||||
|
"<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=='>"
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await page.evaluate(async () => {
|
||||||
|
const image = document.querySelector('img')!;
|
||||||
|
const imageBitmap = await createImageBitmap(image);
|
||||||
|
|
||||||
|
return {
|
||||||
|
a: 'foo',
|
||||||
|
b: imageBitmap,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
a: 'foo',
|
||||||
|
b: undefined,
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Page.evaluateOnNewDocument', function () {
|
describe('Page.evaluateOnNewDocument', function () {
|
||||||
|
Loading…
Reference in New Issue
Block a user