structuredclone_0.html (35870B)
1 <!doctype html> 2 <html> 3 <head> 4 <meta content="text/html; charset=utf-8" http-equiv="content-type" /> 5 <title>2.8 Common DOM interfaces - Structured Clone Algorithm </title> 6 <link rel="help" href="http://www.w3.org/TR/html5/common-dom-interfaces.html#safe-passing-of-structured-data" /> 7 <script src="/resources/testharness.js"></script> 8 <script src="/resources/testharnessreport.js"></script> 9 </head> 10 <body> 11 <div id="log"></div> 12 <iframe></iframe> <!-- used for grabbing an URIError from another realm --> 13 14 <script type="text/javascript"> 15 var worker; 16 var testCollection; 17 setup(function() 18 { 19 //the worker is used for each test in sequence 20 //worker's callback will be set for each test 21 //worker's internal onmessage echoes the data back to this thread through postMessage 22 worker = new Worker("./resources/echo-worker.js"); 23 testCollection = [ 24 function() { 25 var t = async_test("Primitive string is cloned"); 26 t.id = 0; 27 worker.onmessage = t.step_func(function(e) {assert_equals("primitive string", e.data, "\"primitive string\" === event.data"); t.done(); }); 28 t.step(function() { worker.postMessage("primitive string");}); 29 }, 30 function() { 31 var t = async_test("Primitive integer is cloned"); 32 t.id = 1; 33 worker.onmessage = t.step_func(function(e) {assert_equals(2000, e.data, "2000 === event.data"); t.done(); }); 34 t.step(function() { worker.postMessage(2000);}); 35 }, 36 function() { 37 var t = async_test("Primitive floating point is cloned"); 38 t.id = 2; 39 worker.onmessage = t.step_func(function(e) {assert_equals(111.456, e.data, "111.456 === event.data"); t.done(); }); 40 t.step(function() { worker.postMessage(111.456);}); 41 }, 42 function() { 43 var t = async_test("Primitive floating point (negative) is cloned"); 44 t.id = 3; 45 worker.onmessage = t.step_func(function(e) {assert_equals(-111.456, e.data, "-111.456 === event.data"); t.done(); }); 46 t.step(function() { worker.postMessage(-111.456);}); 47 }, 48 function() { 49 var t = async_test("Primitive number (hex) is cloned"); 50 t.id = 4; 51 worker.onmessage = t.step_func(function(e) {assert_equals(0xAB25, e.data, "0xAB25 === event.data"); t.done(); }); 52 t.step(function() { worker.postMessage(0xAB25);}); 53 }, 54 function() { 55 var t = async_test("Primitive number (scientific) is cloned"); 56 t.id = 5; 57 worker.onmessage = t.step_func(function(e) {assert_equals(15e2, e.data, "15e2 === event.data"); t.done(); }); 58 t.step(function() { worker.postMessage(15e2);}); 59 }, 60 function() { 61 var t = async_test("Primitive boolean is cloned"); 62 t.id = 6; 63 worker.onmessage = t.step_func(function(e) {assert_equals(false, e.data, "false === event.data"); t.done(); }); 64 t.step(function() { worker.postMessage(false);}); 65 }, 66 function() { 67 var t = async_test("Instance of Boolean is cloned"); 68 t.id = 7; 69 var obj; 70 t.step(function() {obj = new Boolean(false);}); 71 worker.onmessage = t.step_func(function(e) { 72 assert_equals(obj.constructor, e.data.constructor, "Boolean === event.data.constructor"); 73 assert_equals(obj.valueOf(), e.data.valueOf(), "(new Boolean(false)).valueof() === event.data.valueOf()"); 74 t.done(); 75 }); 76 t.step(function() { worker.postMessage(obj);}); 77 },function() { 78 var t = async_test("Instance of Number is cloned"); 79 t.id = 8; 80 var obj; 81 t.step(function() {obj = new Number(2000);}); 82 worker.onmessage = t.step_func(function(e) { 83 assert_equals(obj.constructor, e.data.constructor, "Number === event.data.constructor"); 84 assert_equals(obj.valueOf(), e.data.valueOf(), "(new Number(2000)).valueof() === event.data.valueOf()"); 85 t.done(); 86 }); 87 t.step(function() { worker.postMessage(obj);}); 88 }, 89 function() { 90 var t = async_test("Instance of String is cloned"); 91 t.id = 9; 92 var obj; 93 t.step(function() { obj = new String("String Object");}); 94 worker.onmessage = t.step_func(function(e) { 95 assert_equals(obj.constructor, e.data.constructor, "String === event.data.constructor"); 96 assert_equals(obj.valueOf(), e.data.valueOf(), "(new String(\"String Object\")).valueof() === event.data.valueOf()"); 97 t.done(); 98 }); 99 t.step(function() { worker.postMessage(obj);}); 100 }, 101 function() { 102 var t = async_test("Instance of Date is cloned"); 103 t.id = 10; 104 var obj; 105 t.step(function() { obj= new Date(2011,1,1);}); 106 worker.onmessage = t.step_func(function(e) { 107 assert_equals(obj.constructor, e.data.constructor, "Date === event.data.constructor"); 108 assert_equals(obj.valueOf(), e.data.valueOf(), "(new Date(2011,1,1)).valueof() === event.data.valueOf()"); 109 t.done(); 110 }); 111 t.step(function() { worker.postMessage(obj);}); 112 }, 113 function() { 114 var t = async_test("Instance of RegExp is cloned"); 115 t.id = 11; 116 var obj; 117 t.step(function() {obj = new RegExp("w3+c","g","i");}); 118 worker.onmessage = t.step_func(function(e) { 119 assert_equals(obj.constructor, e.data.constructor, "RegExp === event.data.constructor"); 120 assert_equals(obj.source, e.data.source, "canon.source === event.data.source"); 121 assert_equals(obj.multiline, e.data.multiline, "canon.multiline === event.data.multiline"); 122 assert_equals(obj.global, e.data.global, "canon.global === event.data.global"); 123 assert_equals(obj.ignoreCase, e.data.ignoreCase, "canon.ignoreCase === event.data.ignoreCase"); 124 t.done(); 125 }); 126 t.step(function() { worker.postMessage(obj);}); 127 }, 128 function() { 129 var t = async_test("Value 'null' is cloned"); 130 t.id = 12; 131 worker.onmessage = t.step_func(function(e) {assert_equals(null, e.data, "null === event.data"); t.done(); }); 132 t.step(function() { worker.postMessage(null);}); 133 }, 134 function() { 135 var t = async_test("Value 'undefined' is cloned"); 136 t.id = 13; 137 worker.onmessage = t.step_func(function(e) {assert_equals(undefined, e.data, "undefined === event.data"); t.done(); }); 138 t.step(function() { worker.postMessage(undefined);}); 139 }, 140 function() { 141 var t = async_test("Object properties are cloned"); 142 t.id = 14; 143 var obj; 144 t.step(function() { 145 obj= {}; 146 obj.a = "test"; 147 obj.b = 2; 148 obj["child"] = 3; 149 }); 150 worker.onmessage = t.step_func(function(e) { 151 assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor"); 152 assert_equals(obj.a, e.data.a, "canon.a === event.data.a"); 153 assert_equals(obj.b, e.data.b, "canon.b === event.data.b"); 154 assert_equals(obj.child, e.data.child, "canon.child === e.data.child"); 155 t.done(); 156 }); 157 t.step(function() { worker.postMessage(obj);}); 158 }, 159 function() { 160 var t = async_test("Prototype chains are not walked."); 161 t.id = 15; 162 function Custom() { 163 this.a = "hello"; 164 } 165 166 var obj; 167 t.step(function() { 168 Object.defineProperty(Custom.prototype, "b", { enumerable: true, value: 100 }); 169 obj = new Custom(); 170 }); 171 worker.onmessage = t.step_func(function(e) { 172 assert_not_equals(obj.constructor, e.data.constructor, "canon.constructor !== event.data.constructor"); 173 assert_equals(Object, e.data.constructor, "Object === e.data.constructor"); 174 assert_equals(obj.a, e.data.a, "canon.a === e.data.a"); 175 assert_equals(undefined, e.data.b, "undefined === e.data.b"); 176 t.done(); 177 }); 178 t.step(function() { worker.postMessage(obj);}); 179 }, 180 function() { 181 var t = async_test("Property descriptors of Objects are not cloned"); 182 t.id = 16; 183 var obj; 184 t.step(function() { 185 obj = {}; 186 Object.defineProperty(obj, "a", { enumerable: true, writable: false, value: 100 }); 187 }); 188 worker.onmessage = t.step_func(function(e) { 189 var des = Object.getOwnPropertyDescriptor(e.data, "a"); 190 assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor"); 191 assert_true(des.writable, "Descriptor is writable"); 192 t.done(); 193 }); 194 t.step(function() { worker.postMessage(obj);}); 195 }, 196 function() { 197 var t = async_test("Cycles are preserved in Objects"); 198 t.id = 17; 199 var obj; 200 t.step(function() { 201 obj = {}; 202 obj.a = obj; 203 }); 204 worker.onmessage = t.step_func(function(e) { 205 assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor"); 206 assert_equals(e.data, e.data.a, "cycle is preserved"); 207 t.done(); 208 }); 209 t.step(function() { worker.postMessage(obj);}); 210 }, 211 function() { 212 var t = async_test("Identity of duplicates is preserved"); 213 t.id = 18; 214 var ref; 215 var obj; 216 t.step(function() { 217 ref = {}; 218 ref.called = 0; 219 Object.defineProperty(ref, "child", {get: function(){this.called++;}, enumerable: true}); 220 221 obj = {a:ref, b:ref}; 222 }); 223 worker.onmessage = t.step_func(function(e) { 224 assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor"); 225 assert_equals(e.data.b.called, 0, "e.data.b.called === 0"); 226 t.done(); 227 }); 228 t.step(function() { worker.postMessage(obj);}); 229 }, 230 function() { 231 var t = async_test("Property order is preserved"); 232 t.id = 19; 233 var obj; 234 t.step(function() { 235 obj = { "a": "hello", "b": "w3c", "c": "and world" }; 236 obj["a"] = "named1"; 237 }); 238 worker.onmessage = t.step_func(function(e) { 239 assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor"); 240 var canonNames = Object.getOwnPropertyNames(obj); 241 var testNames = Object.getOwnPropertyNames(e.data); 242 for (var i in canonNames) { 243 assert_equals(canonNames[i], testNames[i], "canonProperty["+i+"] === dataProperty["+i+"]"); 244 } 245 t.done(); 246 }); 247 t.step(function() { worker.postMessage(obj);}); 248 }, 249 function() { 250 var t = async_test("Enumerable properties of Arrays are cloned"); 251 t.id = 20; 252 var obj; 253 t.step(function() { 254 obj = [0,1]; 255 obj["a"] = "named1"; 256 }); 257 worker.onmessage = t.step_func(function(e) { 258 assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor"); 259 assert_equals(e.data["a"], "named1", "e.data[\"a\"] === \"named1\""); 260 assert_equals(e.data[0], 0, "e.data[0] === 0"); 261 assert_equals(e.data[1], 1, "e.data[1] === 1"); 262 t.done(); 263 }); 264 t.step(function() { worker.postMessage(obj);}); 265 }, 266 function() { 267 var t = async_test("Property descriptors of Arrays are not cloned"); 268 t.id = 21; 269 var obj; 270 t.step(function() { 271 obj = [0, 1]; 272 Object.defineProperty(obj, "2", { enumerable: true, writable: false, value: 100 }); 273 }); 274 worker.onmessage = t.step_func(function(e) { 275 assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor"); 276 assert_equals(e.data[0], 0, "e.data[0] === 0"); 277 assert_equals(e.data[1], 1, "e.data[1] === 1"); 278 var des = Object.getOwnPropertyDescriptor(e.data, "2"); 279 assert_true(des.writable, "Descriptor is writable"); 280 t.done(); 281 }); 282 t.step(function() { worker.postMessage(obj);}); 283 }, 284 function() { 285 var t = async_test("Cycles are preserved in Arrays"); 286 t.id = 22; 287 var obj; 288 t.step(function() { 289 obj = [0,1]; 290 obj[2] = obj; 291 }); 292 worker.onmessage = t.step_func(function(e) { 293 assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor"); 294 assert_equals(e.data[0], 0, "e.data[0] === 0"); 295 assert_equals(e.data[1], 1, "e.data[1] === 1"); 296 assert_equals(e.data[2], e.data, "e.data[2] === e.data"); 297 t.done(); 298 }); 299 t.step(function() { worker.postMessage(obj);}); 300 }, 301 302 function() { 303 var t = async_test("ImageData object can be cloned"); 304 t.id = 23; 305 var obj; 306 t.step(function() { 307 var canvas = document.createElement("canvas"); 308 canvas.width = 40; 309 canvas.height = 40; 310 var context = canvas.getContext('2d'); 311 obj = context.createImageData(40, 40); 312 assert_true(window.hasOwnProperty("ImageData"), "ImageData constructor must be present"); 313 assert_true(obj instanceof ImageData, "ImageData must be returned by .createImageData"); 314 }); 315 worker.onmessage = t.step_func(function(e) { 316 assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor"); 317 assert_not_equals(obj, e.data, "cloned object should be a new instance of ImageData"); 318 assert_equals(obj.width, e.data.width, "canon.width === e.data.width"); 319 assert_equals(obj.height, e.data.height, "canon.height === e.data.height"); 320 assert_array_equals(obj.data, e.data.data, "data arrays are the same"); 321 t.done(); 322 }); 323 t.step(function() { worker.postMessage(obj);}); 324 }, 325 function() { 326 var t = async_test("ImageData expandos are not cloned"); 327 t.id = 24; 328 var obj; 329 t.step(function() { 330 var canvas = document.createElement("canvas"); 331 canvas.width = 40; 332 canvas.height = 40; 333 var context = canvas.getContext('2d'); 334 obj = context.createImageData(40, 40); 335 assert_true(window.hasOwnProperty("ImageData"), "ImageData constructor must be present"); 336 assert_true(obj instanceof ImageData, "ImageData must be returned by .createImageData"); 337 obj.foo = "bar"; 338 }); 339 worker.onmessage = t.step_func(function(e) { 340 assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor"); 341 assert_not_equals(obj, e.data, "cloned object should be a new instance of ImageData"); 342 assert_equals(obj.width, e.data.width, "canon.width === e.data.width"); 343 assert_equals(obj.height, e.data.height, "canon.height === e.data.height"); 344 assert_array_equals(obj.data, e.data.data, "data arrays are the same"); 345 assert_equals(undefined, e.data.foo, "Expando is lost (undefined === e.data.foo)"); 346 t.done(); 347 }); 348 t.step(function() { worker.postMessage(obj);}); 349 }, 350 function() { 351 var t = async_test("Window objects cannot be cloned"); 352 t.id = 25; 353 worker.onmessage = function() {}; //no op because exception should be thrown. 354 t.step(function() { 355 assert_true(DOMException.hasOwnProperty('DATA_CLONE_ERR'), "DOMException.DATA_CLONE_ERR is present"); 356 assert_equals(DOMException.DATA_CLONE_ERR, 25, "DOMException.DATA_CLONE_ERR === 25"); 357 assert_throws_dom('DATA_CLONE_ERR', function() {worker.postMessage(window)}); 358 }); 359 t.done(); 360 }, 361 function() { 362 var t = async_test("Document objects cannot be cloned"); 363 t.id = 26; 364 worker.onmessage = function() {}; //no op because exception should be thrown. 365 t.step(function() { 366 assert_true(DOMException.hasOwnProperty('DATA_CLONE_ERR'), "DOMException.DATA_CLONE_ERR is present"); 367 assert_equals(DOMException.DATA_CLONE_ERR, 25, "DOMException.DATA_CLONE_ERR === 25"); 368 assert_throws_dom('DATA_CLONE_ERR', function() {worker.postMessage(document)}); 369 }); 370 t.done(); 371 }, 372 function() { 373 var t = async_test("Empty Error objects can be cloned"); 374 t.id = 27; 375 worker.onmessage = t.step_func_done(function(e) { 376 assert_equals(Object.getPrototypeOf(e.data), Error.prototype, "Checking prototype"); 377 assert_equals(e.data.constructor, Error, "Checking constructor"); 378 assert_equals(e.data.name, "Error", "Checking name"); 379 assert_false(e.data.hasOwnProperty("message"), "Checking message"); 380 assert_equals(e.data.foo, undefined, "Checking custom property"); 381 }); 382 t.step(function() { 383 const error = Error(); 384 assert_false(error.hasOwnProperty("message"), "Checking message on the source realm"); 385 worker.postMessage(error); 386 }); 387 }, 388 function() { 389 var t = async_test("Error objects can be cloned"); 390 t.id = 28; 391 worker.onmessage = t.step_func_done(function(e) { 392 assert_equals(Object.getPrototypeOf(e.data), Error.prototype, "Checking prototype"); 393 assert_equals(e.data.constructor, Error, "Checking constructor"); 394 assert_equals(e.data.name, "Error", "Checking name"); 395 assert_equals(e.data.message, "some message", "Checking message"); 396 assert_equals(e.data.foo, undefined, "Checking custom property"); 397 }); 398 t.step(function() { 399 const error = Error("some message"); 400 error.foo = "bar"; 401 worker.postMessage(error); 402 }); 403 }, 404 function() { 405 var t = async_test("EvalError objects can be cloned"); 406 t.id = 29; 407 worker.onmessage = t.step_func_done(function(e) { 408 assert_equals(Object.getPrototypeOf(e.data), EvalError.prototype, "Checking prototype"); 409 assert_equals(e.data.constructor, EvalError, "Checking constructor"); 410 assert_equals(e.data.name, "EvalError", "Checking name"); 411 assert_equals(e.data.message, "some message", "Checking message"); 412 assert_equals(e.data.foo, undefined, "Checking custom property"); 413 }); 414 t.step(function() { 415 const error = EvalError("some message"); 416 error.foo = "bar"; 417 worker.postMessage(error); 418 }); 419 }, 420 function() { 421 var t = async_test("RangeError objects can be cloned"); 422 t.id = 30; 423 worker.onmessage = t.step_func_done(function(e) { 424 assert_equals(Object.getPrototypeOf(e.data), RangeError.prototype, "Checking prototype"); 425 assert_equals(e.data.constructor, RangeError, "Checking constructor"); 426 assert_equals(e.data.name, "RangeError", "Checking name"); 427 assert_equals(e.data.message, "some message", "Checking message"); 428 assert_equals(e.data.foo, undefined, "Checking custom property"); 429 }); 430 t.step(function() { 431 const error = RangeError("some message"); 432 error.foo = "bar"; 433 worker.postMessage(error); 434 }); 435 }, 436 function() { 437 var t = async_test("ReferenceError objects can be cloned"); 438 t.id = 31; 439 worker.onmessage = t.step_func_done(function(e) { 440 assert_equals(Object.getPrototypeOf(e.data), ReferenceError.prototype, "Checking prototype"); 441 assert_equals(e.data.constructor, ReferenceError, "Checking constructor"); 442 assert_equals(e.data.name, "ReferenceError", "Checking name"); 443 assert_equals(e.data.message, "some message", "Checking message"); 444 assert_equals(e.data.foo, undefined, "Checking custom property"); 445 }); 446 t.step(function() { 447 const error = ReferenceError("some message"); 448 error.foo = "bar"; 449 worker.postMessage(error); 450 }); 451 }, 452 function() { 453 var t = async_test("SyntaxError objects can be cloned"); 454 t.id = 32; 455 worker.onmessage = t.step_func_done(function(e) { 456 assert_equals(Object.getPrototypeOf(e.data), SyntaxError.prototype, "Checking prototype"); 457 assert_equals(e.data.constructor, SyntaxError, "Checking constructor"); 458 assert_equals(e.data.name, "SyntaxError", "Checking name"); 459 assert_equals(e.data.message, "some message", "Checking message"); 460 assert_equals(e.data.foo, undefined, "Checking custom property"); 461 }); 462 t.step(function() { 463 const error = SyntaxError("some message"); 464 error.foo = "bar"; 465 worker.postMessage(error); 466 }); 467 }, 468 function() { 469 var t = async_test("TypeError objects can be cloned"); 470 t.id = 33; 471 worker.onmessage = t.step_func_done(function(e) { 472 assert_equals(Object.getPrototypeOf(e.data), TypeError.prototype, "Checking prototype"); 473 assert_equals(e.data.constructor, TypeError, "Checking constructor"); 474 assert_equals(e.data.name, "TypeError", "Checking name"); 475 assert_equals(e.data.message, "some message", "Checking message"); 476 assert_equals(e.data.foo, undefined, "Checking custom property"); 477 }); 478 t.step(function() { 479 const error = TypeError("some message"); 480 error.foo = "bar"; 481 worker.postMessage(error); 482 }); 483 }, 484 function() { 485 var t = async_test("URIError objects can be cloned"); 486 t.id = 34; 487 worker.onmessage = t.step_func_done(function(e) { 488 assert_equals(Object.getPrototypeOf(e.data), URIError.prototype, "Checking prototype"); 489 assert_equals(e.data.constructor, URIError, "Checking constructor"); 490 assert_equals(e.data.name, "URIError", "Checking name"); 491 assert_equals(e.data.message, "some message", "Checking message"); 492 assert_equals(e.data.foo, undefined, "Checking custom property"); 493 }); 494 t.step(function() { 495 const error = URIError("some message"); 496 error.foo = "bar"; 497 worker.postMessage(error); 498 }); 499 }, 500 function() { 501 var t = async_test("URIError objects from other realms are treated as URIError"); 502 t.id = 35; 503 worker.onmessage = t.step_func_done(function(e) { 504 assert_equals(Object.getPrototypeOf(e.data), URIError.prototype, "Checking prototype"); 505 assert_equals(e.data.constructor, URIError, "Checking constructor"); 506 assert_equals(e.data.name, "URIError", "Checking name"); 507 assert_equals(e.data.message, "some message", "Checking message"); 508 assert_equals(e.data.foo, undefined, "Checking custom property"); 509 }); 510 t.step(function() { 511 const error = frames[0].URIError("some message"); 512 assert_equals(Object.getPrototypeOf(error), frames[0].URIError.prototype, "Checking prototype before cloning"); 513 assert_equals(error.constructor, frames[0].URIError, "Checking constructor before cloning"); 514 assert_equals(error.name, "URIError", "Checking name before cloning"); 515 error.foo = "bar"; 516 worker.postMessage(error); 517 }); 518 }, 519 function() { 520 var t = async_test("Cloning a modified Error"); 521 t.id = 36; 522 worker.onmessage = t.step_func_done(function(e) { 523 assert_equals(Object.getPrototypeOf(e.data), TypeError.prototype, "Checking prototype"); 524 assert_equals(e.data.constructor, TypeError, "Checking constructor"); 525 assert_equals(e.data.name, "TypeError", "Checking name"); 526 assert_equals(e.data.message, "another message", "Checking message"); 527 assert_equals(e.data.foo, undefined, "Checking custom property"); 528 }); 529 t.step(function() { 530 const error = URIError("some message"); 531 Object.setPrototypeOf(error, SyntaxError.prototype); 532 error.message = {toString: () => "another message" } 533 error.constructor = RangeError; 534 error.name = "TypeError"; 535 error.foo = "bar"; 536 worker.postMessage(error); 537 }); 538 }, 539 function() { 540 var t = async_test("Error.message: getter is ignored when cloning"); 541 t.id = 37; 542 worker.onmessage = t.step_func_done(function(e) { 543 assert_equals(Object.getPrototypeOf(e.data), Error.prototype, "Checking prototype"); 544 assert_equals(e.data.constructor, Error, "Checking constructor"); 545 assert_equals(e.data.name, "Error", "Checking name"); 546 assert_false(e.data.hasOwnProperty("message"), "Checking message"); 547 assert_equals(e.data.foo, undefined, "Checking custom property"); 548 }); 549 t.step(function() { 550 const error = Error(); 551 Object.defineProperty(error, "message", { get: () => "hello" }); 552 assert_equals(error.message, "hello", "Checking message on the source realm"); 553 worker.postMessage(error); 554 }); 555 }, 556 function() { 557 var t = async_test("Error.message: undefined property is stringified"); 558 t.id = 38; 559 worker.onmessage = t.step_func_done(function(e) { 560 assert_equals(Object.getPrototypeOf(e.data), Error.prototype, "Checking prototype"); 561 assert_equals(e.data.constructor, Error, "Checking constructor"); 562 assert_equals(e.data.name, "Error", "Checking name"); 563 assert_equals(e.data.message, "undefined", "Checking message"); 564 assert_equals(e.data.foo, undefined, "Checking custom property"); 565 }); 566 t.step(function() { 567 const error = Error(); 568 error.message = undefined; 569 assert_equals(error.message, undefined, "Checking message on the source realm"); 570 worker.postMessage(error); 571 }); 572 }, 573 function() { 574 var t = async_test("DOMException objects can be cloned"); 575 t.id = 39; 576 worker.onmessage = t.step_func_done(function(e) { 577 assert_equals(Object.getPrototypeOf(e.data), DOMException.prototype, "Checking prototype"); 578 assert_equals(e.data.constructor, DOMException, "Checking constructor"); 579 assert_equals(e.data.name, "IndexSizeError", "Checking name"); 580 assert_equals(e.data.message, "some message", "Checking message"); 581 assert_equals(e.data.code, DOMException.INDEX_SIZE_ERR, "Checking code"); 582 assert_equals(e.data.foo, undefined, "Checking custom property"); 583 }); 584 t.step(function() { 585 const error = new DOMException("some message", "IndexSizeError"); 586 worker.postMessage(error); 587 }); 588 }, 589 function() { 590 var t = async_test("DOMException objects created by the UA can be cloned"); 591 t.id = 40; 592 worker.onmessage = t.step_func_done(function(e) { 593 assert_equals(Object.getPrototypeOf(e.data), DOMException.prototype, "Checking prototype"); 594 assert_equals(e.data.constructor, DOMException, "Checking constructor"); 595 assert_equals(e.data.code, DOMException.DATA_CLONE_ERR, "Checking code"); 596 assert_equals(e.data.name, "DataCloneError", "Checking name"); 597 }); 598 t.step(function() { 599 try { 600 worker.postMessage(window); 601 } catch (error) { 602 worker.postMessage(error); 603 return; 604 } 605 assert_unreached("Window must not be clonable"); 606 }); 607 }, 608 function() { 609 var t = async_test("QuotaExceededError objects can be cloned"); 610 t.id = 41; 611 worker.onmessage = t.step_func_done(function(e) { 612 assert_equals(Object.getPrototypeOf(e.data), QuotaExceededError.prototype, "Checking prototype"); 613 assert_equals(e.data.constructor, QuotaExceededError, "Checking constructor"); 614 assert_equals(e.data.name, "QuotaExceededError", "Checking name"); 615 assert_equals(e.data.message, "some message", "Checking message"); 616 assert_equals(e.data.code, DOMException.QUOTA_EXCEEDED_ERR, "Checking code"); 617 assert_equals(e.data.quota, 0.1, "Checking quota"); 618 assert_equals(e.data.requested, 1.0, "Checking requested"); 619 assert_equals(e.data.foo, undefined, "Checking custom property"); 620 }); 621 t.step(function() { 622 const error = new QuotaExceededError(message = "some message", options = {quota: 0.1, requested: 1.0}); 623 worker.postMessage(error); 624 }); 625 }, 626 function() { 627 var t = async_test("QuotaExceededError objects with empty quota/requested can be cloned"); 628 t.id = 42; 629 worker.onmessage = t.step_func_done(function(e) { 630 assert_equals(Object.getPrototypeOf(e.data), QuotaExceededError.prototype, "Checking prototype"); 631 assert_equals(e.data.constructor, QuotaExceededError, "Checking constructor"); 632 assert_equals(e.data.name, "QuotaExceededError", "Checking name"); 633 assert_equals(e.data.message, "some message", "Checking message"); 634 assert_equals(e.data.code, DOMException.QUOTA_EXCEEDED_ERR, "Checking code"); 635 assert_equals(e.data.quota, null, "Checking quota"); 636 assert_equals(e.data.requested, null, "Checking requested"); 637 assert_equals(e.data.foo, undefined, "Checking custom property"); 638 }); 639 t.step(function() { 640 const error = new QuotaExceededError(message = "some message"); 641 worker.postMessage(error); 642 }); 643 }, 644 ]; 645 }, {explicit_done:true}); 646 647 //Callback for result_callback 648 //queues the next test in the array testCollection 649 //serves to make test execution sequential from the async worker callbacks 650 //alternatively, we would have to create a worker for each test 651 function testFinished(test) { 652 if(test.id < testCollection.length - 1) { 653 //queue the function so that stack remains shallow 654 queue(testCollection[test.id+1]); 655 } else { 656 //when the last test has run, explicitly end test suite 657 done(); 658 } 659 } 660 function queue(func) { 661 step_timeout(func, 10); 662 } 663 664 add_result_callback(testFinished); 665 //start the first test manually 666 queue(testCollection[0]); 667 668 669 670 671 </script> 672 </body> 673 </html>