285 lines
8.1 KiB
JavaScript
285 lines
8.1 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
const TEST_DOC = toDataURL("default-test-page");
|
|
|
|
add_task(async function FunctionDeclarationMissing({ client }) {
|
|
const { Runtime } = client;
|
|
await Assert.rejects(
|
|
Runtime.callFunctionOn(),
|
|
err => err.message.includes("functionDeclaration: string value expected"),
|
|
"functionDeclaration: string value expected"
|
|
);
|
|
});
|
|
|
|
add_task(async function functionDeclarationInvalidTypes({ client }) {
|
|
const { Runtime } = client;
|
|
|
|
const { id: executionContextId } = await enableRuntime(client);
|
|
|
|
for (const functionDeclaration of [null, true, 1, [], {}]) {
|
|
await Assert.rejects(
|
|
Runtime.callFunctionOn({ functionDeclaration, executionContextId }),
|
|
err => err.message.includes("functionDeclaration: string value expected"),
|
|
"functionDeclaration: string value expected"
|
|
);
|
|
}
|
|
});
|
|
|
|
add_task(async function functionDeclarationGetCurrentLocation({ client }) {
|
|
const { Runtime } = client;
|
|
|
|
await loadURL(TEST_DOC);
|
|
const { id: executionContextId } = await enableRuntime(client);
|
|
|
|
const { result } = await Runtime.callFunctionOn({
|
|
functionDeclaration: "() => location.href",
|
|
executionContextId,
|
|
});
|
|
is(result.value, TEST_DOC, "Works against the test page");
|
|
});
|
|
|
|
add_task(async function argumentsInvalidTypes({ client }) {
|
|
const { Runtime } = client;
|
|
|
|
const { id: executionContextId } = await enableRuntime(client);
|
|
|
|
for (const args of [null, true, 1, "foo", {}]) {
|
|
await Assert.rejects(
|
|
Runtime.callFunctionOn({
|
|
functionDeclaration: "",
|
|
arguments: args,
|
|
executionContextId,
|
|
}),
|
|
err => err.message.includes("arguments: array value expected"),
|
|
"arguments: array value expected"
|
|
);
|
|
}
|
|
});
|
|
|
|
add_task(async function argumentsPrimitiveTypes({ client }) {
|
|
const { Runtime } = client;
|
|
|
|
const { id: executionContextId } = await enableRuntime(client);
|
|
|
|
for (const args of [null, true, 1, "foo", {}]) {
|
|
await Assert.rejects(
|
|
Runtime.callFunctionOn({
|
|
functionDeclaration: "",
|
|
arguments: args,
|
|
executionContextId,
|
|
}),
|
|
err => err.message.includes("arguments: array value expected"),
|
|
"arguments: array value expected"
|
|
);
|
|
}
|
|
});
|
|
|
|
add_task(async function executionContextIdNorObjectIdSpecified({ client }) {
|
|
const { Runtime } = client;
|
|
|
|
await Assert.rejects(
|
|
Runtime.callFunctionOn({
|
|
functionDeclaration: "",
|
|
}),
|
|
err =>
|
|
err.message.includes(
|
|
"Either objectId or executionContextId must be specified"
|
|
),
|
|
"Either objectId or executionContextId must be specified"
|
|
);
|
|
});
|
|
|
|
add_task(async function executionContextIdInvalidTypes({ client }) {
|
|
const { Runtime } = client;
|
|
|
|
for (const executionContextId of [null, true, "foo", [], {}]) {
|
|
await Assert.rejects(
|
|
Runtime.callFunctionOn({
|
|
functionDeclaration: "",
|
|
executionContextId,
|
|
}),
|
|
err => err.message.includes("executionContextId: number value expected"),
|
|
"executionContextId: number value expected"
|
|
);
|
|
}
|
|
});
|
|
|
|
add_task(async function executionContextIdInvalidValue({ client }) {
|
|
const { Runtime } = client;
|
|
await Assert.rejects(
|
|
Runtime.callFunctionOn({
|
|
functionDeclaration: "",
|
|
executionContextId: -1,
|
|
}),
|
|
err => err.message.includes("Cannot find context with specified id"),
|
|
"Cannot find context with specified id"
|
|
);
|
|
});
|
|
|
|
add_task(async function objectIdInvalidTypes({ client }) {
|
|
const { Runtime } = client;
|
|
|
|
for (const objectId of [null, true, 1, [], {}]) {
|
|
await Assert.rejects(
|
|
Runtime.callFunctionOn({ functionDeclaration: "", objectId }),
|
|
err => err.message.includes("objectId: string value expected"),
|
|
"objectId: string value expected"
|
|
);
|
|
}
|
|
});
|
|
|
|
add_task(async function objectId({ client }) {
|
|
const { Runtime } = client;
|
|
|
|
const { id: executionContextId } = await enableRuntime(client);
|
|
|
|
// First create an object
|
|
const { result } = await Runtime.callFunctionOn({
|
|
functionDeclaration: "() => ({ foo: 42 })",
|
|
executionContextId,
|
|
});
|
|
|
|
is(result.type, "object", "The type is correct");
|
|
is(result.subtype, undefined, "The subtype is undefined for objects");
|
|
ok(!!result.objectId, "Got an object id");
|
|
|
|
// Then apply a method on this object
|
|
const { result: result2 } = await Runtime.callFunctionOn({
|
|
functionDeclaration: "function () { return this.foo; }",
|
|
executionContextId,
|
|
objectId: result.objectId,
|
|
});
|
|
|
|
is(result2.type, "number", "The type is correct");
|
|
is(result2.subtype, undefined, "The subtype is undefined for numbers");
|
|
is(result2.value, 42, "Expected value returned");
|
|
});
|
|
|
|
add_task(async function objectIdArgumentReference({ client }) {
|
|
const { Runtime } = client;
|
|
|
|
const { id: executionContextId } = await enableRuntime(client);
|
|
|
|
// First create a remote JS object
|
|
const { result } = await Runtime.callFunctionOn({
|
|
functionDeclaration: "() => ({ foo: 1 })",
|
|
executionContextId,
|
|
});
|
|
|
|
is(result.type, "object", "The type is correct");
|
|
is(result.subtype, undefined, "The subtype is undefined for objects");
|
|
ok(!!result.objectId, "Got an object id");
|
|
|
|
// Then increment the `foo` attribute of this JS object,
|
|
// while returning this attribute value
|
|
const { result: result2 } = await Runtime.callFunctionOn({
|
|
functionDeclaration: "arg => ++arg.foo",
|
|
arguments: [{ objectId: result.objectId }],
|
|
executionContextId,
|
|
});
|
|
|
|
Assert.deepEqual(
|
|
result2,
|
|
{
|
|
type: "number",
|
|
value: 2,
|
|
},
|
|
"The result has the expected type and value"
|
|
);
|
|
|
|
// Finally, try to pass this JS object and get it back. Ensure that it
|
|
// returns the same object id. Also increment the attribute again.
|
|
const { result: result3 } = await Runtime.callFunctionOn({
|
|
functionDeclaration: "arg => { arg.foo++; return arg; }",
|
|
arguments: [{ objectId: result.objectId }],
|
|
executionContextId,
|
|
});
|
|
|
|
is(result3.type, "object", "The type is correct");
|
|
is(result3.subtype, undefined, "The subtype is undefined for objects");
|
|
// Remote objects don't have unique ids. So you may have multiple object ids
|
|
// that reference the same remote object
|
|
ok(!!result3.objectId, "Got an object id");
|
|
isnot(result3.objectId, result.objectId, "The object id is different");
|
|
|
|
// Assert that we can still access this object and that its foo attribute
|
|
// has been incremented. Use the second object id we got from previous call
|
|
// to callFunctionOn.
|
|
const { result: result4 } = await Runtime.callFunctionOn({
|
|
functionDeclaration: "arg => arg.foo",
|
|
arguments: [{ objectId: result3.objectId }],
|
|
executionContextId,
|
|
});
|
|
|
|
Assert.deepEqual(
|
|
result4,
|
|
{
|
|
type: "number",
|
|
value: 3,
|
|
},
|
|
"The result has the expected type and value"
|
|
);
|
|
});
|
|
|
|
add_task(async function exceptionDetailsJavascriptError({ client }) {
|
|
const { Runtime } = client;
|
|
|
|
const { id: executionContextId } = await enableRuntime(client);
|
|
|
|
const { exceptionDetails } = await Runtime.callFunctionOn({
|
|
functionDeclaration: "doesNotExists()",
|
|
executionContextId,
|
|
});
|
|
|
|
Assert.deepEqual(
|
|
exceptionDetails,
|
|
{
|
|
text: "doesNotExists is not defined",
|
|
},
|
|
"Javascript error is passed to the client"
|
|
);
|
|
});
|
|
|
|
add_task(async function exceptionDetailsThrowError({ client }) {
|
|
const { Runtime } = client;
|
|
|
|
const { id: executionContextId } = await enableRuntime(client);
|
|
|
|
const { exceptionDetails } = await Runtime.callFunctionOn({
|
|
functionDeclaration: "() => { throw new Error('foo') }",
|
|
executionContextId,
|
|
});
|
|
|
|
Assert.deepEqual(
|
|
exceptionDetails,
|
|
{
|
|
text: "foo",
|
|
},
|
|
"Exception details are passed to the client"
|
|
);
|
|
});
|
|
|
|
add_task(async function exceptionDetailsThrowValue({ client }) {
|
|
const { Runtime } = client;
|
|
|
|
const { id: executionContextId } = await enableRuntime(client);
|
|
|
|
const { exceptionDetails } = await Runtime.callFunctionOn({
|
|
functionDeclaration: "() => { throw 'foo' }",
|
|
executionContextId,
|
|
});
|
|
|
|
Assert.deepEqual(
|
|
exceptionDetails,
|
|
{
|
|
exception: {
|
|
type: "string",
|
|
value: "foo",
|
|
},
|
|
},
|
|
"Exception details are passed as a RemoteObject"
|
|
);
|
|
});
|