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");