1'use strict'; 2 3const { mustCall, mustNotCall } = require('../common'); 4const { Readable } = require('stream'); 5const { strictEqual } = require('assert'); 6 7async function asyncSupport() { 8 const finallyMustCall = mustCall(); 9 const bodyMustCall = mustCall(); 10 11 async function* infiniteGenerate() { 12 try { 13 while (true) yield 'a'; 14 } finally { 15 finallyMustCall(); 16 } 17 } 18 19 const stream = Readable.from(infiniteGenerate()); 20 21 for await (const chunk of stream) { 22 bodyMustCall(); 23 strictEqual(chunk, 'a'); 24 break; 25 } 26} 27 28async function syncSupport() { 29 const finallyMustCall = mustCall(); 30 const bodyMustCall = mustCall(); 31 32 function* infiniteGenerate() { 33 try { 34 while (true) yield 'a'; 35 } finally { 36 finallyMustCall(); 37 } 38 } 39 40 const stream = Readable.from(infiniteGenerate()); 41 42 for await (const chunk of stream) { 43 bodyMustCall(); 44 strictEqual(chunk, 'a'); 45 break; 46 } 47} 48 49async function syncPromiseSupport() { 50 const returnMustBeAwaited = mustCall(); 51 const bodyMustCall = mustCall(); 52 53 function* infiniteGenerate() { 54 try { 55 while (true) yield Promise.resolve('a'); 56 } finally { 57 // eslint-disable-next-line no-unsafe-finally 58 return { then(cb) { 59 returnMustBeAwaited(); 60 cb(); 61 } }; 62 } 63 } 64 65 const stream = Readable.from(infiniteGenerate()); 66 67 for await (const chunk of stream) { 68 bodyMustCall(); 69 strictEqual(chunk, 'a'); 70 break; 71 } 72} 73 74async function syncRejectedSupport() { 75 const returnMustBeAwaited = mustCall(); 76 const bodyMustNotCall = mustNotCall(); 77 const catchMustCall = mustCall(); 78 const secondNextMustNotCall = mustNotCall(); 79 80 function* generate() { 81 try { 82 yield Promise.reject('a'); 83 secondNextMustNotCall(); 84 } finally { 85 // eslint-disable-next-line no-unsafe-finally 86 return { then(cb) { 87 returnMustBeAwaited(); 88 cb(); 89 } }; 90 } 91 } 92 93 const stream = Readable.from(generate()); 94 95 try { 96 for await (const chunk of stream) { 97 bodyMustNotCall(chunk); 98 } 99 } catch { 100 catchMustCall(); 101 } 102} 103 104async function noReturnAfterThrow() { 105 const returnMustNotCall = mustNotCall(); 106 const bodyMustNotCall = mustNotCall(); 107 const catchMustCall = mustCall(); 108 const nextMustCall = mustCall(); 109 110 const stream = Readable.from({ 111 [Symbol.asyncIterator]() { return this; }, 112 async next() { 113 nextMustCall(); 114 throw new Error('a'); 115 }, 116 async return() { 117 returnMustNotCall(); 118 return { done: true }; 119 }, 120 }); 121 122 try { 123 for await (const chunk of stream) { 124 bodyMustNotCall(chunk); 125 } 126 } catch { 127 catchMustCall(); 128 } 129} 130 131async function closeStreamWhileNextIsPending() { 132 const finallyMustCall = mustCall(); 133 const dataMustCall = mustCall(); 134 135 let resolveDestroy; 136 const destroyed = 137 new Promise((resolve) => { resolveDestroy = mustCall(resolve); }); 138 let resolveYielded; 139 const yielded = 140 new Promise((resolve) => { resolveYielded = mustCall(resolve); }); 141 142 async function* infiniteGenerate() { 143 try { 144 while (true) { 145 yield 'a'; 146 resolveYielded(); 147 await destroyed; 148 } 149 } finally { 150 finallyMustCall(); 151 } 152 } 153 154 const stream = Readable.from(infiniteGenerate()); 155 156 stream.on('data', (data) => { 157 dataMustCall(); 158 strictEqual(data, 'a'); 159 }); 160 161 yielded.then(() => { 162 stream.destroy(); 163 resolveDestroy(); 164 }); 165} 166 167async function closeAfterNullYielded() { 168 const finallyMustCall = mustCall(); 169 const dataMustCall = mustCall(3); 170 171 function* generate() { 172 try { 173 yield 'a'; 174 yield 'a'; 175 yield 'a'; 176 } finally { 177 finallyMustCall(); 178 } 179 } 180 181 const stream = Readable.from(generate()); 182 183 stream.on('data', (chunk) => { 184 dataMustCall(); 185 strictEqual(chunk, 'a'); 186 }); 187} 188 189Promise.all([ 190 asyncSupport(), 191 syncSupport(), 192 syncPromiseSupport(), 193 syncRejectedSupport(), 194 noReturnAfterThrow(), 195 closeStreamWhileNextIsPending(), 196 closeAfterNullYielded(), 197]).then(mustCall()); 198