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