common_postMessages.js (10066B)
1 /* eslint-disable mozilla/no-comparison-or-assignment-inside-ok */ 2 3 function getType(a) { 4 if (a === null || a === undefined) { 5 return "null"; 6 } 7 8 if (Array.isArray(a)) { 9 return "array"; 10 } 11 12 if (typeof a == "object") { 13 return "object"; 14 } 15 16 if ( 17 SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupported() && 18 a instanceof WebAssembly.Module 19 ) { 20 return "wasm"; 21 } 22 23 return "primitive"; 24 } 25 26 function compare(a, b) { 27 is(getType(a), getType(b), "Type matches"); 28 29 var type = getType(a); 30 if (type == "array") { 31 is(a.length, b.length, "Array.length matches"); 32 for (var i = 0; i < a.length; ++i) { 33 compare(a[i], b[i]); 34 } 35 36 return; 37 } 38 39 if (type == "object") { 40 ok(a !== b, "They should not match"); 41 42 var aProps = []; 43 for (var p in a) { 44 aProps.push(p); 45 } 46 47 var bProps = []; 48 for (var p in b) { 49 bProps.push(p); 50 } 51 52 is(aProps.length, bProps.length, "Props match"); 53 is(aProps.sort().toString(), bProps.sort().toString(), "Props names match"); 54 55 for (var p in a) { 56 compare(a[p], b[p]); 57 } 58 59 return; 60 } 61 62 if (type == "wasm") { 63 var wasmA = new WebAssembly.Instance(a); 64 ok(wasmA instanceof WebAssembly.Instance, "got an instance"); 65 66 var wasmB = new WebAssembly.Instance(b); 67 ok(wasmB instanceof WebAssembly.Instance, "got an instance"); 68 69 ok(wasmA.exports.foo() === wasmB.exports.foo(), "Same result!"); 70 ok(wasmB.exports.foo() === 42, "We want 42"); 71 } 72 73 if (type != "null") { 74 is(a, b, "Same value"); 75 } 76 } 77 78 var clonableObjects = [ 79 { target: "all", data: "hello world" }, 80 { target: "all", data: 123 }, 81 { target: "all", data: null }, 82 { target: "all", data: true }, 83 { target: "all", data: new Date() }, 84 { target: "all", data: [1, "test", true, new Date()] }, 85 { 86 target: "all", 87 data: { a: true, b: null, c: new Date(), d: [true, false, {}] }, 88 }, 89 { target: "all", data: new Blob([123], { type: "plain/text" }) }, 90 { target: "all", data: new ImageData(2, 2) }, 91 ]; 92 93 function create_fileList() { 94 var url = SimpleTest.getTestFileURL("script_postmessages_fileList.js"); 95 var script = SpecialPowers.loadChromeScript(url); 96 97 function onOpened(message) { 98 var fileList = document.getElementById("fileList"); 99 SpecialPowers.wrap(fileList).mozSetFileArray([message.file]); 100 101 // Just a simple test 102 var domFile = fileList.files[0]; 103 is(domFile.name, "prefs.js", "fileName should be prefs.js"); 104 105 clonableObjects.push({ target: "all", data: fileList.files }); 106 script.destroy(); 107 next(); 108 } 109 110 script.addMessageListener("file.opened", onOpened); 111 script.sendAsyncMessage("file.open"); 112 } 113 114 function create_directory() { 115 if (navigator.userAgent.toLowerCase().includes("Android")) { 116 next(); 117 return; 118 } 119 120 var url = SimpleTest.getTestFileURL("script_postmessages_fileList.js"); 121 var script = SpecialPowers.loadChromeScript(url); 122 123 function onOpened(message) { 124 var fileList = document.getElementById("fileList"); 125 SpecialPowers.wrap(fileList).mozSetDirectory(message.dir); 126 127 SpecialPowers.wrap(fileList) 128 .getFilesAndDirectories() 129 .then(function (list) { 130 list = SpecialPowers.unwrap(list); 131 // Just a simple test 132 is(list.length, 1, "This list has 1 element"); 133 ok(list[0] instanceof Directory, "We have a directory."); 134 135 clonableObjects.push({ target: "all", data: list[0] }); 136 script.destroy(); 137 next(); 138 }); 139 } 140 141 script.addMessageListener("dir.opened", onOpened); 142 script.sendAsyncMessage("dir.open"); 143 } 144 145 function create_wasmModule() { 146 info("Checking if we can play with WebAssembly..."); 147 148 if (!SpecialPowers.Cu.getJSTestingFunctions().wasmIsSupported()) { 149 next(); 150 return; 151 } 152 153 ok(WebAssembly, "WebAssembly object should exist"); 154 ok(WebAssembly.compile, "WebAssembly.compile function should exist"); 155 156 /* 157 js -e ' 158 t = wasmTextToBinary(` 159 (module 160 (func $foo (result i32) (i32.const 42)) 161 (export "foo" (func $foo)) 162 ) 163 `); 164 print(t) 165 ' 166 */ 167 // prettier-ignore 168 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]); 169 170 WebAssembly.compile(fooModuleCode).then( 171 m => { 172 ok(m instanceof WebAssembly.Module, "The WasmModule has been compiled."); 173 clonableObjects.push({ target: "sameProcess", data: m }); 174 next(); 175 }, 176 () => { 177 ok(false, "The compilation of the wasmModule failed."); 178 } 179 ); 180 } 181 182 function runTests(obj) { 183 ok( 184 "clonableObjectsEveryWhere" in obj && 185 "clonableObjectsSameProcess" in obj && 186 "transferableObjects" in obj && 187 (obj.clonableObjectsEveryWhere || 188 obj.clonableObjectsSameProcess || 189 obj.transferableObjects), 190 "We must run some test!" 191 ); 192 193 // cloning tests - everyWhere 194 new Promise(function (resolve, reject) { 195 var clonableObjectsId = 0; 196 function runClonableTest() { 197 if (clonableObjectsId >= clonableObjects.length) { 198 resolve(); 199 return; 200 } 201 202 var object = clonableObjects[clonableObjectsId++]; 203 204 if (object.target != "all") { 205 runClonableTest(); 206 return; 207 } 208 209 obj 210 .send(object.data, []) 211 .catch(() => { 212 return { error: true }; 213 }) 214 .then(received => { 215 if (!obj.clonableObjectsEveryWhere) { 216 ok(received.error, "Error expected"); 217 } else { 218 ok(!received.error, "Error not expected"); 219 compare(received.data, object.data); 220 } 221 runClonableTest(); 222 }); 223 } 224 225 runClonableTest(); 226 }) 227 228 // clonable same process 229 .then(function () { 230 return new Promise(function (resolve, reject) { 231 var clonableObjectsId = 0; 232 function runClonableTest() { 233 if (clonableObjectsId >= clonableObjects.length) { 234 resolve(); 235 return; 236 } 237 238 var object = clonableObjects[clonableObjectsId++]; 239 240 if (object.target != "sameProcess") { 241 runClonableTest(); 242 return; 243 } 244 245 obj 246 .send(object.data, []) 247 .catch(() => { 248 return { error: true }; 249 }) 250 .then(received => { 251 if (!obj.clonableObjectsSameProcess) { 252 ok(received.error, "Error expected"); 253 } else { 254 ok(!received.error, "Error not expected"); 255 compare(received.data, object.data); 256 } 257 runClonableTest(); 258 }); 259 } 260 261 runClonableTest(); 262 }); 263 }) 264 265 // transfering tests 266 .then(function () { 267 if (!obj.transferableObjects) { 268 return Promise.resolve(); 269 } 270 271 // MessagePort 272 return new Promise(function (r, rr) { 273 var mc = new MessageChannel(); 274 obj.send(42, [mc.port1]).then(function (received) { 275 is(received.ports.length, 1, "MessagePort has been transferred"); 276 mc.port2.postMessage("hello world"); 277 received.ports[0].onmessage = function (e) { 278 is(e.data, "hello world", "Ports are connected!"); 279 r(); 280 }; 281 }); 282 }); 283 }) 284 285 // no dup transfering 286 .then(function () { 287 if (!obj.transferableObjects) { 288 return Promise.resolve(); 289 } 290 291 // MessagePort 292 return new Promise(function (r, rr) { 293 var mc = new MessageChannel(); 294 obj 295 .send(42, [mc.port1, mc.port1]) 296 .then( 297 function (received) { 298 ok(false, "Duplicate ports should throw!"); 299 }, 300 function () { 301 ok(true, "Duplicate ports should throw!"); 302 } 303 ) 304 .then(r); 305 }); 306 }) 307 308 // maintaining order of transferred ports 309 .then(function () { 310 if (!obj.transferableObjects) { 311 return Promise.resolve(); 312 } 313 314 // MessagePort 315 return new Promise(function (r, rr) { 316 var mcs = []; 317 const NPORTS = 50; 318 for (let i = 0; i < NPORTS; i++) { 319 mcs.push(new MessageChannel()); 320 } 321 obj 322 .send( 323 42, 324 mcs.map(channel => channel.port1) 325 ) 326 .then(function (received) { 327 is( 328 received.ports.length, 329 NPORTS, 330 `all ${NPORTS} ports transferred` 331 ); 332 const promises = Array(NPORTS) 333 .fill() 334 .map( 335 (_, i) => 336 new Promise(function (subr, subrr) { 337 mcs[i].port2.postMessage(i); 338 received.ports[i].onmessage = e => subr(e.data == i); 339 }) 340 ); 341 return Promise.all(promises); 342 }) 343 .then(function (result) { 344 let in_order = 0; 345 for (const correct of result) { 346 if (correct) { 347 in_order++; 348 } 349 } 350 is(in_order, NPORTS, "All transferred ports are in order"); 351 }) 352 .then(r); 353 }); 354 }) 355 356 // non transfering tests 357 .then(function () { 358 if (obj.transferableObjects) { 359 return Promise.resolve(); 360 } 361 362 // MessagePort 363 return new Promise(function (r, rr) { 364 var mc = new MessageChannel(); 365 obj 366 .send(42, [mc.port1]) 367 .then( 368 function (received) { 369 ok(false, "This object should not support port transferring"); 370 }, 371 function () { 372 ok(true, "This object should not support port transferring"); 373 } 374 ) 375 .then(r); 376 }); 377 }) 378 379 // done. 380 .then(function () { 381 obj.finished(); 382 }); 383 } 384 385 function next() { 386 if (!tests.length) { 387 SimpleTest.finish(); 388 return; 389 } 390 391 var test = tests.shift(); 392 test(); 393 } 394 395 var tests = [create_fileList, create_directory, create_wasmModule];