/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
"use strict";
function ChromeTask_ChromeScript() {
"use strict";
const {
Assert: AssertCls } = ChromeUtils.importESModule(
"resource://testing-common/Assert.sys.mjs"
);
addMessageListener(
"chrome-task:spawn", async
function (aData) {
let id = aData.id;
let source = aData.runnable ||
"()=>{}";
function getStack(aStack) {
let frames = [];
for (let frame = aStack; frame; frame = frame.caller) {
frames.push(frame.filename +
":" + frame.name +
":" + frame.lineNumber);
}
return frames.join(
"\n");
}
/* eslint-disable no-unused-vars */
var Assert =
new AssertCls((err, message, stack) => {
sendAsyncMessage(
"chrome-task:test-result", {
id,
condition: !err,
name: err ? err.message : message,
stack: getStack(err ? err.stack : stack),
});
});
var ok =
Assert.ok.bind(
Assert);
var is =
Assert.equal.bind(
Assert);
var isnot =
Assert.notEqual.bind(
Assert);
function todo(expr, name) {
sendAsyncMessage(
"chrome-task:test-todo", { id, expr, name });
}
function todo_is(a, b, name) {
sendAsyncMessage(
"chrome-task:test-todo_is", { id, a, b, name });
}
function info(name) {
sendAsyncMessage(
"chrome-task:test-info", { id, name });
}
/* eslint-enable no-unused-vars */
try {
let sb = Cu.Sandbox(Services.scriptSecurityManager.getSystemPrincipal(), {
sandboxPrototype: {
__proto__: globalThis,
Assert,
ok,
is,
isnot,
todo,
todo_is,
info,
},
});
let runnable = Cu.evalInSandbox(`(() => (${source}))()`, sb);
let result = await runnable.call(
this, aData.arg);
sendAsyncMessage(
"chrome-task:complete", {
id,
result,
});
}
catch (ex) {
sendAsyncMessage(
"chrome-task:complete", {
id,
error: ex.toString(),
});
}
});
}
/**
* This object provides the public module functions.
*/
var ChromeTask = {
/**
* the ChromeScript if it has already been loaded.
*/
_chromeScript:
null,
/**
* Mapping from message id to associated promise.
*/
_promises:
new Map(),
/**
* Incrementing integer to generate unique message id.
*/
_messageID:
1,
/**
* Creates and starts a new task in the chrome process.
*
* @param arg A single serializable argument that will be passed to the
* task when executed on the content process.
* @param task
* - A generator or function which will be serialized and sent to
* the remote browser to be executed. Unlike Task.spawn, this
* argument may not be an iterator as it will be serialized and
* sent to the remote browser.
* @return {Promise}
* Resolves when the task finishes without errors.
* @rejects An error message if execution fails.
*/
spawn:
function ChromeTask_spawn(arg, task) {
// Load the frame script if needed.
let handle = ChromeTask._chromeScript;
if (!handle) {
handle = SpecialPowers.loadChromeScript(ChromeTask_ChromeScript);
handle.addMessageListener(
"chrome-task:complete", ChromeTask.onComplete);
handle.addMessageListener(
"chrome-task:test-result", ChromeTask.onResult);
handle.addMessageListener(
"chrome-task:test-info", ChromeTask.onInfo);
handle.addMessageListener(
"chrome-task:test-todo", ChromeTask.onTodo);
handle.addMessageListener(
"chrome-task:test-todo_is",
ChromeTask.onTodoIs
);
ChromeTask._chromeScript = handle;
}
let deferred = {};
deferred.promise =
new Promise((resolve, reject) => {
deferred.resolve = resolve;
deferred.reject = reject;
});
let id = ChromeTask._messageID++;
ChromeTask._promises.set(id, deferred);
handle.sendAsyncMessage(
"chrome-task:spawn", {
id,
runnable: task.toString(),
arg,
});
return deferred.promise;
},
onComplete(aData) {
let deferred = ChromeTask._promises.get(aData.id);
ChromeTask._promises.
delete(aData.id);
if (aData.error) {
deferred.reject(aData.error);
}
else {
deferred.resolve(aData.result);
}
},
onResult(aData) {
SimpleTest.record(aData.condition, aData.name);
},
onInfo(aData) {
SimpleTest.info(aData.name);
},
onTodo(aData) {
SimpleTest.todo(aData.expr, aData.name);
},
onTodoIs(aData) {
SimpleTest.todo_is(aData.a, aData.b, aData.name);
},
};