summaryrefslogtreecommitdiffstats
path: root/dom/base/test/common_postMessages.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/test/common_postMessages.js')
-rw-r--r--dom/base/test/common_postMessages.js393
1 files changed, 393 insertions, 0 deletions
diff --git a/dom/base/test/common_postMessages.js b/dom/base/test/common_postMessages.js
new file mode 100644
index 0000000000..c4836fdd77
--- /dev/null
+++ b/dom/base/test/common_postMessages.js
@@ -0,0 +1,393 @@
+function getType(a) {
+ if (a === null || a === undefined) {
+ return "null";
+ }
+
+ if (Array.isArray(a)) {
+ return "array";
+ }
+
+ if (typeof a == "object") {
+ return "object";
+ }
+
+ if (
+ SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupported() &&
+ a instanceof WebAssembly.Module
+ ) {
+ return "wasm";
+ }
+
+ return "primitive";
+}
+
+function compare(a, b) {
+ is(getType(a), getType(b), "Type matches");
+
+ var type = getType(a);
+ if (type == "array") {
+ is(a.length, b.length, "Array.length matches");
+ for (var i = 0; i < a.length; ++i) {
+ compare(a[i], b[i]);
+ }
+
+ return;
+ }
+
+ if (type == "object") {
+ ok(a !== b, "They should not match");
+
+ var aProps = [];
+ for (var p in a) {
+ aProps.push(p);
+ }
+
+ var bProps = [];
+ for (var p in b) {
+ bProps.push(p);
+ }
+
+ is(aProps.length, bProps.length, "Props match");
+ is(aProps.sort().toString(), bProps.sort().toString(), "Props names match");
+
+ for (var p in a) {
+ compare(a[p], b[p]);
+ }
+
+ return;
+ }
+
+ if (type == "wasm") {
+ var wasmA = new WebAssembly.Instance(a);
+ ok(wasmA instanceof WebAssembly.Instance, "got an instance");
+
+ var wasmB = new WebAssembly.Instance(b);
+ ok(wasmB instanceof WebAssembly.Instance, "got an instance");
+
+ ok(wasmA.exports.foo() === wasmB.exports.foo(), "Same result!");
+ ok(wasmB.exports.foo() === 42, "We want 42");
+ }
+
+ if (type != "null") {
+ is(a, b, "Same value");
+ }
+}
+
+var clonableObjects = [
+ { target: "all", data: "hello world" },
+ { target: "all", data: 123 },
+ { target: "all", data: null },
+ { target: "all", data: true },
+ { target: "all", data: new Date() },
+ { target: "all", data: [1, "test", true, new Date()] },
+ {
+ target: "all",
+ data: { a: true, b: null, c: new Date(), d: [true, false, {}] },
+ },
+ { target: "all", data: new Blob([123], { type: "plain/text" }) },
+ { target: "all", data: new ImageData(2, 2) },
+];
+
+function create_fileList() {
+ var url = SimpleTest.getTestFileURL("script_postmessages_fileList.js");
+ var script = SpecialPowers.loadChromeScript(url);
+
+ function onOpened(message) {
+ var fileList = document.getElementById("fileList");
+ SpecialPowers.wrap(fileList).mozSetFileArray([message.file]);
+
+ // Just a simple test
+ var domFile = fileList.files[0];
+ is(domFile.name, "prefs.js", "fileName should be prefs.js");
+
+ clonableObjects.push({ target: "all", data: fileList.files });
+ script.destroy();
+ next();
+ }
+
+ script.addMessageListener("file.opened", onOpened);
+ script.sendAsyncMessage("file.open");
+}
+
+function create_directory() {
+ if (navigator.userAgent.toLowerCase().includes("Android")) {
+ next();
+ return;
+ }
+
+ var url = SimpleTest.getTestFileURL("script_postmessages_fileList.js");
+ var script = SpecialPowers.loadChromeScript(url);
+
+ function onOpened(message) {
+ var fileList = document.getElementById("fileList");
+ SpecialPowers.wrap(fileList).mozSetDirectory(message.dir);
+
+ SpecialPowers.wrap(fileList)
+ .getFilesAndDirectories()
+ .then(function (list) {
+ list = SpecialPowers.unwrap(list);
+ // Just a simple test
+ is(list.length, 1, "This list has 1 element");
+ ok(list[0] instanceof Directory, "We have a directory.");
+
+ clonableObjects.push({ target: "all", data: list[0] });
+ script.destroy();
+ next();
+ });
+ }
+
+ script.addMessageListener("dir.opened", onOpened);
+ script.sendAsyncMessage("dir.open");
+}
+
+function create_wasmModule() {
+ info("Checking if we can play with WebAssembly...");
+
+ if (!SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupported()) {
+ next();
+ return;
+ }
+
+ ok(WebAssembly, "WebAssembly object should exist");
+ ok(WebAssembly.compile, "WebAssembly.compile function should exist");
+
+ /*
+ js -e '
+ t = wasmTextToBinary(`
+ (module
+ (func $foo (result i32) (i32.const 42))
+ (export "foo" (func $foo))
+ )
+ `);
+ print(t)
+ '
+ */
+ // prettier-ignore
+ const fooModuleCode = new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,127,3,2,1,0,7,7,1,3,102,111,111,0,0,10,6,1,4,0,65,42,11,0,13,4,110,97,109,101,1,6,1,0,3,102,111,111]);
+
+ WebAssembly.compile(fooModuleCode).then(
+ m => {
+ ok(m instanceof WebAssembly.Module, "The WasmModule has been compiled.");
+ clonableObjects.push({ target: "sameProcess", data: m });
+ next();
+ },
+ () => {
+ ok(false, "The compilation of the wasmModule failed.");
+ }
+ );
+}
+
+function runTests(obj) {
+ ok(
+ "clonableObjectsEveryWhere" in obj &&
+ "clonableObjectsSameProcess" in obj &&
+ "transferableObjects" in obj &&
+ (obj.clonableObjectsEveryWhere ||
+ obj.clonableObjectsSameProcess ||
+ obj.transferableObjects),
+ "We must run some test!"
+ );
+
+ // cloning tests - everyWhere
+ new Promise(function (resolve, reject) {
+ var clonableObjectsId = 0;
+ function runClonableTest() {
+ if (clonableObjectsId >= clonableObjects.length) {
+ resolve();
+ return;
+ }
+
+ var object = clonableObjects[clonableObjectsId++];
+
+ if (object.target != "all") {
+ runClonableTest();
+ return;
+ }
+
+ obj
+ .send(object.data, [])
+ .catch(() => {
+ return { error: true };
+ })
+ .then(received => {
+ if (!obj.clonableObjectsEveryWhere) {
+ ok(received.error, "Error expected");
+ } else {
+ ok(!received.error, "Error not expected");
+ compare(received.data, object.data);
+ }
+ runClonableTest();
+ });
+ }
+
+ runClonableTest();
+ })
+
+ // clonable same process
+ .then(function () {
+ return new Promise(function (resolve, reject) {
+ var clonableObjectsId = 0;
+ function runClonableTest() {
+ if (clonableObjectsId >= clonableObjects.length) {
+ resolve();
+ return;
+ }
+
+ var object = clonableObjects[clonableObjectsId++];
+
+ if (object.target != "sameProcess") {
+ runClonableTest();
+ return;
+ }
+
+ obj
+ .send(object.data, [])
+ .catch(() => {
+ return { error: true };
+ })
+ .then(received => {
+ if (!obj.clonableObjectsSameProcess) {
+ ok(received.error, "Error expected");
+ } else {
+ ok(!received.error, "Error not expected");
+ compare(received.data, object.data);
+ }
+ runClonableTest();
+ });
+ }
+
+ runClonableTest();
+ });
+ })
+
+ // transfering tests
+ .then(function () {
+ if (!obj.transferableObjects) {
+ return Promise.resolve();
+ }
+
+ // MessagePort
+ return new Promise(function (r, rr) {
+ var mc = new MessageChannel();
+ obj.send(42, [mc.port1]).then(function (received) {
+ is(received.ports.length, 1, "MessagePort has been transferred");
+ mc.port2.postMessage("hello world");
+ received.ports[0].onmessage = function (e) {
+ is(e.data, "hello world", "Ports are connected!");
+ r();
+ };
+ });
+ });
+ })
+
+ // no dup transfering
+ .then(function () {
+ if (!obj.transferableObjects) {
+ return Promise.resolve();
+ }
+
+ // MessagePort
+ return new Promise(function (r, rr) {
+ var mc = new MessageChannel();
+ obj
+ .send(42, [mc.port1, mc.port1])
+ .then(
+ function (received) {
+ ok(false, "Duplicate ports should throw!");
+ },
+ function () {
+ ok(true, "Duplicate ports should throw!");
+ }
+ )
+ .then(r);
+ });
+ })
+
+ // maintaining order of transferred ports
+ .then(function () {
+ if (!obj.transferableObjects) {
+ return Promise.resolve();
+ }
+
+ // MessagePort
+ return new Promise(function (r, rr) {
+ var mcs = [];
+ const NPORTS = 50;
+ for (let i = 0; i < NPORTS; i++) {
+ mcs.push(new MessageChannel());
+ }
+ obj
+ .send(
+ 42,
+ mcs.map(channel => channel.port1)
+ )
+ .then(function (received) {
+ is(
+ received.ports.length,
+ NPORTS,
+ `all ${NPORTS} ports transferred`
+ );
+ const promises = Array(NPORTS)
+ .fill()
+ .map(
+ (_, i) =>
+ new Promise(function (subr, subrr) {
+ mcs[i].port2.postMessage(i);
+ received.ports[i].onmessage = e => subr(e.data == i);
+ })
+ );
+ return Promise.all(promises);
+ })
+ .then(function (result) {
+ let in_order = 0;
+ for (const correct of result) {
+ if (correct) {
+ in_order++;
+ }
+ }
+ is(in_order, NPORTS, "All transferred ports are in order");
+ })
+ .then(r);
+ });
+ })
+
+ // non transfering tests
+ .then(function () {
+ if (obj.transferableObjects) {
+ return Promise.resolve();
+ }
+
+ // MessagePort
+ return new Promise(function (r, rr) {
+ var mc = new MessageChannel();
+ obj
+ .send(42, [mc.port1])
+ .then(
+ function (received) {
+ ok(false, "This object should not support port transferring");
+ },
+ function () {
+ ok(true, "This object should not support port transferring");
+ }
+ )
+ .then(r);
+ });
+ })
+
+ // done.
+ .then(function () {
+ obj.finished();
+ });
+}
+
+function next() {
+ if (!tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ var test = tests.shift();
+ test();
+}
+
+var tests = [create_fileList, create_directory, create_wasmModule];