• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// META: global=window,worker
2// META: script=../resources/test-utils.js
3// META: script=../resources/recording-streams.js
4'use strict';
5
6test(() => {
7
8  const rs = new ReadableStream();
9  const ws = new WritableStream();
10
11  assert_false(rs.locked, 'sanity check: the ReadableStream must not start locked');
12  assert_false(ws.locked, 'sanity check: the WritableStream must not start locked');
13
14  rs.pipeTo(ws);
15
16  assert_true(rs.locked, 'the ReadableStream must become locked');
17  assert_true(ws.locked, 'the WritableStream must become locked');
18
19}, 'Piping must lock both the ReadableStream and WritableStream');
20
21promise_test(() => {
22
23  const rs = new ReadableStream({
24    start(controller) {
25      controller.close();
26    }
27  });
28  const ws = new WritableStream();
29
30  return rs.pipeTo(ws).then(() => {
31    assert_false(rs.locked, 'the ReadableStream must become unlocked');
32    assert_false(ws.locked, 'the WritableStream must become unlocked');
33  });
34
35}, 'Piping finishing must unlock both the ReadableStream and WritableStream');
36
37promise_test(t => {
38
39  const fakeRS = Object.create(ReadableStream.prototype);
40  const ws = new WritableStream();
41
42  return methodRejects(t, ReadableStream.prototype, 'pipeTo', fakeRS, [ws]);
43
44}, 'pipeTo must check the brand of its ReadableStream this value');
45
46promise_test(t => {
47
48  const rs = new ReadableStream();
49  const fakeWS = Object.create(WritableStream.prototype);
50
51  return methodRejects(t, ReadableStream.prototype, 'pipeTo', rs, [fakeWS]);
52
53}, 'pipeTo must check the brand of its WritableStream argument');
54
55promise_test(t => {
56
57  const rs = new ReadableStream();
58  const ws = new WritableStream();
59
60  rs.getReader();
61
62  assert_true(rs.locked, 'sanity check: the ReadableStream starts locked');
63  assert_false(ws.locked, 'sanity check: the WritableStream does not start locked');
64
65  return promise_rejects_js(t, TypeError, rs.pipeTo(ws)).then(() => {
66    assert_false(ws.locked, 'the WritableStream must still be unlocked');
67  });
68
69}, 'pipeTo must fail if the ReadableStream is locked, and not lock the WritableStream');
70
71promise_test(t => {
72
73  const rs = new ReadableStream();
74  const ws = new WritableStream();
75
76  ws.getWriter();
77
78  assert_false(rs.locked, 'sanity check: the ReadableStream does not start locked');
79  assert_true(ws.locked, 'sanity check: the WritableStream starts locked');
80
81  return promise_rejects_js(t, TypeError, rs.pipeTo(ws)).then(() => {
82    assert_false(rs.locked, 'the ReadableStream must still be unlocked');
83  });
84
85}, 'pipeTo must fail if the WritableStream is locked, and not lock the ReadableStream');
86
87promise_test(() => {
88
89  const CHUNKS = 10;
90
91  const rs = new ReadableStream({
92    start(c) {
93      for (let i = 0; i < CHUNKS; ++i) {
94        c.enqueue(i);
95      }
96      c.close();
97    }
98  });
99
100  const written = [];
101  const ws = new WritableStream({
102    write(chunk) {
103      written.push(chunk);
104    },
105    close() {
106      written.push('closed');
107    }
108  }, new CountQueuingStrategy({ highWaterMark: CHUNKS }));
109
110  return rs.pipeTo(ws).then(() => {
111    const targetValues = [];
112    for (let i = 0; i < CHUNKS; ++i) {
113      targetValues.push(i);
114    }
115    targetValues.push('closed');
116
117    assert_array_equals(written, targetValues, 'the correct values must be written');
118
119    // Ensure both readable and writable are closed by the time the pipe finishes.
120    return Promise.all([
121      rs.getReader().closed,
122      ws.getWriter().closed
123    ]);
124  });
125
126  // NOTE: no requirement on *when* the pipe finishes; that is left to implementations.
127
128}, 'Piping from a ReadableStream from which lots of chunks are synchronously readable');
129
130promise_test(t => {
131
132  let controller;
133  const rs = recordingReadableStream({
134    start(c) {
135      controller = c;
136    }
137  });
138
139  const ws = recordingWritableStream();
140
141  const pipePromise = rs.pipeTo(ws).then(() => {
142    assert_array_equals(ws.events, ['write', 'Hello', 'close']);
143  });
144
145  t.step_timeout(() => {
146    controller.enqueue('Hello');
147    t.step_timeout(() => controller.close(), 10);
148  }, 10);
149
150  return pipePromise;
151
152}, 'Piping from a ReadableStream for which a chunk becomes asynchronously readable after the pipeTo');
153
154for (const preventAbort of [true, false]) {
155  promise_test(() => {
156
157    const rs = new ReadableStream({
158      pull() {
159        return Promise.reject(undefined);
160      }
161    });
162
163    return rs.pipeTo(new WritableStream(), { preventAbort }).then(
164        () => assert_unreached('pipeTo promise should be rejected'),
165        value => assert_equals(value, undefined, 'rejection value should be undefined'));
166
167  }, `an undefined rejection from pull should cause pipeTo() to reject when preventAbort is ${preventAbort}`);
168}
169
170for (const preventCancel of [true, false]) {
171  promise_test(() => {
172
173    const rs = new ReadableStream({
174      pull(controller) {
175        controller.enqueue(0);
176      }
177    });
178
179    const ws = new WritableStream({
180      write() {
181        return Promise.reject(undefined);
182      }
183    });
184
185    return rs.pipeTo(ws, { preventCancel }).then(
186         () => assert_unreached('pipeTo promise should be rejected'),
187        value => assert_equals(value, undefined, 'rejection value should be undefined'));
188
189  }, `an undefined rejection from write should cause pipeTo() to reject when preventCancel is ${preventCancel}`);
190}
191
192promise_test(t => {
193  const rs = new ReadableStream();
194  const ws = new WritableStream();
195  return promise_rejects_js(t, TypeError, rs.pipeTo(ws, {
196    get preventAbort() {
197      ws.getWriter();
198    }
199  }), 'pipeTo should reject');
200}, 'pipeTo() should reject if an option getter grabs a writer');
201
202promise_test(t => {
203  const rs = new ReadableStream({
204    start(controller) {
205      controller.close();
206    }
207  });
208  const ws = new WritableStream();
209
210  return rs.pipeTo(ws, null);
211}, 'pipeTo() promise should resolve if null is passed');
212