11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst common = require('../common'); 41cb0ef41Sopenharmony_ciconst { 51cb0ef41Sopenharmony_ci Writable, 61cb0ef41Sopenharmony_ci Readable, 71cb0ef41Sopenharmony_ci Transform, 81cb0ef41Sopenharmony_ci finished, 91cb0ef41Sopenharmony_ci Duplex, 101cb0ef41Sopenharmony_ci PassThrough, 111cb0ef41Sopenharmony_ci Stream, 121cb0ef41Sopenharmony_ci} = require('stream'); 131cb0ef41Sopenharmony_ciconst assert = require('assert'); 141cb0ef41Sopenharmony_ciconst EE = require('events'); 151cb0ef41Sopenharmony_ciconst fs = require('fs'); 161cb0ef41Sopenharmony_ciconst { promisify } = require('util'); 171cb0ef41Sopenharmony_ciconst http = require('http'); 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ci{ 201cb0ef41Sopenharmony_ci const rs = new Readable({ 211cb0ef41Sopenharmony_ci read() {} 221cb0ef41Sopenharmony_ci }); 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci finished(rs, common.mustSucceed()); 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ci rs.push(null); 271cb0ef41Sopenharmony_ci rs.resume(); 281cb0ef41Sopenharmony_ci} 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci{ 311cb0ef41Sopenharmony_ci const ws = new Writable({ 321cb0ef41Sopenharmony_ci write(data, enc, cb) { 331cb0ef41Sopenharmony_ci cb(); 341cb0ef41Sopenharmony_ci } 351cb0ef41Sopenharmony_ci }); 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci finished(ws, common.mustSucceed()); 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci ws.end(); 401cb0ef41Sopenharmony_ci} 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci{ 431cb0ef41Sopenharmony_ci const tr = new Transform({ 441cb0ef41Sopenharmony_ci transform(data, enc, cb) { 451cb0ef41Sopenharmony_ci cb(); 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci }); 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci let finish = false; 501cb0ef41Sopenharmony_ci let ended = false; 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci tr.on('end', () => { 531cb0ef41Sopenharmony_ci ended = true; 541cb0ef41Sopenharmony_ci }); 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci tr.on('finish', () => { 571cb0ef41Sopenharmony_ci finish = true; 581cb0ef41Sopenharmony_ci }); 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci finished(tr, common.mustSucceed(() => { 611cb0ef41Sopenharmony_ci assert(finish); 621cb0ef41Sopenharmony_ci assert(ended); 631cb0ef41Sopenharmony_ci })); 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci tr.end(); 661cb0ef41Sopenharmony_ci tr.resume(); 671cb0ef41Sopenharmony_ci} 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci{ 701cb0ef41Sopenharmony_ci const rs = fs.createReadStream(__filename); 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci rs.resume(); 731cb0ef41Sopenharmony_ci finished(rs, common.mustCall()); 741cb0ef41Sopenharmony_ci} 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci{ 771cb0ef41Sopenharmony_ci const finishedPromise = promisify(finished); 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci async function run() { 801cb0ef41Sopenharmony_ci const rs = fs.createReadStream(__filename); 811cb0ef41Sopenharmony_ci const done = common.mustCall(); 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci let ended = false; 841cb0ef41Sopenharmony_ci rs.resume(); 851cb0ef41Sopenharmony_ci rs.on('end', () => { 861cb0ef41Sopenharmony_ci ended = true; 871cb0ef41Sopenharmony_ci }); 881cb0ef41Sopenharmony_ci await finishedPromise(rs); 891cb0ef41Sopenharmony_ci assert(ended); 901cb0ef41Sopenharmony_ci done(); 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci run(); 941cb0ef41Sopenharmony_ci} 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci{ 971cb0ef41Sopenharmony_ci // Check pre-cancelled 981cb0ef41Sopenharmony_ci const signal = new EventTarget(); 991cb0ef41Sopenharmony_ci signal.aborted = true; 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci const rs = Readable.from((function* () {})()); 1021cb0ef41Sopenharmony_ci finished(rs, { signal }, common.mustCall((err) => { 1031cb0ef41Sopenharmony_ci assert.strictEqual(err.name, 'AbortError'); 1041cb0ef41Sopenharmony_ci })); 1051cb0ef41Sopenharmony_ci} 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci{ 1081cb0ef41Sopenharmony_ci // Check cancelled before the stream ends sync. 1091cb0ef41Sopenharmony_ci const ac = new AbortController(); 1101cb0ef41Sopenharmony_ci const { signal } = ac; 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci const rs = Readable.from((function* () {})()); 1131cb0ef41Sopenharmony_ci finished(rs, { signal }, common.mustCall((err) => { 1141cb0ef41Sopenharmony_ci assert.strictEqual(err.name, 'AbortError'); 1151cb0ef41Sopenharmony_ci })); 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci ac.abort(); 1181cb0ef41Sopenharmony_ci} 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci{ 1211cb0ef41Sopenharmony_ci // Check cancelled before the stream ends async. 1221cb0ef41Sopenharmony_ci const ac = new AbortController(); 1231cb0ef41Sopenharmony_ci const { signal } = ac; 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci const rs = Readable.from((function* () {})()); 1261cb0ef41Sopenharmony_ci setTimeout(() => ac.abort(), 1); 1271cb0ef41Sopenharmony_ci finished(rs, { signal }, common.mustCall((err) => { 1281cb0ef41Sopenharmony_ci assert.strictEqual(err.name, 'AbortError'); 1291cb0ef41Sopenharmony_ci })); 1301cb0ef41Sopenharmony_ci} 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci{ 1331cb0ef41Sopenharmony_ci // Check cancelled after doesn't throw. 1341cb0ef41Sopenharmony_ci const ac = new AbortController(); 1351cb0ef41Sopenharmony_ci const { signal } = ac; 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci const rs = Readable.from((function* () { 1381cb0ef41Sopenharmony_ci yield 5; 1391cb0ef41Sopenharmony_ci setImmediate(() => ac.abort()); 1401cb0ef41Sopenharmony_ci })()); 1411cb0ef41Sopenharmony_ci rs.resume(); 1421cb0ef41Sopenharmony_ci finished(rs, { signal }, common.mustSucceed()); 1431cb0ef41Sopenharmony_ci} 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci{ 1461cb0ef41Sopenharmony_ci // Promisified abort works 1471cb0ef41Sopenharmony_ci const finishedPromise = promisify(finished); 1481cb0ef41Sopenharmony_ci async function run() { 1491cb0ef41Sopenharmony_ci const ac = new AbortController(); 1501cb0ef41Sopenharmony_ci const { signal } = ac; 1511cb0ef41Sopenharmony_ci const rs = Readable.from((function* () {})()); 1521cb0ef41Sopenharmony_ci setImmediate(() => ac.abort()); 1531cb0ef41Sopenharmony_ci await finishedPromise(rs, { signal }); 1541cb0ef41Sopenharmony_ci } 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci assert.rejects(run, { name: 'AbortError' }).then(common.mustCall()); 1571cb0ef41Sopenharmony_ci} 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci{ 1601cb0ef41Sopenharmony_ci // Promisified pre-aborted works 1611cb0ef41Sopenharmony_ci const finishedPromise = promisify(finished); 1621cb0ef41Sopenharmony_ci async function run() { 1631cb0ef41Sopenharmony_ci const signal = new EventTarget(); 1641cb0ef41Sopenharmony_ci signal.aborted = true; 1651cb0ef41Sopenharmony_ci const rs = Readable.from((function* () {})()); 1661cb0ef41Sopenharmony_ci await finishedPromise(rs, { signal }); 1671cb0ef41Sopenharmony_ci } 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci assert.rejects(run, { name: 'AbortError' }).then(common.mustCall()); 1701cb0ef41Sopenharmony_ci} 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci{ 1741cb0ef41Sopenharmony_ci const rs = fs.createReadStream('file-does-not-exist'); 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci finished(rs, common.expectsError({ 1771cb0ef41Sopenharmony_ci code: 'ENOENT' 1781cb0ef41Sopenharmony_ci })); 1791cb0ef41Sopenharmony_ci} 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci{ 1821cb0ef41Sopenharmony_ci const rs = new Readable(); 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ci finished(rs, common.mustSucceed()); 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci rs.push(null); 1871cb0ef41Sopenharmony_ci rs.emit('close'); // Should not trigger an error 1881cb0ef41Sopenharmony_ci rs.resume(); 1891cb0ef41Sopenharmony_ci} 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_ci{ 1921cb0ef41Sopenharmony_ci const rs = new Readable(); 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci finished(rs, common.mustCall((err) => { 1951cb0ef41Sopenharmony_ci assert(err, 'premature close error'); 1961cb0ef41Sopenharmony_ci })); 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci rs.emit('close'); // Should trigger error 1991cb0ef41Sopenharmony_ci rs.push(null); 2001cb0ef41Sopenharmony_ci rs.resume(); 2011cb0ef41Sopenharmony_ci} 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci// Test faulty input values and options. 2041cb0ef41Sopenharmony_ci{ 2051cb0ef41Sopenharmony_ci const rs = new Readable({ 2061cb0ef41Sopenharmony_ci read() {} 2071cb0ef41Sopenharmony_ci }); 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci assert.throws( 2101cb0ef41Sopenharmony_ci () => finished(rs, 'foo'), 2111cb0ef41Sopenharmony_ci { 2121cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 2131cb0ef41Sopenharmony_ci message: /callback/ 2141cb0ef41Sopenharmony_ci } 2151cb0ef41Sopenharmony_ci ); 2161cb0ef41Sopenharmony_ci assert.throws( 2171cb0ef41Sopenharmony_ci () => finished(rs, 'foo', () => {}), 2181cb0ef41Sopenharmony_ci { 2191cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 2201cb0ef41Sopenharmony_ci message: /options/ 2211cb0ef41Sopenharmony_ci } 2221cb0ef41Sopenharmony_ci ); 2231cb0ef41Sopenharmony_ci assert.throws( 2241cb0ef41Sopenharmony_ci () => finished(rs, {}, 'foo'), 2251cb0ef41Sopenharmony_ci { 2261cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 2271cb0ef41Sopenharmony_ci message: /callback/ 2281cb0ef41Sopenharmony_ci } 2291cb0ef41Sopenharmony_ci ); 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci finished(rs, null, common.mustCall()); 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci rs.push(null); 2341cb0ef41Sopenharmony_ci rs.resume(); 2351cb0ef41Sopenharmony_ci} 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_ci// Test that calling returned function removes listeners 2381cb0ef41Sopenharmony_ci{ 2391cb0ef41Sopenharmony_ci const ws = new Writable({ 2401cb0ef41Sopenharmony_ci write(data, env, cb) { 2411cb0ef41Sopenharmony_ci cb(); 2421cb0ef41Sopenharmony_ci } 2431cb0ef41Sopenharmony_ci }); 2441cb0ef41Sopenharmony_ci const removeListener = finished(ws, common.mustNotCall()); 2451cb0ef41Sopenharmony_ci removeListener(); 2461cb0ef41Sopenharmony_ci ws.end(); 2471cb0ef41Sopenharmony_ci} 2481cb0ef41Sopenharmony_ci 2491cb0ef41Sopenharmony_ci{ 2501cb0ef41Sopenharmony_ci const rs = new Readable(); 2511cb0ef41Sopenharmony_ci const removeListeners = finished(rs, common.mustNotCall()); 2521cb0ef41Sopenharmony_ci removeListeners(); 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ci rs.emit('close'); 2551cb0ef41Sopenharmony_ci rs.push(null); 2561cb0ef41Sopenharmony_ci rs.resume(); 2571cb0ef41Sopenharmony_ci} 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci{ 2601cb0ef41Sopenharmony_ci const streamLike = new EE(); 2611cb0ef41Sopenharmony_ci streamLike.readableEnded = true; 2621cb0ef41Sopenharmony_ci streamLike.readable = true; 2631cb0ef41Sopenharmony_ci assert.throws( 2641cb0ef41Sopenharmony_ci () => { 2651cb0ef41Sopenharmony_ci finished(streamLike, () => {}); 2661cb0ef41Sopenharmony_ci }, 2671cb0ef41Sopenharmony_ci { code: 'ERR_INVALID_ARG_TYPE' } 2681cb0ef41Sopenharmony_ci ); 2691cb0ef41Sopenharmony_ci streamLike.emit('close'); 2701cb0ef41Sopenharmony_ci} 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci{ 2731cb0ef41Sopenharmony_ci const writable = new Writable({ write() {} }); 2741cb0ef41Sopenharmony_ci writable.writable = false; 2751cb0ef41Sopenharmony_ci writable.destroy(); 2761cb0ef41Sopenharmony_ci finished(writable, common.mustCall((err) => { 2771cb0ef41Sopenharmony_ci assert.strictEqual(err.code, 'ERR_STREAM_PREMATURE_CLOSE'); 2781cb0ef41Sopenharmony_ci })); 2791cb0ef41Sopenharmony_ci} 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci{ 2821cb0ef41Sopenharmony_ci const readable = new Readable(); 2831cb0ef41Sopenharmony_ci readable.readable = false; 2841cb0ef41Sopenharmony_ci readable.destroy(); 2851cb0ef41Sopenharmony_ci finished(readable, common.mustCall((err) => { 2861cb0ef41Sopenharmony_ci assert.strictEqual(err.code, 'ERR_STREAM_PREMATURE_CLOSE'); 2871cb0ef41Sopenharmony_ci })); 2881cb0ef41Sopenharmony_ci} 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci{ 2911cb0ef41Sopenharmony_ci const w = new Writable({ 2921cb0ef41Sopenharmony_ci write(chunk, encoding, callback) { 2931cb0ef41Sopenharmony_ci setImmediate(callback); 2941cb0ef41Sopenharmony_ci } 2951cb0ef41Sopenharmony_ci }); 2961cb0ef41Sopenharmony_ci finished(w, common.mustCall((err) => { 2971cb0ef41Sopenharmony_ci assert.strictEqual(err.code, 'ERR_STREAM_PREMATURE_CLOSE'); 2981cb0ef41Sopenharmony_ci })); 2991cb0ef41Sopenharmony_ci w.end('asd'); 3001cb0ef41Sopenharmony_ci w.destroy(); 3011cb0ef41Sopenharmony_ci} 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_cifunction testClosed(factory) { 3041cb0ef41Sopenharmony_ci { 3051cb0ef41Sopenharmony_ci // If already destroyed but finished is cancelled in same tick 3061cb0ef41Sopenharmony_ci // don't invoke the callback, 3071cb0ef41Sopenharmony_ci 3081cb0ef41Sopenharmony_ci const s = factory(); 3091cb0ef41Sopenharmony_ci s.destroy(); 3101cb0ef41Sopenharmony_ci const dispose = finished(s, common.mustNotCall()); 3111cb0ef41Sopenharmony_ci dispose(); 3121cb0ef41Sopenharmony_ci } 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ci { 3151cb0ef41Sopenharmony_ci // If already destroyed invoked callback. 3161cb0ef41Sopenharmony_ci 3171cb0ef41Sopenharmony_ci const s = factory(); 3181cb0ef41Sopenharmony_ci s.destroy(); 3191cb0ef41Sopenharmony_ci finished(s, common.mustCall()); 3201cb0ef41Sopenharmony_ci } 3211cb0ef41Sopenharmony_ci 3221cb0ef41Sopenharmony_ci { 3231cb0ef41Sopenharmony_ci // Don't invoke until destroy has completed. 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_ci let destroyed = false; 3261cb0ef41Sopenharmony_ci const s = factory({ 3271cb0ef41Sopenharmony_ci destroy(err, cb) { 3281cb0ef41Sopenharmony_ci setImmediate(() => { 3291cb0ef41Sopenharmony_ci destroyed = true; 3301cb0ef41Sopenharmony_ci cb(); 3311cb0ef41Sopenharmony_ci }); 3321cb0ef41Sopenharmony_ci } 3331cb0ef41Sopenharmony_ci }); 3341cb0ef41Sopenharmony_ci s.destroy(); 3351cb0ef41Sopenharmony_ci finished(s, common.mustCall(() => { 3361cb0ef41Sopenharmony_ci assert.strictEqual(destroyed, true); 3371cb0ef41Sopenharmony_ci })); 3381cb0ef41Sopenharmony_ci } 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_ci { 3411cb0ef41Sopenharmony_ci // Invoke callback even if close is inhibited. 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_ci const s = factory({ 3441cb0ef41Sopenharmony_ci emitClose: false, 3451cb0ef41Sopenharmony_ci destroy(err, cb) { 3461cb0ef41Sopenharmony_ci cb(); 3471cb0ef41Sopenharmony_ci finished(s, common.mustCall()); 3481cb0ef41Sopenharmony_ci } 3491cb0ef41Sopenharmony_ci }); 3501cb0ef41Sopenharmony_ci s.destroy(); 3511cb0ef41Sopenharmony_ci } 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci { 3541cb0ef41Sopenharmony_ci // Invoke with deep async. 3551cb0ef41Sopenharmony_ci 3561cb0ef41Sopenharmony_ci const s = factory({ 3571cb0ef41Sopenharmony_ci destroy(err, cb) { 3581cb0ef41Sopenharmony_ci setImmediate(() => { 3591cb0ef41Sopenharmony_ci cb(); 3601cb0ef41Sopenharmony_ci setImmediate(() => { 3611cb0ef41Sopenharmony_ci finished(s, common.mustCall()); 3621cb0ef41Sopenharmony_ci }); 3631cb0ef41Sopenharmony_ci }); 3641cb0ef41Sopenharmony_ci } 3651cb0ef41Sopenharmony_ci }); 3661cb0ef41Sopenharmony_ci s.destroy(); 3671cb0ef41Sopenharmony_ci } 3681cb0ef41Sopenharmony_ci} 3691cb0ef41Sopenharmony_ci 3701cb0ef41Sopenharmony_citestClosed((opts) => new Readable({ ...opts })); 3711cb0ef41Sopenharmony_citestClosed((opts) => new Writable({ write() {}, ...opts })); 3721cb0ef41Sopenharmony_ci 3731cb0ef41Sopenharmony_ci{ 3741cb0ef41Sopenharmony_ci const w = new Writable({ 3751cb0ef41Sopenharmony_ci write(chunk, encoding, cb) { 3761cb0ef41Sopenharmony_ci cb(); 3771cb0ef41Sopenharmony_ci }, 3781cb0ef41Sopenharmony_ci autoDestroy: false 3791cb0ef41Sopenharmony_ci }); 3801cb0ef41Sopenharmony_ci w.end('asd'); 3811cb0ef41Sopenharmony_ci process.nextTick(() => { 3821cb0ef41Sopenharmony_ci finished(w, common.mustCall()); 3831cb0ef41Sopenharmony_ci }); 3841cb0ef41Sopenharmony_ci} 3851cb0ef41Sopenharmony_ci 3861cb0ef41Sopenharmony_ci{ 3871cb0ef41Sopenharmony_ci const w = new Writable({ 3881cb0ef41Sopenharmony_ci write(chunk, encoding, cb) { 3891cb0ef41Sopenharmony_ci cb(new Error()); 3901cb0ef41Sopenharmony_ci }, 3911cb0ef41Sopenharmony_ci autoDestroy: false 3921cb0ef41Sopenharmony_ci }); 3931cb0ef41Sopenharmony_ci w.write('asd'); 3941cb0ef41Sopenharmony_ci w.on('error', common.mustCall(() => { 3951cb0ef41Sopenharmony_ci finished(w, common.mustCall()); 3961cb0ef41Sopenharmony_ci })); 3971cb0ef41Sopenharmony_ci} 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ci{ 4001cb0ef41Sopenharmony_ci const r = new Readable({ 4011cb0ef41Sopenharmony_ci autoDestroy: false 4021cb0ef41Sopenharmony_ci }); 4031cb0ef41Sopenharmony_ci r.push(null); 4041cb0ef41Sopenharmony_ci r.resume(); 4051cb0ef41Sopenharmony_ci r.on('end', common.mustCall(() => { 4061cb0ef41Sopenharmony_ci finished(r, common.mustCall()); 4071cb0ef41Sopenharmony_ci })); 4081cb0ef41Sopenharmony_ci} 4091cb0ef41Sopenharmony_ci 4101cb0ef41Sopenharmony_ci{ 4111cb0ef41Sopenharmony_ci const rs = fs.createReadStream(__filename, { autoClose: false }); 4121cb0ef41Sopenharmony_ci rs.resume(); 4131cb0ef41Sopenharmony_ci rs.on('close', common.mustNotCall()); 4141cb0ef41Sopenharmony_ci rs.on('end', common.mustCall(() => { 4151cb0ef41Sopenharmony_ci finished(rs, common.mustCall()); 4161cb0ef41Sopenharmony_ci })); 4171cb0ef41Sopenharmony_ci} 4181cb0ef41Sopenharmony_ci 4191cb0ef41Sopenharmony_ci{ 4201cb0ef41Sopenharmony_ci const d = new EE(); 4211cb0ef41Sopenharmony_ci d._writableState = {}; 4221cb0ef41Sopenharmony_ci d._writableState.finished = true; 4231cb0ef41Sopenharmony_ci finished(d, { readable: false, writable: true }, common.mustCall((err) => { 4241cb0ef41Sopenharmony_ci assert.strictEqual(err.code, 'ERR_STREAM_PREMATURE_CLOSE'); 4251cb0ef41Sopenharmony_ci })); 4261cb0ef41Sopenharmony_ci d._writableState.errored = true; 4271cb0ef41Sopenharmony_ci d.emit('close'); 4281cb0ef41Sopenharmony_ci} 4291cb0ef41Sopenharmony_ci 4301cb0ef41Sopenharmony_ci{ 4311cb0ef41Sopenharmony_ci const r = new Readable(); 4321cb0ef41Sopenharmony_ci finished(r, common.mustCall((err) => { 4331cb0ef41Sopenharmony_ci assert.strictEqual(err.code, 'ERR_STREAM_PREMATURE_CLOSE'); 4341cb0ef41Sopenharmony_ci })); 4351cb0ef41Sopenharmony_ci r.push('asd'); 4361cb0ef41Sopenharmony_ci r.push(null); 4371cb0ef41Sopenharmony_ci r.destroy(); 4381cb0ef41Sopenharmony_ci} 4391cb0ef41Sopenharmony_ci 4401cb0ef41Sopenharmony_ci{ 4411cb0ef41Sopenharmony_ci const d = new Duplex({ 4421cb0ef41Sopenharmony_ci final(cb) { }, // Never close writable side for test purpose 4431cb0ef41Sopenharmony_ci read() { 4441cb0ef41Sopenharmony_ci this.push(null); 4451cb0ef41Sopenharmony_ci } 4461cb0ef41Sopenharmony_ci }); 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_ci d.on('end', common.mustCall()); 4491cb0ef41Sopenharmony_ci 4501cb0ef41Sopenharmony_ci finished(d, { readable: true, writable: false }, common.mustCall()); 4511cb0ef41Sopenharmony_ci 4521cb0ef41Sopenharmony_ci d.end(); 4531cb0ef41Sopenharmony_ci d.resume(); 4541cb0ef41Sopenharmony_ci} 4551cb0ef41Sopenharmony_ci 4561cb0ef41Sopenharmony_ci{ 4571cb0ef41Sopenharmony_ci const d = new Duplex({ 4581cb0ef41Sopenharmony_ci final(cb) { }, // Never close writable side for test purpose 4591cb0ef41Sopenharmony_ci read() { 4601cb0ef41Sopenharmony_ci this.push(null); 4611cb0ef41Sopenharmony_ci } 4621cb0ef41Sopenharmony_ci }); 4631cb0ef41Sopenharmony_ci 4641cb0ef41Sopenharmony_ci d.on('end', common.mustCall()); 4651cb0ef41Sopenharmony_ci 4661cb0ef41Sopenharmony_ci d.end(); 4671cb0ef41Sopenharmony_ci finished(d, { readable: true, writable: false }, common.mustCall()); 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_ci d.resume(); 4701cb0ef41Sopenharmony_ci} 4711cb0ef41Sopenharmony_ci 4721cb0ef41Sopenharmony_ci{ 4731cb0ef41Sopenharmony_ci // Test for compat for e.g. fd-slicer which implements 4741cb0ef41Sopenharmony_ci // non standard destroy behavior which might not emit 4751cb0ef41Sopenharmony_ci // 'close'. 4761cb0ef41Sopenharmony_ci const r = new Readable(); 4771cb0ef41Sopenharmony_ci finished(r, common.mustCall()); 4781cb0ef41Sopenharmony_ci r.resume(); 4791cb0ef41Sopenharmony_ci r.push('asd'); 4801cb0ef41Sopenharmony_ci r.destroyed = true; 4811cb0ef41Sopenharmony_ci r.push(null); 4821cb0ef41Sopenharmony_ci} 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci{ 4851cb0ef41Sopenharmony_ci // Regression https://github.com/nodejs/node/issues/33130 4861cb0ef41Sopenharmony_ci const response = new PassThrough(); 4871cb0ef41Sopenharmony_ci 4881cb0ef41Sopenharmony_ci class HelloWorld extends Duplex { 4891cb0ef41Sopenharmony_ci constructor(response) { 4901cb0ef41Sopenharmony_ci super({ 4911cb0ef41Sopenharmony_ci autoDestroy: false 4921cb0ef41Sopenharmony_ci }); 4931cb0ef41Sopenharmony_ci 4941cb0ef41Sopenharmony_ci this.response = response; 4951cb0ef41Sopenharmony_ci this.readMore = false; 4961cb0ef41Sopenharmony_ci 4971cb0ef41Sopenharmony_ci response.once('end', () => { 4981cb0ef41Sopenharmony_ci this.push(null); 4991cb0ef41Sopenharmony_ci }); 5001cb0ef41Sopenharmony_ci 5011cb0ef41Sopenharmony_ci response.on('readable', () => { 5021cb0ef41Sopenharmony_ci if (this.readMore) { 5031cb0ef41Sopenharmony_ci this._read(); 5041cb0ef41Sopenharmony_ci } 5051cb0ef41Sopenharmony_ci }); 5061cb0ef41Sopenharmony_ci } 5071cb0ef41Sopenharmony_ci 5081cb0ef41Sopenharmony_ci _read() { 5091cb0ef41Sopenharmony_ci const { response } = this; 5101cb0ef41Sopenharmony_ci 5111cb0ef41Sopenharmony_ci this.readMore = true; 5121cb0ef41Sopenharmony_ci 5131cb0ef41Sopenharmony_ci if (response.readableLength) { 5141cb0ef41Sopenharmony_ci this.readMore = false; 5151cb0ef41Sopenharmony_ci } 5161cb0ef41Sopenharmony_ci 5171cb0ef41Sopenharmony_ci let data; 5181cb0ef41Sopenharmony_ci while ((data = response.read()) !== null) { 5191cb0ef41Sopenharmony_ci this.push(data); 5201cb0ef41Sopenharmony_ci } 5211cb0ef41Sopenharmony_ci } 5221cb0ef41Sopenharmony_ci } 5231cb0ef41Sopenharmony_ci 5241cb0ef41Sopenharmony_ci const instance = new HelloWorld(response); 5251cb0ef41Sopenharmony_ci instance.setEncoding('utf8'); 5261cb0ef41Sopenharmony_ci instance.end(); 5271cb0ef41Sopenharmony_ci 5281cb0ef41Sopenharmony_ci (async () => { 5291cb0ef41Sopenharmony_ci await EE.once(instance, 'finish'); 5301cb0ef41Sopenharmony_ci 5311cb0ef41Sopenharmony_ci setImmediate(() => { 5321cb0ef41Sopenharmony_ci response.write('chunk 1'); 5331cb0ef41Sopenharmony_ci response.write('chunk 2'); 5341cb0ef41Sopenharmony_ci response.write('chunk 3'); 5351cb0ef41Sopenharmony_ci response.end(); 5361cb0ef41Sopenharmony_ci }); 5371cb0ef41Sopenharmony_ci 5381cb0ef41Sopenharmony_ci let res = ''; 5391cb0ef41Sopenharmony_ci for await (const data of instance) { 5401cb0ef41Sopenharmony_ci res += data; 5411cb0ef41Sopenharmony_ci } 5421cb0ef41Sopenharmony_ci 5431cb0ef41Sopenharmony_ci assert.strictEqual(res, 'chunk 1chunk 2chunk 3'); 5441cb0ef41Sopenharmony_ci })().then(common.mustCall()); 5451cb0ef41Sopenharmony_ci} 5461cb0ef41Sopenharmony_ci 5471cb0ef41Sopenharmony_ci{ 5481cb0ef41Sopenharmony_ci const p = new PassThrough(); 5491cb0ef41Sopenharmony_ci p.end(); 5501cb0ef41Sopenharmony_ci finished(p, common.mustNotCall()); 5511cb0ef41Sopenharmony_ci} 5521cb0ef41Sopenharmony_ci 5531cb0ef41Sopenharmony_ci{ 5541cb0ef41Sopenharmony_ci const p = new PassThrough(); 5551cb0ef41Sopenharmony_ci p.end(); 5561cb0ef41Sopenharmony_ci p.on('finish', common.mustCall(() => { 5571cb0ef41Sopenharmony_ci finished(p, common.mustNotCall()); 5581cb0ef41Sopenharmony_ci })); 5591cb0ef41Sopenharmony_ci} 5601cb0ef41Sopenharmony_ci 5611cb0ef41Sopenharmony_ci{ 5621cb0ef41Sopenharmony_ci const server = http.createServer(common.mustCall((req, res) => { 5631cb0ef41Sopenharmony_ci res.on('close', common.mustCall(() => { 5641cb0ef41Sopenharmony_ci finished(res, common.mustCall(() => { 5651cb0ef41Sopenharmony_ci server.close(); 5661cb0ef41Sopenharmony_ci })); 5671cb0ef41Sopenharmony_ci })); 5681cb0ef41Sopenharmony_ci res.end(); 5691cb0ef41Sopenharmony_ci })) 5701cb0ef41Sopenharmony_ci .listen(0, function() { 5711cb0ef41Sopenharmony_ci http.request({ 5721cb0ef41Sopenharmony_ci method: 'GET', 5731cb0ef41Sopenharmony_ci port: this.address().port 5741cb0ef41Sopenharmony_ci }).end() 5751cb0ef41Sopenharmony_ci .on('response', common.mustCall()); 5761cb0ef41Sopenharmony_ci }); 5771cb0ef41Sopenharmony_ci} 5781cb0ef41Sopenharmony_ci 5791cb0ef41Sopenharmony_ci{ 5801cb0ef41Sopenharmony_ci const server = http.createServer(common.mustCall((req, res) => { 5811cb0ef41Sopenharmony_ci req.on('close', common.mustCall(() => { 5821cb0ef41Sopenharmony_ci finished(req, common.mustCall(() => { 5831cb0ef41Sopenharmony_ci server.close(); 5841cb0ef41Sopenharmony_ci })); 5851cb0ef41Sopenharmony_ci })); 5861cb0ef41Sopenharmony_ci req.destroy(); 5871cb0ef41Sopenharmony_ci })).listen(0, function() { 5881cb0ef41Sopenharmony_ci http.request({ 5891cb0ef41Sopenharmony_ci method: 'GET', 5901cb0ef41Sopenharmony_ci port: this.address().port 5911cb0ef41Sopenharmony_ci }).end().on('error', common.mustCall()); 5921cb0ef41Sopenharmony_ci }); 5931cb0ef41Sopenharmony_ci} 5941cb0ef41Sopenharmony_ci 5951cb0ef41Sopenharmony_ci{ 5961cb0ef41Sopenharmony_ci const w = new Writable({ 5971cb0ef41Sopenharmony_ci write(chunk, encoding, callback) { 5981cb0ef41Sopenharmony_ci process.nextTick(callback); 5991cb0ef41Sopenharmony_ci } 6001cb0ef41Sopenharmony_ci }); 6011cb0ef41Sopenharmony_ci w.aborted = false; 6021cb0ef41Sopenharmony_ci w.end(); 6031cb0ef41Sopenharmony_ci let closed = false; 6041cb0ef41Sopenharmony_ci w.on('finish', () => { 6051cb0ef41Sopenharmony_ci assert.strictEqual(closed, false); 6061cb0ef41Sopenharmony_ci w.emit('aborted'); 6071cb0ef41Sopenharmony_ci }); 6081cb0ef41Sopenharmony_ci w.on('close', common.mustCall(() => { 6091cb0ef41Sopenharmony_ci closed = true; 6101cb0ef41Sopenharmony_ci })); 6111cb0ef41Sopenharmony_ci 6121cb0ef41Sopenharmony_ci finished(w, common.mustCall(() => { 6131cb0ef41Sopenharmony_ci assert.strictEqual(closed, true); 6141cb0ef41Sopenharmony_ci })); 6151cb0ef41Sopenharmony_ci} 6161cb0ef41Sopenharmony_ci 6171cb0ef41Sopenharmony_ci{ 6181cb0ef41Sopenharmony_ci const w = new Writable(); 6191cb0ef41Sopenharmony_ci const _err = new Error(); 6201cb0ef41Sopenharmony_ci w.destroy(_err); 6211cb0ef41Sopenharmony_ci assert.strictEqual(w.errored, _err); 6221cb0ef41Sopenharmony_ci finished(w, common.mustCall((err) => { 6231cb0ef41Sopenharmony_ci assert.strictEqual(_err, err); 6241cb0ef41Sopenharmony_ci assert.strictEqual(w.closed, true); 6251cb0ef41Sopenharmony_ci finished(w, common.mustCall((err) => { 6261cb0ef41Sopenharmony_ci assert.strictEqual(_err, err); 6271cb0ef41Sopenharmony_ci })); 6281cb0ef41Sopenharmony_ci })); 6291cb0ef41Sopenharmony_ci} 6301cb0ef41Sopenharmony_ci 6311cb0ef41Sopenharmony_ci{ 6321cb0ef41Sopenharmony_ci const w = new Writable(); 6331cb0ef41Sopenharmony_ci w.destroy(); 6341cb0ef41Sopenharmony_ci assert.strictEqual(w.errored, null); 6351cb0ef41Sopenharmony_ci finished(w, common.mustCall((err) => { 6361cb0ef41Sopenharmony_ci assert.strictEqual(w.closed, true); 6371cb0ef41Sopenharmony_ci assert.strictEqual(err.code, 'ERR_STREAM_PREMATURE_CLOSE'); 6381cb0ef41Sopenharmony_ci finished(w, common.mustCall((err) => { 6391cb0ef41Sopenharmony_ci assert.strictEqual(err.code, 'ERR_STREAM_PREMATURE_CLOSE'); 6401cb0ef41Sopenharmony_ci })); 6411cb0ef41Sopenharmony_ci })); 6421cb0ef41Sopenharmony_ci} 6431cb0ef41Sopenharmony_ci 6441cb0ef41Sopenharmony_ci{ 6451cb0ef41Sopenharmony_ci // Legacy Streams do not inherit from Readable or Writable. 6461cb0ef41Sopenharmony_ci // We cannot really assume anything about them, so we cannot close them 6471cb0ef41Sopenharmony_ci // automatically. 6481cb0ef41Sopenharmony_ci const s = new Stream(); 6491cb0ef41Sopenharmony_ci finished(s, common.mustNotCall()); 6501cb0ef41Sopenharmony_ci} 6511cb0ef41Sopenharmony_ci 6521cb0ef41Sopenharmony_ci{ 6531cb0ef41Sopenharmony_ci const server = http.createServer(common.mustCall(function(req, res) { 6541cb0ef41Sopenharmony_ci fs.createReadStream(__filename).pipe(res); 6551cb0ef41Sopenharmony_ci finished(res, common.mustCall(function(err) { 6561cb0ef41Sopenharmony_ci assert.strictEqual(err, undefined); 6571cb0ef41Sopenharmony_ci })); 6581cb0ef41Sopenharmony_ci })).listen(0, function() { 6591cb0ef41Sopenharmony_ci http.request( 6601cb0ef41Sopenharmony_ci { method: 'GET', port: this.address().port }, 6611cb0ef41Sopenharmony_ci common.mustCall(function(res) { 6621cb0ef41Sopenharmony_ci res.resume(); 6631cb0ef41Sopenharmony_ci finished(res, common.mustCall(() => { 6641cb0ef41Sopenharmony_ci server.close(); 6651cb0ef41Sopenharmony_ci })); 6661cb0ef41Sopenharmony_ci }) 6671cb0ef41Sopenharmony_ci ).end(); 6681cb0ef41Sopenharmony_ci }); 6691cb0ef41Sopenharmony_ci} 6701cb0ef41Sopenharmony_ci 6711cb0ef41Sopenharmony_ci{ 6721cb0ef41Sopenharmony_ci const stream = new Duplex({ 6731cb0ef41Sopenharmony_ci write(chunk, enc, cb) { 6741cb0ef41Sopenharmony_ci setImmediate(cb); 6751cb0ef41Sopenharmony_ci } 6761cb0ef41Sopenharmony_ci }); 6771cb0ef41Sopenharmony_ci 6781cb0ef41Sopenharmony_ci stream.end('foo'); 6791cb0ef41Sopenharmony_ci 6801cb0ef41Sopenharmony_ci finished(stream, { readable: false }, common.mustCall((err) => { 6811cb0ef41Sopenharmony_ci assert(!err); 6821cb0ef41Sopenharmony_ci })); 6831cb0ef41Sopenharmony_ci} 684