tor-browser

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

transfer-with-messageport.window.js (7244B)


      1 "use strict";
      2 
      3 function receiveEventOnce(target, name) {
      4  return new Promise(resolve => {
      5    target.addEventListener(
      6      name,
      7      ev => {
      8        resolve(ev);
      9      },
     10      { once: true }
     11    );
     12  });
     13 }
     14 
     15 async function postAndTestMessageEvent(data, transfer, title) {
     16  postMessage(data, "*", transfer);
     17  const messagePortCount = transfer.filter(i => i instanceof MessagePort)
     18    .length;
     19  const ev = await receiveEventOnce(window, "message");
     20  assert_equals(
     21    ev.ports.length,
     22    messagePortCount,
     23    `Correct number of ports ${title}`
     24  );
     25  for (const [i, port] of ev.ports.entries()) {
     26    assert_true(
     27      port instanceof MessagePort,
     28      `ports[${i}] include MessagePort ${title}`
     29    );
     30  }
     31  for (const [key, value] of Object.entries(data)) {
     32    assert_true(
     33      ev.data[key] instanceof value.constructor,
     34      `data.${key} has correct interface ${value.constructor.name} ${title}`
     35    );
     36  }
     37 }
     38 
     39 async function transferMessagePortWithOrder1(stream) {
     40  const channel = new MessageChannel();
     41  await postAndTestMessageEvent(
     42    { stream, port2: channel.port2 },
     43    [stream, channel.port2],
     44    `when transferring [${stream.constructor.name}, MessagePort]`
     45  );
     46 }
     47 
     48 async function transferMessagePortWithOrder2(stream) {
     49  const channel = new MessageChannel();
     50  await postAndTestMessageEvent(
     51    { stream, port2: channel.port2 },
     52    [channel.port2, stream],
     53    `when transferring [MessagePort, ${stream.constructor.name}]`
     54  );
     55 }
     56 
     57 async function transferMessagePortWithOrder3(stream) {
     58  const channel = new MessageChannel();
     59  await postAndTestMessageEvent(
     60    { port1: channel.port1, stream, port2: channel.port2 },
     61    [channel.port1, stream, channel.port2],
     62    `when transferring [MessagePort, ${stream.constructor.name}, MessagePort]`
     63  );
     64 }
     65 
     66 async function transferMessagePortWithOrder4(stream) {
     67  const channel = new MessageChannel();
     68  await postAndTestMessageEvent(
     69    {},
     70    [channel.port1, stream, channel.port2],
     71    `when transferring [MessagePort, ${stream.constructor.name}, MessagePort] but with empty data`
     72  );
     73 }
     74 
     75 async function transferMessagePortWithOrder5(stream) {
     76  const channel = new MessageChannel();
     77  await postAndTestMessageEvent(
     78    { port2: channel.port2, port1: channel.port1, stream },
     79    [channel.port1, stream, channel.port2],
     80    `when transferring [MessagePort, ${stream.constructor.name}, MessagePort] but with data having different order`
     81  );
     82 }
     83 
     84 async function transferMessagePortWithOrder6(stream) {
     85  const channel = new MessageChannel();
     86  await postAndTestMessageEvent(
     87    { port2: channel.port2, port1: channel.port1 },
     88    [channel.port1, stream, channel.port2],
     89    `when transferring [MessagePort, ${stream.constructor.name}, MessagePort] but with stream not being in the data`
     90  );
     91 }
     92 
     93 async function transferMessagePortWithOrder7(stream) {
     94  const channel = new MessageChannel();
     95  await postAndTestMessageEvent(
     96    { stream },
     97    [channel.port1, stream, channel.port2],
     98    `when transferring [MessagePort, ${stream.constructor.name}, MessagePort] but with ports not being in the data`
     99  );
    100 }
    101 
    102 async function transferMessagePortWith(constructor) {
    103  await transferMessagePortWithOrder1(new constructor());
    104  await transferMessagePortWithOrder2(new constructor());
    105  await transferMessagePortWithOrder3(new constructor());
    106 }
    107 
    108 async function advancedTransferMessagePortWith(constructor) {
    109  await transferMessagePortWithOrder4(new constructor());
    110  await transferMessagePortWithOrder5(new constructor());
    111  await transferMessagePortWithOrder6(new constructor());
    112  await transferMessagePortWithOrder7(new constructor());
    113 }
    114 
    115 async function mixedTransferMessagePortWithOrder1() {
    116  const channel = new MessageChannel();
    117  const readable = new ReadableStream();
    118  const writable = new WritableStream();
    119  const transform = new TransformStream();
    120  await postAndTestMessageEvent(
    121    {
    122      readable,
    123      writable,
    124      transform,
    125      port1: channel.port1,
    126      port2: channel.port2,
    127    },
    128    [readable, writable, transform, channel.port1, channel.port2],
    129    `when transferring [ReadableStream, WritableStream, TransformStream, MessagePort, MessagePort]`
    130  );
    131 }
    132 
    133 async function mixedTransferMessagePortWithOrder2() {
    134  const channel = new MessageChannel();
    135  const readable = new ReadableStream();
    136  const writable = new WritableStream();
    137  const transform = new TransformStream();
    138  await postAndTestMessageEvent(
    139    { readable, writable, transform },
    140    [transform, channel.port1, readable, channel.port2, writable],
    141    `when transferring [TransformStream, MessagePort, ReadableStream, MessagePort, WritableStream]`
    142  );
    143 }
    144 
    145 async function mixedTransferMessagePortWithOrder3() {
    146  const channel = new MessageChannel();
    147  const readable1 = new ReadableStream();
    148  const readable2 = new ReadableStream();
    149  const writable1 = new WritableStream();
    150  const writable2 = new WritableStream();
    151  const transform1 = new TransformStream();
    152  const transform2 = new TransformStream();
    153  await postAndTestMessageEvent(
    154    { readable1, writable1, transform1, readable2, writable2, transform2 },
    155    [
    156      transform2,
    157      channel.port1,
    158      readable1,
    159      channel.port2,
    160      writable2,
    161      readable2,
    162      writable1,
    163      transform1,
    164    ],
    165    `when transferring [TransformStream, MessagePort, ReadableStream, MessagePort, WritableStream, ReadableStream, WritableStream, TransformStream] but with the data having different order`
    166  );
    167 }
    168 
    169 async function mixedTransferMessagePortWith() {
    170  await mixedTransferMessagePortWithOrder1();
    171  await mixedTransferMessagePortWithOrder2();
    172  await mixedTransferMessagePortWithOrder3();
    173 }
    174 
    175 promise_test(async t => {
    176  await transferMessagePortWith(ReadableStream);
    177 }, "Transferring a MessagePort with a ReadableStream should set `.ports`");
    178 
    179 promise_test(async t => {
    180  await transferMessagePortWith(WritableStream);
    181 }, "Transferring a MessagePort with a WritableStream should set `.ports`");
    182 
    183 promise_test(async t => {
    184  await transferMessagePortWith(TransformStream);
    185 }, "Transferring a MessagePort with a TransformStream should set `.ports`");
    186 
    187 promise_test(async t => {
    188  await advancedTransferMessagePortWith(ReadableStream);
    189 }, "Transferring a MessagePort with a ReadableStream should set `.ports`, advanced");
    190 
    191 promise_test(async t => {
    192  await advancedTransferMessagePortWith(WritableStream);
    193 }, "Transferring a MessagePort with a WritableStream should set `.ports`, advanced");
    194 
    195 promise_test(async t => {
    196  await advancedTransferMessagePortWith(TransformStream);
    197 }, "Transferring a MessagePort with a TransformStream should set `.ports`, advanced");
    198 
    199 promise_test(async t => {
    200  await mixedTransferMessagePortWith();
    201 }, "Transferring a MessagePort with multiple streams should set `.ports`");
    202 
    203 test(() => {
    204  assert_throws_dom("DataCloneError", () =>
    205    postMessage({ stream: new ReadableStream() }, "*")
    206  );
    207 }, "ReadableStream must not be serializable");
    208 
    209 test(() => {
    210  assert_throws_dom("DataCloneError", () =>
    211    postMessage({ stream: new WritableStream() }, "*")
    212  );
    213 }, "WritableStream must not be serializable");
    214 
    215 test(() => {
    216  assert_throws_dom("DataCloneError", () =>
    217    postMessage({ stream: new TransformStream() }, "*")
    218  );
    219 }, "TransformStream must not be serializable");