219 lines
7.1 KiB
JavaScript
219 lines
7.1 KiB
JavaScript
"use strict";
|
|
|
|
function receiveEventOnce(target, name) {
|
|
return new Promise(resolve => {
|
|
target.addEventListener(
|
|
name,
|
|
ev => {
|
|
resolve(ev);
|
|
},
|
|
{ once: true }
|
|
);
|
|
});
|
|
}
|
|
|
|
async function postAndTestMessageEvent(data, transfer, title) {
|
|
postMessage(data, "*", transfer);
|
|
const messagePortCount = transfer.filter(i => i instanceof MessagePort)
|
|
.length;
|
|
const ev = await receiveEventOnce(window, "message");
|
|
assert_equals(
|
|
ev.ports.length,
|
|
messagePortCount,
|
|
`Correct number of ports ${title}`
|
|
);
|
|
for (const [i, port] of ev.ports.entries()) {
|
|
assert_true(
|
|
port instanceof MessagePort,
|
|
`ports[${i}] include MessagePort ${title}`
|
|
);
|
|
}
|
|
for (const [key, value] of Object.entries(data)) {
|
|
assert_true(
|
|
ev.data[key] instanceof value.constructor,
|
|
`data.${key} has correct interface ${value.constructor.name} ${title}`
|
|
);
|
|
}
|
|
}
|
|
|
|
async function transferMessagePortWithOrder1(stream) {
|
|
const channel = new MessageChannel();
|
|
await postAndTestMessageEvent(
|
|
{ stream, port2: channel.port2 },
|
|
[stream, channel.port2],
|
|
`when transferring [${stream.constructor.name}, MessagePort]`
|
|
);
|
|
}
|
|
|
|
async function transferMessagePortWithOrder2(stream) {
|
|
const channel = new MessageChannel();
|
|
await postAndTestMessageEvent(
|
|
{ stream, port2: channel.port2 },
|
|
[channel.port2, stream],
|
|
`when transferring [MessagePort, ${stream.constructor.name}]`
|
|
);
|
|
}
|
|
|
|
async function transferMessagePortWithOrder3(stream) {
|
|
const channel = new MessageChannel();
|
|
await postAndTestMessageEvent(
|
|
{ port1: channel.port1, stream, port2: channel.port2 },
|
|
[channel.port1, stream, channel.port2],
|
|
`when transferring [MessagePort, ${stream.constructor.name}, MessagePort]`
|
|
);
|
|
}
|
|
|
|
async function transferMessagePortWithOrder4(stream) {
|
|
const channel = new MessageChannel();
|
|
await postAndTestMessageEvent(
|
|
{},
|
|
[channel.port1, stream, channel.port2],
|
|
`when transferring [MessagePort, ${stream.constructor.name}, MessagePort] but with empty data`
|
|
);
|
|
}
|
|
|
|
async function transferMessagePortWithOrder5(stream) {
|
|
const channel = new MessageChannel();
|
|
await postAndTestMessageEvent(
|
|
{ port2: channel.port2, port1: channel.port1, stream },
|
|
[channel.port1, stream, channel.port2],
|
|
`when transferring [MessagePort, ${stream.constructor.name}, MessagePort] but with data having different order`
|
|
);
|
|
}
|
|
|
|
async function transferMessagePortWithOrder6(stream) {
|
|
const channel = new MessageChannel();
|
|
await postAndTestMessageEvent(
|
|
{ port2: channel.port2, port1: channel.port1 },
|
|
[channel.port1, stream, channel.port2],
|
|
`when transferring [MessagePort, ${stream.constructor.name}, MessagePort] but with stream not being in the data`
|
|
);
|
|
}
|
|
|
|
async function transferMessagePortWithOrder7(stream) {
|
|
const channel = new MessageChannel();
|
|
await postAndTestMessageEvent(
|
|
{ stream },
|
|
[channel.port1, stream, channel.port2],
|
|
`when transferring [MessagePort, ${stream.constructor.name}, MessagePort] but with ports not being in the data`
|
|
);
|
|
}
|
|
|
|
async function transferMessagePortWith(constructor) {
|
|
await transferMessagePortWithOrder1(new constructor());
|
|
await transferMessagePortWithOrder2(new constructor());
|
|
await transferMessagePortWithOrder3(new constructor());
|
|
}
|
|
|
|
async function advancedTransferMessagePortWith(constructor) {
|
|
await transferMessagePortWithOrder4(new constructor());
|
|
await transferMessagePortWithOrder5(new constructor());
|
|
await transferMessagePortWithOrder6(new constructor());
|
|
await transferMessagePortWithOrder7(new constructor());
|
|
}
|
|
|
|
async function mixedTransferMessagePortWithOrder1() {
|
|
const channel = new MessageChannel();
|
|
const readable = new ReadableStream();
|
|
const writable = new WritableStream();
|
|
const transform = new TransformStream();
|
|
await postAndTestMessageEvent(
|
|
{
|
|
readable,
|
|
writable,
|
|
transform,
|
|
port1: channel.port1,
|
|
port2: channel.port2,
|
|
},
|
|
[readable, writable, transform, channel.port1, channel.port2],
|
|
`when transferring [ReadableStream, WritableStream, TransformStream, MessagePort, MessagePort]`
|
|
);
|
|
}
|
|
|
|
async function mixedTransferMessagePortWithOrder2() {
|
|
const channel = new MessageChannel();
|
|
const readable = new ReadableStream();
|
|
const writable = new WritableStream();
|
|
const transform = new TransformStream();
|
|
await postAndTestMessageEvent(
|
|
{ readable, writable, transform },
|
|
[transform, channel.port1, readable, channel.port2, writable],
|
|
`when transferring [TransformStream, MessagePort, ReadableStream, MessagePort, WritableStream]`
|
|
);
|
|
}
|
|
|
|
async function mixedTransferMessagePortWithOrder3() {
|
|
const channel = new MessageChannel();
|
|
const readable1 = new ReadableStream();
|
|
const readable2 = new ReadableStream();
|
|
const writable1 = new WritableStream();
|
|
const writable2 = new WritableStream();
|
|
const transform1 = new TransformStream();
|
|
const transform2 = new TransformStream();
|
|
await postAndTestMessageEvent(
|
|
{ readable1, writable1, transform1, readable2, writable2, transform2 },
|
|
[
|
|
transform2,
|
|
channel.port1,
|
|
readable1,
|
|
channel.port2,
|
|
writable2,
|
|
readable2,
|
|
writable1,
|
|
transform1,
|
|
],
|
|
`when transferring [TransformStream, MessagePort, ReadableStream, MessagePort, WritableStream, ReadableStream, WritableStream, TransformStream] but with the data having different order`
|
|
);
|
|
}
|
|
|
|
async function mixedTransferMessagePortWith() {
|
|
await mixedTransferMessagePortWithOrder1();
|
|
await mixedTransferMessagePortWithOrder2();
|
|
await mixedTransferMessagePortWithOrder3();
|
|
}
|
|
|
|
promise_test(async t => {
|
|
await transferMessagePortWith(ReadableStream);
|
|
}, "Transferring a MessagePort with a ReadableStream should set `.ports`");
|
|
|
|
promise_test(async t => {
|
|
await transferMessagePortWith(WritableStream);
|
|
}, "Transferring a MessagePort with a WritableStream should set `.ports`");
|
|
|
|
promise_test(async t => {
|
|
await transferMessagePortWith(TransformStream);
|
|
}, "Transferring a MessagePort with a TransformStream should set `.ports`");
|
|
|
|
promise_test(async t => {
|
|
await advancedTransferMessagePortWith(ReadableStream);
|
|
}, "Transferring a MessagePort with a ReadableStream should set `.ports`, advanced");
|
|
|
|
promise_test(async t => {
|
|
await advancedTransferMessagePortWith(WritableStream);
|
|
}, "Transferring a MessagePort with a WritableStream should set `.ports`, advanced");
|
|
|
|
promise_test(async t => {
|
|
await advancedTransferMessagePortWith(TransformStream);
|
|
}, "Transferring a MessagePort with a TransformStream should set `.ports`, advanced");
|
|
|
|
promise_test(async t => {
|
|
await mixedTransferMessagePortWith();
|
|
}, "Transferring a MessagePort with multiple streams should set `.ports`");
|
|
|
|
test(() => {
|
|
assert_throws_dom("DataCloneError", () =>
|
|
postMessage({ stream: new ReadableStream() }, "*")
|
|
);
|
|
}, "ReadableStream must not be serializable");
|
|
|
|
test(() => {
|
|
assert_throws_dom("DataCloneError", () =>
|
|
postMessage({ stream: new WritableStream() }, "*")
|
|
);
|
|
}, "WritableStream must not be serializable");
|
|
|
|
test(() => {
|
|
assert_throws_dom("DataCloneError", () =>
|
|
postMessage({ stream: new TransformStream() }, "*")
|
|
);
|
|
}, "TransformStream must not be serializable");
|