Bug 1739976 - [webdriver-bidi] Add basic support for payload deserialization. r=webdriver-reviewers,jgraham,jdescottes

Differential Revision: https://phabricator.services.mozilla.com/D133677
This commit is contained in:
Henrik Skupin 2021-12-15 22:26:13 +00:00
Родитель a6679a0579
Коммит a1b9267fa5
3 изменённых файлов: 175 добавлений и 18 удалений

Просмотреть файл

@ -4,13 +4,15 @@
"use strict";
var EXPORTED_SYMBOLS = ["serialize"];
var EXPORTED_SYMBOLS = ["deserialize", "serialize"];
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
XPCOMUtils.defineLazyModuleGetters(this, {
assert: "chrome://remote/content/shared/webdriver/Assert.jsm",
InvalidArgumentError: "chrome://remote/content/shared/webdriver/Errors.jsm",
Log: "chrome://remote/content/shared/Log.jsm",
});
@ -18,6 +20,71 @@ XPCOMUtils.defineLazyGetter(this, "logger", () =>
Log.get(Log.TYPES.WEBDRIVER_BIDI)
);
/**
* Deserialize a local value.
*
* @see https://w3c.github.io/webdriver-bidi/#deserialize-local-value
*
* @param {Object} serializedValue
* Value of any type to be deserialized.
*
* @returns {Object} Deserialized representation of the value.
*/
function deserialize(serializedValue) {
const { objectId, type, value } = serializedValue;
if (type !== undefined) {
assert.string(type, `Expected "type" to be a string, got ${type}`);
}
// With an objectId present deserialize as remote reference.
if (objectId !== undefined) {
assert.string(
objectId,
`Expected "objectId" to be a string, got ${objectId}`
);
// TODO: Implement deserialization of remote references (bug 1693838)
logger.warn(`Unsupported type remote reference with objectId ${objectId}`);
return undefined;
}
// Primitive protocol values
switch (type) {
case "undefined":
return undefined;
case "null":
return null;
case "string":
assert.string(value, `Expected "value" to be a string, got ${value}`);
return value;
case "number":
// If value is already a number return its value.
if (typeof value === "number") {
return value;
}
// Otherwise it has to be one of the special strings
assert.in(value, ["NaN", "-0", "+Infinity", "-Infinity"]);
return Number(value);
case "boolean":
assert.boolean(value, `Expected "value" to be a boolean, got ${value}`);
return value;
case "bigint":
assert.string(value, `Expected "value" to be a string, got ${value}`);
try {
return BigInt(value);
} catch (e) {
throw new InvalidArgumentError(
`Failed to deserialize value as BigInt: ${value}`
);
}
}
logger.warn(`Unsupported type for local value ${type}`);
return undefined;
}
/**
* Serialize a value as a remote value.
*
@ -31,31 +98,25 @@ XPCOMUtils.defineLazyGetter(this, "logger", () =>
function serialize(value /*, maxDepth, nodeDetails, knownObjects */) {
const type = typeof value;
let remoteValue;
// Primitive protocol values
if (type == "undefined") {
remoteValue = { type };
return { type };
} else if (Object.is(value, null)) {
remoteValue = { type: "null" };
// Special numbers
return { type: "null" };
} else if (Object.is(value, NaN)) {
remoteValue = { type: "number", value: "NaN" };
return { type: "number", value: "NaN" };
} else if (Object.is(value, -0)) {
remoteValue = { type: "number", value: "-0" };
return { type: "number", value: "-0" };
} else if (Object.is(value, Infinity)) {
remoteValue = { type: "number", value: "+Infinity" };
return { type: "number", value: "+Infinity" };
} else if (Object.is(value, -Infinity)) {
remoteValue = { type: "number", value: "-Infinity" };
return { type: "number", value: "-Infinity" };
} else if (type == "bigint") {
remoteValue = { type, value: value.toString() };
// values that are directly represented in the serialization
return { type, value: value.toString() };
} else if (["boolean", "number", "string"].includes(type)) {
remoteValue = { type, value };
} else {
logger.warn(`Unsupported type for remote value: ${value.toString()}`);
return { type, value };
}
return remoteValue;
logger.warn(`Unsupported type for remote value: ${value.toString()}`);
return undefined;
}

Просмотреть файл

@ -0,0 +1,95 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const PRIMITIVE_TYPES = [
{ value: undefined, serialized: { type: "undefined" } },
{ value: null, serialized: { type: "null" } },
{ value: "foo", serialized: { type: "string", value: "foo" } },
{ value: Number.NaN, serialized: { type: "number", value: "NaN" } },
{ value: -0, serialized: { type: "number", value: "-0" } },
{
value: Number.POSITIVE_INFINITY,
serialized: { type: "number", value: "+Infinity" },
},
{
value: Number.NEGATIVE_INFINITY,
serialized: { type: "number", value: "-Infinity" },
},
{ value: 42, serialized: { type: "number", value: 42 } },
{ value: false, serialized: { type: "boolean", value: false } },
{ value: 42n, serialized: { type: "bigint", value: "42" } },
];
const { deserialize, serialize } = ChromeUtils.import(
"chrome://remote/content/webdriver-bidi/RemoteValue.jsm"
);
add_test(function test_deserializePrimitiveTypes() {
for (const type of PRIMITIVE_TYPES) {
const { value: expectedValue, serialized } = type;
const value = deserialize(serialized);
info(`Checking '${type}'`);
if (serialized.value == "NaN") {
ok(Number.isNaN(value), `Got expected value for ${serialized}`);
} else {
Assert.strictEqual(
value,
expectedValue,
`Got expected value for ${serialized}`
);
}
}
run_next_test();
});
add_test(function test_deserializePrimitiveTypesInvalidValues() {
const invalidValues = [
{ type: "bigint", values: [undefined, null, false, "foo", [], {}] },
{ type: "boolean", values: [undefined, null, 42, "foo", [], {}] },
{
type: "number",
values: [undefined, null, false, "43", [], {}],
},
{ type: "string", values: [undefined, null, false, 42, [], {}] },
];
for (const invalidValue of invalidValues) {
const { type, values } = invalidValue;
for (const value of values) {
info(`Checking '${type}' with value ${value}`);
Assert.throws(
() => deserialize({ type, value }),
/InvalidArgument/,
`Got expected error for type ${type} and value ${value}`
);
}
}
run_next_test();
});
add_test(function test_serializePrimitiveTypes() {
for (const type of PRIMITIVE_TYPES) {
const { value, serialized } = type;
const serializedValue = serialize(value);
for (const prop in serialized) {
info(`Checking '${serialized.type}'`);
Assert.strictEqual(
serializedValue[prop],
serialized[prop],
`Got expected value for property ${prop}`
);
}
}
run_next_test();
});

Просмотреть файл

@ -2,4 +2,5 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
[test_RemoteValue.js]
[test_WebDriverBiDiConnection.js]