chore: fix BiDi deserializer (#11264)

This commit is contained in:
Nikolay Vitkov 2023-10-30 13:02:04 +01:00 committed by GitHub
parent 22aeff1eac
commit 0d4aab828a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 48 deletions

View File

@ -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;
}
} }
} }

View File

@ -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"],

View File

@ -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 () {