diff options
Diffstat (limited to 'dom/base/test/common_postMessages.js')
-rw-r--r-- | dom/base/test/common_postMessages.js | 393 |
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..e582adb41f --- /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; + } + + // 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; + } + + // 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; + } + + // 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; + } + + // 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]; |