1// META: global=window,worker
2// META: script=../resources/recording-streams.js
3'use strict';
4
5const error1 = new Error('error1!');
6error1.name = 'error1';
7
8promise_test(() => {
9
10  const rs = recordingReadableStream();
11
12  const ws = recordingWritableStream();
13  const writer = ws.getWriter();
14  writer.close();
15  writer.releaseLock();
16
17  return rs.pipeTo(ws).then(
18    () => assert_unreached('the promise must not fulfill'),
19    err => {
20      assert_equals(err.name, 'TypeError', 'the promise must reject with a TypeError');
21
22      assert_array_equals(rs.eventsWithoutPulls, ['cancel', err]);
23      assert_array_equals(ws.events, ['close']);
24
25      return Promise.all([
26        rs.getReader().closed,
27        ws.getWriter().closed
28      ]);
29    }
30  );
31
32}, 'Closing must be propagated backward: starts closed; preventCancel omitted; fulfilled cancel promise');
33
34promise_test(t => {
35
36  // Our recording streams do not deal well with errors generated by the system, so give them some help
37  let recordedError;
38  const rs = recordingReadableStream({
39    cancel(cancelErr) {
40      recordedError = cancelErr;
41      throw error1;
42    }
43  });
44
45  const ws = recordingWritableStream();
46  const writer = ws.getWriter();
47  writer.close();
48  writer.releaseLock();
49
50  return promise_rejects_exactly(t, error1, rs.pipeTo(ws), 'pipeTo must reject with the same error').then(() => {
51    assert_equals(recordedError.name, 'TypeError', 'the cancel reason must be a TypeError');
52
53    assert_array_equals(rs.eventsWithoutPulls, ['cancel', recordedError]);
54    assert_array_equals(ws.events, ['close']);
55
56    return Promise.all([
57      rs.getReader().closed,
58      ws.getWriter().closed
59    ]);
60  });
61
62}, 'Closing must be propagated backward: starts closed; preventCancel omitted; rejected cancel promise');
63
64for (const falsy of [undefined, null, false, +0, -0, NaN, '']) {
65  const stringVersion = Object.is(falsy, -0) ? '-0' : String(falsy);
66
67  promise_test(() => {
68
69    const rs = recordingReadableStream();
70
71    const ws = recordingWritableStream();
72    const writer = ws.getWriter();
73    writer.close();
74    writer.releaseLock();
75
76    return rs.pipeTo(ws, { preventCancel: falsy }).then(
77      () => assert_unreached('the promise must not fulfill'),
78      err => {
79        assert_equals(err.name, 'TypeError', 'the promise must reject with a TypeError');
80
81        assert_array_equals(rs.eventsWithoutPulls, ['cancel', err]);
82        assert_array_equals(ws.events, ['close']);
83
84        return Promise.all([
85          rs.getReader().closed,
86          ws.getWriter().closed
87        ]);
88      }
89    );
90
91  }, `Closing must be propagated backward: starts closed; preventCancel = ${stringVersion} (falsy); fulfilled cancel ` +
92     `promise`);
93}
94
95for (const truthy of [true, 'a', 1, Symbol(), { }]) {
96  promise_test(t => {
97
98    const rs = recordingReadableStream();
99
100    const ws = recordingWritableStream();
101    const writer = ws.getWriter();
102    writer.close();
103    writer.releaseLock();
104
105    return promise_rejects_js(t, TypeError, rs.pipeTo(ws, { preventCancel: truthy })).then(() => {
106      assert_array_equals(rs.eventsWithoutPulls, []);
107      assert_array_equals(ws.events, ['close']);
108
109      return ws.getWriter().closed;
110    });
111
112  }, `Closing must be propagated backward: starts closed; preventCancel = ${String(truthy)} (truthy)`);
113}
114
115promise_test(t => {
116
117  const rs = recordingReadableStream();
118
119  const ws = recordingWritableStream();
120  const writer = ws.getWriter();
121  writer.close();
122  writer.releaseLock();
123
124  return promise_rejects_js(t, TypeError, rs.pipeTo(ws, { preventCancel: true, preventAbort: true }))
125    .then(() => {
126      assert_array_equals(rs.eventsWithoutPulls, []);
127      assert_array_equals(ws.events, ['close']);
128
129      return ws.getWriter().closed;
130    });
131
132}, 'Closing must be propagated backward: starts closed; preventCancel = true, preventAbort = true');
133
134promise_test(t => {
135
136  const rs = recordingReadableStream();
137
138  const ws = recordingWritableStream();
139  const writer = ws.getWriter();
140  writer.close();
141  writer.releaseLock();
142
143  return promise_rejects_js(t, TypeError,
144                         rs.pipeTo(ws, { preventCancel: true, preventAbort: true, preventClose: true }))
145  .then(() => {
146    assert_array_equals(rs.eventsWithoutPulls, []);
147    assert_array_equals(ws.events, ['close']);
148
149    return ws.getWriter().closed;
150  });
151
152}, 'Closing must be propagated backward: starts closed; preventCancel = true, preventAbort = true, preventClose ' +
153   '= true');
154