• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"use strict";
2
3function 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
15async 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
39async 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
48async 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
57async 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
66async 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
75async 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
84async 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
93async 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
102async function transferMessagePortWith(constructor) {
103  await transferMessagePortWithOrder1(new constructor());
104  await transferMessagePortWithOrder2(new constructor());
105  await transferMessagePortWithOrder3(new constructor());
106}
107
108async function advancedTransferMesagePortWith(constructor) {
109  await transferMessagePortWithOrder4(new constructor());
110  await transferMessagePortWithOrder5(new constructor());
111  await transferMessagePortWithOrder6(new constructor());
112  await transferMessagePortWithOrder7(new constructor());
113}
114
115async 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
133async 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
145async 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
169async function mixedTransferMesagePortWith() {
170  await mixedTransferMessagePortWithOrder1();
171  await mixedTransferMessagePortWithOrder2();
172  await mixedTransferMessagePortWithOrder3();
173}
174
175promise_test(async t => {
176  await transferMessagePortWith(ReadableStream);
177}, "Transferring a MessagePort with a ReadableStream should set `.ports`");
178
179promise_test(async t => {
180  await transferMessagePortWith(WritableStream);
181}, "Transferring a MessagePort with a WritableStream should set `.ports`");
182
183promise_test(async t => {
184  await transferMessagePortWith(TransformStream);
185}, "Transferring a MessagePort with a TransformStream should set `.ports`");
186
187promise_test(async t => {
188  await transferMessagePortWith(ReadableStream);
189}, "Transferring a MessagePort with a ReadableStream should set `.ports`, advanced");
190
191promise_test(async t => {
192  await transferMessagePortWith(WritableStream);
193}, "Transferring a MessagePort with a WritableStream should set `.ports`, advanced");
194
195promise_test(async t => {
196  await transferMessagePortWith(TransformStream);
197}, "Transferring a MessagePort with a TransformStream should set `.ports`, advanced");
198
199promise_test(async t => {
200  await mixedTransferMesagePortWith();
201}, "Transferring a MessagePort with multiple streams should set `.ports`");
202
203test(() => {
204  assert_throws_dom("DataCloneError", () =>
205    postMessage({ stream: new ReadableStream() }, "*")
206  );
207}, "ReadableStream must not be serializable");
208
209test(() => {
210  assert_throws_dom("DataCloneError", () =>
211    postMessage({ stream: new WritableStream() }, "*")
212  );
213}, "WritableStream must not be serializable");
214
215test(() => {
216  assert_throws_dom("DataCloneError", () =>
217    postMessage({ stream: new TransformStream() }, "*")
218  );
219}, "TransformStream must not be serializable");
220