Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
"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"
);
});