diff --git a/README.md b/README.md index 1c9c6afe12..4a69842b6e 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ npm install --save readable-stream This package is a mirror of the streams implementations in Node.js. -Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v10.8.0/docs/api/stream.html). +Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v10.9.0/docs/api/stream.html). If you want to guarantee a stable streams base, regardless of what version of Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core, for background see [this blogpost](http://r.va.gg/2014/06/why-i-dont-use-nodes-core-stream-module.html). diff --git a/build/files.js b/build/files.js index 942e2e188d..98ca9ac32a 100644 --- a/build/files.js +++ b/build/files.js @@ -180,10 +180,6 @@ function CorkedRequest(state) { /Object\.getPrototypeOf\((chunk)\) !== Buffer\.prototype/g , '!Buffer.isBuffer($1)' ] - , fixCopyBuffer = [ - /Buffer\.prototype\.copy\.call\(src, target, offset\);/ - , 'src.copy(target, offset);' - ] , errorsOneLevel = [ /internal\/errors/ , '../errors' @@ -280,24 +276,15 @@ module.exports['_stream_writable.js'] = [ module.exports['internal/streams/buffer_list.js'] = [ [ - /(?:var|const) (?:{ )Buffer(?: }) = require\('buffer'\)(?:\.Buffer)?;/, + /const \{ inspect \} = require\('util'\);/, ` -const Buffer = require('buffer').Buffer -const util = require('util') +const { inspect } = require('util') +const custom = inspect && inspect.custom || 'inspect' ` ] - , fixCopyBuffer , [ - /$/, - ` - -if (util && util.inspect && util.inspect.custom) { - module.exports.prototype[util.inspect.custom] = function () { - const obj = util.inspect({ length: this.length }); - return \`\${this.constructor.name} \${obj}\`; - } -} -` + /inspect.custom/g, + 'custom' ] ] diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index 221a39d4b0..e42e1caefb 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -381,7 +381,7 @@ Readable.prototype.read = function (n) { // if we're doing read(0) to trigger a readable event, but we // already have a bunch of data in the buffer, then just trigger // the 'readable' event and move on. - if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { + if (n === 0 && state.needReadable && ((state.highWaterMark !== 0 ? state.length >= state.highWaterMark : state.length > 0) || state.ended)) { debug('read: emitReadable', state.length, state.ended); if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); return null; @@ -768,6 +768,7 @@ Readable.prototype.on = function (ev, fn) { if (!state.endEmitted && !state.readableListening) { state.readableListening = state.needReadable = true; state.emittedReadable = false; + debug('on readable', state.length, state.reading); if (state.length) { emitReadable(this); } else if (!state.reading) { diff --git a/lib/internal/streams/buffer_list.js b/lib/internal/streams/buffer_list.js index 72463e17ff..24ed31305f 100644 --- a/lib/internal/streams/buffer_list.js +++ b/lib/internal/streams/buffer_list.js @@ -2,14 +2,16 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -var Buffer = require('buffer').Buffer; -var util = require('util'); +var _require = require('buffer'), + Buffer = _require.Buffer; -var _require = require('util'), - inspect = _require.inspect; +var _require2 = require('util'), + inspect = _require2.inspect; + +var custom = inspect && custom || 'inspect'; function copyBuffer(src, target, offset) { - src.copy(target, offset); + Buffer.prototype.copy.call(src, target, offset); } module.exports = function () { @@ -152,17 +154,10 @@ module.exports = function () { return ret; }; - BufferList.prototype[inspect.custom] = function () { + BufferList.prototype[custom] = function () { var obj = inspect({ length: this.length }); return this.constructor.name + ' ' + obj; }; return BufferList; -}(); - -if (util && util.inspect && util.inspect.custom) { - module.exports.prototype[util.inspect.custom] = function () { - var obj = util.inspect({ length: this.length }); - return this.constructor.name + ' ' + obj; - }; -} \ No newline at end of file +}(); \ No newline at end of file diff --git a/test/browser.js b/test/browser.js index a3504d63f7..0a099fc9f3 100644 --- a/test/browser.js +++ b/test/browser.js @@ -13,12 +13,6 @@ if (!global.console.info) { var test = require('tape'); var util = require('util'); -// TODO: add replacements instead -if (!util.inspect) { - util.inspect = function () {}; - util.inspect.custom = 'custom'; -} - // TODO: add replacements instead global.process = { env: {}, diff --git a/test/common/README.md b/test/common/README.md index 943700ed71..75005f6442 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -125,12 +125,6 @@ Tests whether `name`, `expected`, and `code` are part of a raised warning. If an expected warning does not have a code then `common.noWarnCode` can be used to indicate this. -### fileExists(pathname) -* pathname [<string>] -* return [<boolean>] - -Checks if `pathname` exists - ### getArrayBufferViews(buf) * `buf` [<Buffer>] * return [<ArrayBufferView[]>] @@ -582,7 +576,7 @@ one listed below. (`heap.validateSnapshotNodes(...)` is a shortcut for Create a heap dump and an embedder graph copy and validate occurrences. - + ```js validateSnapshotNodes('TLSWRAP', [ { @@ -600,7 +594,7 @@ validateSnapshotNodes('TLSWRAP', [ The http2.js module provides a handful of utilities for creating mock HTTP/2 frames for testing of HTTP/2 endpoints - + ```js const http2 = require('../common/http2'); ``` @@ -610,7 +604,7 @@ const http2 = require('../common/http2'); The `http2.Frame` is a base class that creates a `Buffer` containing a serialized HTTP/2 frame header. - + ```js // length is a 24-bit unsigned integer // type is an 8-bit unsigned integer identifying the frame type @@ -629,7 +623,7 @@ The serialized `Buffer` may be retrieved using the `frame.data` property. The `http2.DataFrame` is a subclass of `http2.Frame` that serializes a `DATA` frame. - + ```js // id is the 32-bit stream identifier // payload is a Buffer containing the DATA payload @@ -646,7 +640,7 @@ socket.write(frame.data); The `http2.HeadersFrame` is a subclass of `http2.Frame` that serializes a `HEADERS` frame. - + ```js // id is the 32-bit stream identifier // payload is a Buffer containing the HEADERS payload (see either @@ -664,7 +658,7 @@ socket.write(frame.data); The `http2.SettingsFrame` is a subclass of `http2.Frame` that serializes an empty `SETTINGS` frame. - + ```js // ack is a boolean indicating whether or not to set the ACK flag. const frame = new http2.SettingsFrame(ack); @@ -677,7 +671,7 @@ socket.write(frame.data); Set to a `Buffer` instance that contains a minimal set of serialized HTTP/2 request headers to be used as the payload of a `http2.HeadersFrame`. - + ```js const frame = new http2.HeadersFrame(1, http2.kFakeRequestHeaders, 0, true); @@ -689,7 +683,7 @@ socket.write(frame.data); Set to a `Buffer` instance that contains a minimal set of serialized HTTP/2 response headers to be used as the payload a `http2.HeadersFrame`. - + ```js const frame = new http2.HeadersFrame(1, http2.kFakeResponseHeaders, 0, true); @@ -701,7 +695,7 @@ socket.write(frame.data); Set to a `Buffer` containing the preamble bytes an HTTP/2 client must send upon initial establishment of a connection. - + ```js socket.write(http2.kClientMagic); ``` diff --git a/test/common/benchmark.js b/test/common/benchmark.js index 56ee8e5719..4108712ccb 100644 --- a/test/common/benchmark.js +++ b/test/common/benchmark.js @@ -36,7 +36,10 @@ function runBenchmark(name, args, env) { var mergedEnv = Object.assign({}, process.env, env); - var child = fork(runjs, argv, { env: mergedEnv, stdio: 'pipe' }); + var child = fork(runjs, argv, { + env: mergedEnv, + stdio: ['inherit', 'pipe', 'inherit', 'ipc'] + }); child.stdout.setEncoding('utf8'); var stdout = ''; diff --git a/test/common/index.js b/test/common/index.js index 67d596414c..6fd2ae483a 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -518,17 +518,8 @@ exports.hasMultiLocalhost = function hasMultiLocalhost() { return ret === 0; }; -exports.fileExists = function (pathname) { - try { - fs.accessSync(pathname); - return true; - } catch (err) { - return false; - } -}; - exports.skipIfEslintMissing = function () { - if (!exports.fileExists(path.join(__dirname, '..', '..', 'tools', 'node_modules', 'eslint'))) { + if (!fs.existsSync(path.join(__dirname, '..', '..', 'tools', 'node_modules', 'eslint'))) { exports.skip('missing ESLint'); } }; @@ -768,7 +759,8 @@ exports.expectsError = function expectsError(fn, settings, exact) { assert.fail('Expected one argument, got ' + util.inspect(arguments)); } var descriptor = Object.getOwnPropertyDescriptor(error, 'message'); - assert.strictEqual(descriptor.enumerable, false, 'The error message should be non-enumerable'); + // The error message should be non-enumerable + assert.strictEqual(descriptor.enumerable, false); var innerSettings = settings; if ('type' in settings) { diff --git a/test/common/index.mjs b/test/common/index.mjs index d6e9f31fe3..c15315e9e9 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -7,7 +7,6 @@ import common from './index.js'; const { - PORT, isMainThread, isWindows, isWOW64, @@ -38,7 +37,6 @@ const { mustCallAtLeast, mustCallAsync, hasMultiLocalhost, - fileExists, skipIfEslintMissing, canCreateSymLink, getCallSite, @@ -67,7 +65,6 @@ const { } = common; export { - PORT, isMainThread, isWindows, isWOW64, @@ -98,7 +95,6 @@ export { mustCallAtLeast, mustCallAsync, hasMultiLocalhost, - fileExists, skipIfEslintMissing, canCreateSymLink, getCallSite, diff --git a/test/parallel/test-stream-readable-hwm-0.js b/test/parallel/test-stream-readable-hwm-0.js new file mode 100644 index 0000000000..e648eef7ec --- /dev/null +++ b/test/parallel/test-stream-readable-hwm-0.js @@ -0,0 +1,39 @@ +'use strict'; + +/**/ +var bufferShim = require('safe-buffer').Buffer; +/**/ + +var common = require('../common'); + +// This test ensures that Readable stream will call _read() for streams +// with highWaterMark === 0 upon .read(0) instead of just trying to +// emit 'readable' event. + +var assert = require('assert/'); + +var _require = require('../../'), + Readable = _require.Readable; + +var r = new Readable({ + // must be called only once upon setting 'readable' listener + read: common.mustCall(), + highWaterMark: 0 +}); + +var pushedNull = false; +// this will trigger read(0) but must only be called after push(null) +// because the we haven't pushed any data +r.on('readable', common.mustCall(function () { + assert.strictEqual(r.read(), null); + assert.strictEqual(pushedNull, true); +})); +r.on('end', common.mustCall()); +process.nextTick(function () { + assert.strictEqual(r.read(), null); + pushedNull = true; + r.push(null); +}); +;require('tap').pass('sync run');var _list = process.listeners('uncaughtException');process.removeAllListeners('uncaughtException');_list.pop();_list.forEach(function (e) { + return process.on('uncaughtException', e); +}); \ No newline at end of file diff --git a/test/parallel/test-stream-transform-final.js b/test/parallel/test-stream-transform-final.js index bdd2f05faa..78763f3b29 100644 --- a/test/parallel/test-stream-transform-final.js +++ b/test/parallel/test-stream-transform-final.js @@ -63,46 +63,56 @@ The order things are called var t = new stream.Transform({ objectMode: true, transform: common.mustCall(function (chunk, _, next) { - assert.strictEqual(++state, chunk, 'transformCallback part 1'); + // transformCallback part 1 + assert.strictEqual(++state, chunk); this.push(state); - assert.strictEqual(++state, chunk + 2, 'transformCallback part 2'); + // transformCallback part 2 + assert.strictEqual(++state, chunk + 2); process.nextTick(next); }, 3), final: common.mustCall(function (done) { state++; - assert.strictEqual(state, 10, 'finalCallback part 1'); + // finalCallback part 1 + assert.strictEqual(state, 10); setTimeout(function () { state++; - assert.strictEqual(state, 11, 'finalCallback part 2'); + // finalCallback part 2 + assert.strictEqual(state, 11); done(); }, 100); }, 1), flush: common.mustCall(function (done) { state++; - assert.strictEqual(state, 12, 'flushCallback part 1'); + // flushCallback part 1 + assert.strictEqual(state, 12); process.nextTick(function () { state++; - assert.strictEqual(state, 15, 'flushCallback part 2'); + // flushCallback part 2 + assert.strictEqual(state, 15); done(); }); }, 1) }); t.on('finish', common.mustCall(function () { state++; - assert.strictEqual(state, 13, 'finishListener'); + // finishListener + assert.strictEqual(state, 13); }, 1)); t.on('end', common.mustCall(function () { state++; - assert.strictEqual(state, 16, 'end event'); + // end event + assert.strictEqual(state, 16); }, 1)); t.on('data', common.mustCall(function (d) { - assert.strictEqual(++state, d + 1, 'dataListener'); + // dataListener + assert.strictEqual(++state, d + 1); }, 3)); t.write(1); t.write(4); t.end(7, common.mustCall(function () { state++; - assert.strictEqual(state, 14, 'endMethodCallback'); + // endMethodCallback + assert.strictEqual(state, 14); }, 1)); ;require('tap').pass('sync run');var _list = process.listeners('uncaughtException');process.removeAllListeners('uncaughtException');_list.pop();_list.forEach(function (e) { return process.on('uncaughtException', e); diff --git a/test/parallel/test-stream2-read-sync-stack.js b/test/parallel/test-stream2-read-sync-stack.js index 0afe19954d..7ce308cbde 100644 --- a/test/parallel/test-stream2-read-sync-stack.js +++ b/test/parallel/test-stream2-read-sync-stack.js @@ -26,13 +26,13 @@ var bufferShim = require('safe-buffer').Buffer; /**/ var common = require('../common'); var Readable = require('../../').Readable; + +// This tests synchronous read callbacks and verifies that even if they nest +// heavily the process handles it without an error + var r = new Readable(); var N = 256 * 1024; -// Go ahead and allow the pathological case for this test. -// Yes, it's an infinite loop, that's the point. -process.maxTickDepth = N + 2; - var reads = 0; r._read = function (n) { var chunk = reads++ === N ? null : bufferShim.allocUnsafe(1);