11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst common = require('../common'); 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci// Ensure that subscribing the 'data' event will not make the stream flow. 61cb0ef41Sopenharmony_ci// The 'data' event will require calling read() by hand. 71cb0ef41Sopenharmony_ci// 81cb0ef41Sopenharmony_ci// The test is written for the (somewhat rare) highWaterMark: 0 streams to 91cb0ef41Sopenharmony_ci// specifically catch any regressions that might occur with these streams. 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ciconst assert = require('assert'); 121cb0ef41Sopenharmony_ciconst { Readable } = require('stream'); 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ciconst streamData = [ 'a', null ]; 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci// Track the calls so we can assert their order later. 171cb0ef41Sopenharmony_ciconst calls = []; 181cb0ef41Sopenharmony_ciconst r = new Readable({ 191cb0ef41Sopenharmony_ci read: common.mustCall(() => { 201cb0ef41Sopenharmony_ci calls.push('_read:' + streamData[0]); 211cb0ef41Sopenharmony_ci process.nextTick(() => { 221cb0ef41Sopenharmony_ci calls.push('push:' + streamData[0]); 231cb0ef41Sopenharmony_ci r.push(streamData.shift()); 241cb0ef41Sopenharmony_ci }); 251cb0ef41Sopenharmony_ci }, streamData.length), 261cb0ef41Sopenharmony_ci highWaterMark: 0, 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci // Object mode is used here just for testing convenience. It really 291cb0ef41Sopenharmony_ci // shouldn't affect the order of events. Just the data and its format. 301cb0ef41Sopenharmony_ci objectMode: true, 311cb0ef41Sopenharmony_ci}); 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ciassert.strictEqual(r.readableFlowing, null); 341cb0ef41Sopenharmony_cir.on('readable', common.mustCall(() => { 351cb0ef41Sopenharmony_ci calls.push('readable'); 361cb0ef41Sopenharmony_ci}, 2)); 371cb0ef41Sopenharmony_ciassert.strictEqual(r.readableFlowing, false); 381cb0ef41Sopenharmony_cir.on('data', common.mustCall((data) => { 391cb0ef41Sopenharmony_ci calls.push('data:' + data); 401cb0ef41Sopenharmony_ci}, 1)); 411cb0ef41Sopenharmony_cir.on('end', common.mustCall(() => { 421cb0ef41Sopenharmony_ci calls.push('end'); 431cb0ef41Sopenharmony_ci})); 441cb0ef41Sopenharmony_ciassert.strictEqual(r.readableFlowing, false); 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci// The stream emits the events asynchronously but that's not guaranteed to 471cb0ef41Sopenharmony_ci// happen on the next tick (especially since the _read implementation above 481cb0ef41Sopenharmony_ci// uses process.nextTick). 491cb0ef41Sopenharmony_ci// 501cb0ef41Sopenharmony_ci// We use setImmediate here to give the stream enough time to emit all the 511cb0ef41Sopenharmony_ci// events it's about to emit. 521cb0ef41Sopenharmony_cisetImmediate(() => { 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci // Only the _read, push, readable calls have happened. No data must be 551cb0ef41Sopenharmony_ci // emitted yet. 561cb0ef41Sopenharmony_ci assert.deepStrictEqual(calls, ['_read:a', 'push:a', 'readable']); 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci // Calling 'r.read()' should trigger the data event. 591cb0ef41Sopenharmony_ci assert.strictEqual(r.read(), 'a'); 601cb0ef41Sopenharmony_ci assert.deepStrictEqual( 611cb0ef41Sopenharmony_ci calls, 621cb0ef41Sopenharmony_ci ['_read:a', 'push:a', 'readable', 'data:a']); 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci // The next 'read()' will return null because hwm: 0 does not buffer any 651cb0ef41Sopenharmony_ci // data and the _read implementation above does the push() asynchronously. 661cb0ef41Sopenharmony_ci // 671cb0ef41Sopenharmony_ci // Note: This 'null' signals "no data available". It isn't the end-of-stream 681cb0ef41Sopenharmony_ci // null value as the stream doesn't know yet that it is about to reach the 691cb0ef41Sopenharmony_ci // end. 701cb0ef41Sopenharmony_ci // 711cb0ef41Sopenharmony_ci // Using setImmediate again to give the stream enough time to emit all the 721cb0ef41Sopenharmony_ci // events it wants to emit. 731cb0ef41Sopenharmony_ci assert.strictEqual(r.read(), null); 741cb0ef41Sopenharmony_ci setImmediate(() => { 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci // There's a new 'readable' event after the data has been pushed. 771cb0ef41Sopenharmony_ci // The 'end' event will be emitted only after a 'read()'. 781cb0ef41Sopenharmony_ci // 791cb0ef41Sopenharmony_ci // This is somewhat special for the case where the '_read' implementation 801cb0ef41Sopenharmony_ci // calls 'push' asynchronously. If 'push' was synchronous, the 'end' event 811cb0ef41Sopenharmony_ci // would be emitted here _before_ we call read(). 821cb0ef41Sopenharmony_ci assert.deepStrictEqual( 831cb0ef41Sopenharmony_ci calls, 841cb0ef41Sopenharmony_ci ['_read:a', 'push:a', 'readable', 'data:a', 851cb0ef41Sopenharmony_ci '_read:null', 'push:null', 'readable']); 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci assert.strictEqual(r.read(), null); 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci // While it isn't really specified whether the 'end' event should happen 901cb0ef41Sopenharmony_ci // synchronously with read() or not, we'll assert the current behavior 911cb0ef41Sopenharmony_ci // ('end' event happening on the next tick after read()) so any changes 921cb0ef41Sopenharmony_ci // to it are noted and acknowledged in the future. 931cb0ef41Sopenharmony_ci assert.deepStrictEqual( 941cb0ef41Sopenharmony_ci calls, 951cb0ef41Sopenharmony_ci ['_read:a', 'push:a', 'readable', 'data:a', 961cb0ef41Sopenharmony_ci '_read:null', 'push:null', 'readable']); 971cb0ef41Sopenharmony_ci process.nextTick(() => { 981cb0ef41Sopenharmony_ci assert.deepStrictEqual( 991cb0ef41Sopenharmony_ci calls, 1001cb0ef41Sopenharmony_ci ['_read:a', 'push:a', 'readable', 'data:a', 1011cb0ef41Sopenharmony_ci '_read:null', 'push:null', 'readable', 'end']); 1021cb0ef41Sopenharmony_ci }); 1031cb0ef41Sopenharmony_ci }); 1041cb0ef41Sopenharmony_ci}); 105