1'use strict'; 2 3const common = require('../common'); 4const { Readable, addAbortSignal } = require('stream'); 5const assert = require('assert'); 6 7{ 8 const read = new Readable({ 9 read() {} 10 }); 11 read.resume(); 12 13 read.on('close', common.mustCall()); 14 15 read.destroy(); 16 assert.strictEqual(read.errored, null); 17 assert.strictEqual(read.destroyed, true); 18} 19 20{ 21 const read = new Readable({ 22 read() {} 23 }); 24 read.resume(); 25 26 const expected = new Error('kaboom'); 27 28 read.on('end', common.mustNotCall('no end event')); 29 read.on('close', common.mustCall()); 30 read.on('error', common.mustCall((err) => { 31 assert.strictEqual(err, expected); 32 })); 33 34 read.destroy(expected); 35 assert.strictEqual(read.errored, expected); 36 assert.strictEqual(read.destroyed, true); 37} 38 39{ 40 const read = new Readable({ 41 read() {} 42 }); 43 44 read._destroy = common.mustCall(function(err, cb) { 45 assert.strictEqual(err, expected); 46 cb(err); 47 }); 48 49 const expected = new Error('kaboom'); 50 51 read.on('end', common.mustNotCall('no end event')); 52 read.on('close', common.mustCall()); 53 read.on('error', common.mustCall((err) => { 54 assert.strictEqual(err, expected); 55 })); 56 57 read.destroy(expected); 58 assert.strictEqual(read.destroyed, true); 59} 60 61{ 62 const read = new Readable({ 63 read() {}, 64 destroy: common.mustCall(function(err, cb) { 65 assert.strictEqual(err, expected); 66 cb(); 67 }) 68 }); 69 70 const expected = new Error('kaboom'); 71 72 read.on('end', common.mustNotCall('no end event')); 73 74 // Error is swallowed by the custom _destroy 75 read.on('error', common.mustNotCall('no error event')); 76 read.on('close', common.mustCall()); 77 78 read.destroy(expected); 79 assert.strictEqual(read.destroyed, true); 80} 81 82{ 83 const read = new Readable({ 84 read() {} 85 }); 86 87 read._destroy = common.mustCall(function(err, cb) { 88 assert.strictEqual(err, null); 89 cb(); 90 }); 91 92 read.destroy(); 93 assert.strictEqual(read.destroyed, true); 94} 95 96{ 97 const read = new Readable({ 98 read() {} 99 }); 100 read.resume(); 101 102 read._destroy = common.mustCall(function(err, cb) { 103 assert.strictEqual(err, null); 104 process.nextTick(() => { 105 this.push(null); 106 cb(); 107 }); 108 }); 109 110 const fail = common.mustNotCall('no end event'); 111 112 read.on('end', fail); 113 read.on('close', common.mustCall()); 114 115 read.destroy(); 116 117 read.removeListener('end', fail); 118 read.on('end', common.mustNotCall()); 119 assert.strictEqual(read.destroyed, true); 120} 121 122{ 123 const read = new Readable({ 124 read() {} 125 }); 126 127 const expected = new Error('kaboom'); 128 129 read._destroy = common.mustCall(function(err, cb) { 130 assert.strictEqual(err, null); 131 cb(expected); 132 }); 133 134 let ticked = false; 135 read.on('end', common.mustNotCall('no end event')); 136 read.on('error', common.mustCall((err) => { 137 assert.strictEqual(ticked, true); 138 assert.strictEqual(read._readableState.errorEmitted, true); 139 assert.strictEqual(read._readableState.errored, expected); 140 assert.strictEqual(err, expected); 141 })); 142 143 read.destroy(); 144 assert.strictEqual(read._readableState.errorEmitted, false); 145 assert.strictEqual(read._readableState.errored, expected); 146 assert.strictEqual(read.destroyed, true); 147 ticked = true; 148} 149 150{ 151 const read = new Readable({ 152 read() {} 153 }); 154 read.resume(); 155 156 read.destroyed = true; 157 assert.strictEqual(read.destroyed, true); 158 159 // The internal destroy() mechanism should not be triggered 160 read.on('end', common.mustNotCall()); 161 read.destroy(); 162} 163 164{ 165 function MyReadable() { 166 assert.strictEqual(this.destroyed, false); 167 this.destroyed = false; 168 Readable.call(this); 169 } 170 171 Object.setPrototypeOf(MyReadable.prototype, Readable.prototype); 172 Object.setPrototypeOf(MyReadable, Readable); 173 174 new MyReadable(); 175} 176 177{ 178 // Destroy and destroy callback 179 const read = new Readable({ 180 read() {} 181 }); 182 read.resume(); 183 184 const expected = new Error('kaboom'); 185 186 let ticked = false; 187 read.on('close', common.mustCall(() => { 188 assert.strictEqual(read._readableState.errorEmitted, true); 189 assert.strictEqual(ticked, true); 190 })); 191 read.on('error', common.mustCall((err) => { 192 assert.strictEqual(err, expected); 193 })); 194 195 assert.strictEqual(read._readableState.errored, null); 196 assert.strictEqual(read._readableState.errorEmitted, false); 197 198 read.destroy(expected, common.mustCall(function(err) { 199 assert.strictEqual(read._readableState.errored, expected); 200 assert.strictEqual(err, expected); 201 })); 202 assert.strictEqual(read._readableState.errorEmitted, false); 203 assert.strictEqual(read._readableState.errored, expected); 204 ticked = true; 205} 206 207{ 208 const readable = new Readable({ 209 destroy: common.mustCall(function(err, cb) { 210 process.nextTick(cb, new Error('kaboom 1')); 211 }), 212 read() {} 213 }); 214 215 let ticked = false; 216 readable.on('close', common.mustCall(() => { 217 assert.strictEqual(ticked, true); 218 assert.strictEqual(readable._readableState.errorEmitted, true); 219 })); 220 readable.on('error', common.mustCall((err) => { 221 assert.strictEqual(ticked, true); 222 assert.strictEqual(err.message, 'kaboom 1'); 223 assert.strictEqual(readable._readableState.errorEmitted, true); 224 })); 225 226 readable.destroy(); 227 assert.strictEqual(readable.destroyed, true); 228 assert.strictEqual(readable._readableState.errored, null); 229 assert.strictEqual(readable._readableState.errorEmitted, false); 230 231 // Test case where `readable.destroy()` is called again with an error before 232 // the `_destroy()` callback is called. 233 readable.destroy(new Error('kaboom 2')); 234 assert.strictEqual(readable._readableState.errorEmitted, false); 235 assert.strictEqual(readable._readableState.errored, null); 236 237 ticked = true; 238} 239 240{ 241 const read = new Readable({ 242 read() {} 243 }); 244 245 read.destroy(); 246 read.push('hi'); 247 read.on('data', common.mustNotCall()); 248} 249 250{ 251 const read = new Readable({ 252 read: common.mustNotCall() 253 }); 254 read.destroy(); 255 assert.strictEqual(read.destroyed, true); 256 read.read(); 257} 258 259{ 260 const read = new Readable({ 261 autoDestroy: false, 262 read() { 263 this.push(null); 264 this.push('asd'); 265 } 266 }); 267 268 read.on('error', common.mustCall(() => { 269 assert(read._readableState.errored); 270 })); 271 read.resume(); 272} 273 274{ 275 const controller = new AbortController(); 276 const read = addAbortSignal(controller.signal, new Readable({ 277 read() { 278 this.push('asd'); 279 }, 280 })); 281 282 read.on('error', common.mustCall((e) => { 283 assert.strictEqual(e.name, 'AbortError'); 284 })); 285 controller.abort(); 286 read.on('data', common.mustNotCall()); 287} 288 289{ 290 const controller = new AbortController(); 291 const read = new Readable({ 292 signal: controller.signal, 293 read() { 294 this.push('asd'); 295 }, 296 }); 297 298 read.on('error', common.mustCall((e) => { 299 assert.strictEqual(e.name, 'AbortError'); 300 })); 301 controller.abort(); 302 read.on('data', common.mustNotCall()); 303} 304 305{ 306 const controller = new AbortController(); 307 const read = addAbortSignal(controller.signal, new Readable({ 308 objectMode: true, 309 read() { 310 return false; 311 } 312 })); 313 read.push('asd'); 314 315 read.on('error', common.mustCall((e) => { 316 assert.strictEqual(e.name, 'AbortError'); 317 })); 318 assert.rejects((async () => { 319 // eslint-disable-next-line no-unused-vars, no-empty 320 for await (const chunk of read) { } 321 })(), /AbortError/); 322 setTimeout(() => controller.abort(), 0); 323} 324 325{ 326 const read = new Readable({ 327 read() { 328 }, 329 }); 330 331 read.on('data', common.mustNotCall()); 332 read.on('error', common.mustCall((e) => { 333 read.push('asd'); 334 read.read(); 335 })); 336 read.on('close', common.mustCall((e) => { 337 read.push('asd'); 338 read.read(); 339 })); 340 read.destroy(new Error('asd')); 341} 342 343{ 344 const read = new Readable({ 345 read() { 346 }, 347 }); 348 349 read.on('data', common.mustNotCall()); 350 read.on('close', common.mustCall((e) => { 351 read.push('asd'); 352 read.read(); 353 })); 354 read.destroy(); 355} 356 357{ 358 const read = new Readable({ 359 read() { 360 }, 361 }); 362 363 read.on('data', common.mustNotCall()); 364 read.on('close', common.mustCall((e) => { 365 read.push('asd'); 366 read.unshift('asd'); 367 })); 368 read.destroy(); 369} 370 371{ 372 const read = new Readable({ 373 read() { 374 }, 375 }); 376 377 read.on('data', common.mustNotCall()); 378 read.destroy(); 379 read.unshift('asd'); 380} 381 382{ 383 const read = new Readable({ 384 read() { 385 }, 386 }); 387 388 read.resume(); 389 read.on('data', common.mustNotCall()); 390 read.on('close', common.mustCall((e) => { 391 read.push('asd'); 392 })); 393 read.destroy(); 394} 395 396{ 397 const read = new Readable({ 398 read() { 399 }, 400 }); 401 402 read.on('data', common.mustNotCall()); 403 read.destroy(); 404 read.push('asd'); 405} 406