tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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>