diff --git a/README.md b/README.md
index d0fafcf20f..bba15c79d2 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# readable-stream
-***Node-core v10.1.0 streams for userland*** [](https://travis-ci.org/nodejs/readable-stream)
+***Node-core v10.3.0 streams for userland*** [](https://travis-ci.org/nodejs/readable-stream)
[](https://nodei.co/npm/readable-stream/)
@@ -18,7 +18,7 @@ npm install --save readable-stream
This package is a mirror of the Streams2 and Streams3 implementations in
Node-core.
-Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v10.1.0/docs/api/stream.html).
+Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v10.3.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/test-replacements.js b/build/test-replacements.js
index 12843a8428..1241aa80d4 100644
--- a/build/test-replacements.js
+++ b/build/test-replacements.js
@@ -12,6 +12,11 @@ const altForEachImplReplacement = require('./common-replacements').altForEachImp
require('./common-replacements').bufferStaticMethods
, specialForEachReplacment =
require('./common-replacements').specialForEachReplacment
+ , deepStrictEqual = [
+ /util\.isDeepStrictEqual/,
+ 'require(\'deep-strict-equal\')'
+ ]
+
module.exports.all = [
[
@@ -78,6 +83,7 @@ module.exports['common.js'] = [
, objectKeysReplacement
, altForEachImplReplacement
, altForEachUseReplacement
+ , deepStrictEqual
, [
/(exports.mustCall[\s\S]*)/m
@@ -110,7 +116,7 @@ module.exports['common.js'] = [
+ ' knownGlobals.push(DTRACE_NET_SOCKET_WRITE);\n'
+ ' if (global.__coverage__)\n'
+ ' knownGlobals.push(__coverage__);\n'
- + '\'core,__core-js_shared__,Promise,Map,Set,WeakMap,WeakSet,Reflect,System,asap,Observable,regeneratorRuntime,_babelPolyfill\'.split(\',\').filter(function (item) { return typeof global[item] !== undefined}).forEach(function (item) {knownGlobals.push(global[item])})'
+ + '\'core,__core-js_shared__,console,Promise,Map,Set,WeakMap,WeakSet,Reflect,System,asap,Observable,regeneratorRuntime,_babelPolyfill\'.split(\',\').filter(function (item) { return typeof global[item] !== undefined}).forEach(function (item) {knownGlobals.push(global[item])})'
+ ' /**/\n\n$1'
]
@@ -338,6 +344,22 @@ module.exports['test-stream-unpipe-event.js'] = [
]
]
+module.exports['test-stream-readable-flow-recursion.js'] = [
+ deepStrictEqual
+]
+
+module.exports['test-stream-readable-with-unimplemented-_read.js'] = [
+ deepStrictEqual
+]
+
+module.exports['test-stream-writable-needdrain-state.js'] = [
+ deepStrictEqual
+]
+
+module.exports['test-stream-readable-setEncoding-null.js'] = [
+ deepStrictEqual
+]
+
module.exports['test-stream-pipeline.js'] = [
[
/require\('http2'\)/g,
diff --git a/errors.js b/errors.js
index 5b8c455772..b17eeea660 100644
--- a/errors.js
+++ b/errors.js
@@ -2,26 +2,43 @@
const codes = {};
-function createErrorType(name) {
- function E(message) {
- if (!Error.captureStackTrace)
- this.stack = (new Error()).stack;
- else
- Error.captureStackTrace(this, this.constructor);
- this.message = message;
+function createErrorType(code, message, Base) {
+ if (!Base) {
+ Base = Error
}
- E.prototype = new Error();
- E.prototype.name = name;
- E.prototype.constructor = E;
- codes[name] = E;
+ function getMessage (arg1, arg2) {
+ if (typeof message === 'string') {
+ return message
+ } else {
+ return message(arg1, arg2)
+ }
+ }
+
+ // TODO(mcollina) make this a function
+ class NodeError extends Base {
+ constructor (arg1, arg2) {
+ super(getMessage(arg1, arg2));
+ }
+ }
+
+ NodeError.prototype.name = Base.name;
+ NodeError.prototype.code = code;
+
+ codes[code] = NodeError;
}
-createErrorType('ERR_INVALID_OPT_VALUE');
-createErrorType('ERR_INVALID_ARG_TYPE');
-createErrorType('ERR_STREAM_PUSH_AFTER_EOF');
-createErrorType('ERR_METHOD_NOT_IMPLEMENTED');
-createErrorType('ERR_STREAM_PUSH_AFTER_EOF');
-createErrorType('ERR_STREAM_PREMATURE_CLOSE');
+createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) {
+ return 'The value "' + value + '" is invalid for option "' + name + '"'
+}, TypeError);
+createErrorType('ERR_INVALID_ARG_TYPE', 'argument must be of the right type');
+createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream-push() after EOF');
+createErrorType('ERR_METHOD_NOT_IMPLEMENTED', 'the method is not implemented');
+createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'premature close');
+createErrorType('ERR_STREAM_DESTROYED', 'the stream was destroyed');
+createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times');
+createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable');
+createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end');
+createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError);
module.exports.codes = codes;
diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js
index 6f295c95b2..c9823bb68b 100644
--- a/lib/_stream_readable.js
+++ b/lib/_stream_readable.js
@@ -86,12 +86,14 @@ var _require$codes = require('../errors').codes,
ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED,
ERR_STREAM_UNSHIFT_AFTER_END_EVENT = _require$codes.ERR_STREAM_UNSHIFT_AFTER_END_EVENT;
-var ReadableAsyncIterator = require('./internal/streams/async_iterator');
-
var _require2 = require('../experimentalWarning'),
emitExperimentalWarning = _require2.emitExperimentalWarning;
-var StringDecoder;
+// Lazy loaded to improve the startup performance.
+
+
+var StringDecoder = void 0;
+var ReadableAsyncIterator = void 0;
util.inherits(Readable, Stream);
@@ -345,7 +347,8 @@ Readable.prototype.isPaused = function () {
Readable.prototype.setEncoding = function (enc) {
if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder;
this._readableState.decoder = new StringDecoder(enc);
- this._readableState.encoding = enc;
+ // if setEncoding(null), decoder.encoding equals utf8
+ this._readableState.encoding = this._readableState.decoder.encoding;
return this;
};
@@ -804,7 +807,7 @@ Readable.prototype.removeListener = function (ev, fn) {
if (ev === 'readable') {
// We need to check if there is someone still listening to
- // to readable and reset the state. However this needs to happen
+ // readable and reset the state. However this needs to happen
// after readable has been emitted but before I/O (nextTick) to
// support once('readable', fn) cycles. This means that calling
// resume within the same tick will have no
@@ -816,11 +819,11 @@ Readable.prototype.removeListener = function (ev, fn) {
};
Readable.prototype.removeAllListeners = function (ev) {
- var res = Stream.prototype.removeAllListeners.call(this, ev);
+ var res = Stream.prototype.removeAllListeners.apply(this, arguments);
if (ev === 'readable' || ev === undefined) {
// We need to check if there is someone still listening to
- // to readable and reset the state. However this needs to happen
+ // readable and reset the state. However this needs to happen
// after readable has been emitted but before I/O (nextTick) to
// support once('readable', fn) cycles. This means that calling
// resume within the same tick will have no
@@ -954,7 +957,7 @@ Readable.prototype.wrap = function (stream) {
Readable.prototype[Symbol.asyncIterator] = function () {
emitExperimentalWarning('Readable[Symbol.asyncIterator]');
-
+ if (ReadableAsyncIterator === undefined) ReadableAsyncIterator = require('./internal/streams/async_iterator');
return new ReadableAsyncIterator(this);
};
diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js
index c63861de4c..ec6c075154 100644
--- a/lib/_stream_writable.js
+++ b/lib/_stream_writable.js
@@ -307,8 +307,7 @@ function writeAfterEnd(stream, cb) {
// mode the stream is in. Currently this means that `null` is never accepted
// and undefined/non-string values are only allowed in object mode.
function validChunk(stream, state, chunk, cb) {
- var valid = true;
- var er = false;
+ var er;
if (chunk === null) {
er = new ERR_STREAM_NULL_VALUES();
@@ -318,9 +317,9 @@ function validChunk(stream, state, chunk, cb) {
if (er) {
stream.emit('error', er);
pna.nextTick(cb, er);
- valid = false;
+ return false;
}
- return valid;
+ return true;
}
Writable.prototype.write = function (chunk, encoding, cb) {
@@ -350,9 +349,7 @@ Writable.prototype.write = function (chunk, encoding, cb) {
};
Writable.prototype.cork = function () {
- var state = this._writableState;
-
- state.corked++;
+ this._writableState.corked++;
};
Writable.prototype.uncork = function () {
diff --git a/lib/internal/streams/pipeline.js b/lib/internal/streams/pipeline.js
index 56c67af8e5..8ec2395556 100644
--- a/lib/internal/streams/pipeline.js
+++ b/lib/internal/streams/pipeline.js
@@ -8,7 +8,7 @@
var pna = require('process-nextick-args');
/**/
-var eos = require('./end-of-stream');
+var eos = void 0;
var _require$codes = require('../../../errors').codes,
ERR_MISSING_ARGS = _require$codes.ERR_MISSING_ARGS,
@@ -37,6 +37,7 @@ function destroyer(stream, reading, writing, callback) {
closed = true;
});
+ if (eos === undefined) eos = require('./end-of-stream');
eos(stream, { readable: reading, writable: writing }, function (err) {
if (err) return callback(err);
closed = true;
diff --git a/lib/internal/streams/state.js b/lib/internal/streams/state.js
index 7786caf326..1632e883f8 100644
--- a/lib/internal/streams/state.js
+++ b/lib/internal/streams/state.js
@@ -7,17 +7,18 @@ var pna = require('process-nextick-args');
var ERR_INVALID_OPT_VALUE = require('../../../errors').codes.ERR_INVALID_OPT_VALUE;
+function highWaterMarkFrom(options, isDuplex, duplexKey) {
+ return options.highWaterMark != null ? options.highWaterMark : isDuplex ? options[duplexKey] : null;
+}
+
function getHighWaterMark(state, options, duplexKey, isDuplex) {
- var hwm = options.highWaterMark;
+ var hwm = highWaterMarkFrom(options, isDuplex, duplexKey);
if (hwm != null) {
- if (typeof hwm !== 'number' || !(hwm >= 0)) throw new ERR_INVALID_OPT_VALUE('highWaterMark', hwm);
- return Math.floor(hwm);
- } else if (isDuplex) {
- hwm = options[duplexKey];
- if (hwm != null) {
- if (typeof hwm !== 'number' || !(hwm >= 0)) throw new ERR_INVALID_OPT_VALUE(duplexKey, hwm);
- return Math.floor(hwm);
+ if (!Number.isInteger(hwm) || hwm < 0) {
+ var name = isDuplex ? duplexKey : 'highWaterMark';
+ throw new ERR_INVALID_OPT_VALUE(name, hwm);
}
+ return Math.floor(hwm);
}
// Default value
diff --git a/package.json b/package.json
index 88fefba4fc..c4dc57832f 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"assert": "^1.4.0",
"babel-polyfill": "^6.9.1",
"buffer": "^5.1.0",
+ "deep-strict-equal": "^0.2.0",
"lolex": "^2.6.0",
"nyc": "^11.0.0",
"tap": "^11.0.0",
diff --git a/test/common/README.md b/test/common/README.md
index 41f61baa75..46769f66dd 100644
--- a/test/common/README.md
+++ b/test/common/README.md
@@ -166,11 +166,6 @@ Attempts to get a valid TTY file descriptor. Returns `-1` if it fails.
The TTY file descriptor is assumed to be capable of being writable.
-### globalCheck
-* [<boolean>]
-
-Set to `false` if the test should not check for global leaks.
-
### hasCrypto
* [<boolean>]
diff --git a/test/common/index.js b/test/common/index.js
index a3916882ac..4ffb2714fe 100644
--- a/test/common/index.js
+++ b/test/common/index.js
@@ -348,8 +348,7 @@ exports.platformTimeout = function (ms) {
return ms; // ARMv8+
};
-var knownGlobals = [Buffer, clearImmediate, clearInterval, clearTimeout, console, constructor, // Enumerable in V8 3.21.
-global, process, setImmediate, setInterval, setTimeout];
+var knownGlobals = [Buffer, clearImmediate, clearInterval, clearTimeout, global, process, setImmediate, setInterval, setTimeout];
if (global.gc) {
knownGlobals.push(global.gc);
@@ -373,31 +372,6 @@ if (global.COUNTER_NET_SERVER_CONNECTION) {
knownGlobals.push(COUNTER_HTTP_CLIENT_RESPONSE);
}
-/**/if (!process.browser) {
- if (global.ArrayBuffer) {
- knownGlobals.push(ArrayBuffer);
- knownGlobals.push(Int8Array);
- knownGlobals.push(Uint8Array);
- knownGlobals.push(Uint8ClampedArray);
- knownGlobals.push(Int16Array);
- knownGlobals.push(Uint16Array);
- knownGlobals.push(Int32Array);
- knownGlobals.push(Uint32Array);
- knownGlobals.push(Float32Array);
- knownGlobals.push(Float64Array);
- knownGlobals.push(DataView);
- }
-} /**/
-
-// Harmony features.
-if (global.Proxy) {
- knownGlobals.push(Proxy);
-}
-
-if (global.Symbol) {
- knownGlobals.push(Symbol);
-}
-
if (process.env.NODE_TEST_KNOWN_GLOBALS) {
var knownFromEnv = process.env.NODE_TEST_KNOWN_GLOBALS.split(',');
allowGlobals.apply(undefined, _toConsumableArray(knownFromEnv));
@@ -417,7 +391,7 @@ if (typeof constructor == 'function') knownGlobals.push(constructor);
if (typeof DTRACE_NET_SOCKET_READ == 'function') knownGlobals.push(DTRACE_NET_SOCKET_READ);
if (typeof DTRACE_NET_SOCKET_WRITE == 'function') knownGlobals.push(DTRACE_NET_SOCKET_WRITE);
if (global.__coverage__) knownGlobals.push(__coverage__);
-'core,__core-js_shared__,Promise,Map,Set,WeakMap,WeakSet,Reflect,System,asap,Observable,regeneratorRuntime,_babelPolyfill'.split(',').filter(function (item) {
+'core,__core-js_shared__,console,Promise,Map,Set,WeakMap,WeakSet,Reflect,System,asap,Observable,regeneratorRuntime,_babelPolyfill'.split(',').filter(function (item) {
return typeof global[item] !== undefined;
}).forEach(function (item) {
knownGlobals.push(global[item]);
@@ -442,11 +416,7 @@ function leakedGlobals() {
}
exports.leakedGlobals = leakedGlobals;
-// Turn this off if the test should not check for global leaks.
-exports.globalCheck = true;
-
process.on('exit', function () {
- if (!exports.globalCheck) return;
var leaked = leakedGlobals();
if (leaked.length > 0) {
assert.fail('Unexpected global(s) found: ' + leaked.join(', '));
@@ -820,7 +790,7 @@ exports.expectsError = function expectsError(fn, settings, exact) {
for (var _iterator2 = keys[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var key = _step2.value;
- if (!util.isDeepStrictEqual(error[key], innerSettings[key])) {
+ if (!require('deep-strict-equal')(error[key], innerSettings[key])) {
// Create placeholder objects to create a nice output.
var a = new Comparison(error, keys);
var b = new Comparison(innerSettings, keys);
@@ -1015,4 +985,4 @@ if (!util._errnoException) {
e.syscall = syscall;
return e;
};
-}
\ No newline at end of file
+}
diff --git a/test/common/index.mjs b/test/common/index.mjs
index 4ae4dcd7f0..32533c6bf3 100644
--- a/test/common/index.mjs
+++ b/test/common/index.mjs
@@ -24,8 +24,6 @@ let knownGlobals = [
clearImmediate,
clearInterval,
clearTimeout,
- console,
- constructor, // Enumerable in V8 3.21.
global,
process,
setImmediate,
@@ -66,29 +64,6 @@ export function leakedGlobals() {
knownGlobals.push(COUNTER_HTTP_CLIENT_RESPONSE);
}
- if (global.ArrayBuffer) {
- knownGlobals.push(ArrayBuffer);
- knownGlobals.push(Int8Array);
- knownGlobals.push(Uint8Array);
- knownGlobals.push(Uint8ClampedArray);
- knownGlobals.push(Int16Array);
- knownGlobals.push(Uint16Array);
- knownGlobals.push(Int32Array);
- knownGlobals.push(Uint32Array);
- knownGlobals.push(Float32Array);
- knownGlobals.push(Float64Array);
- knownGlobals.push(DataView);
- }
-
- // Harmony features.
- if (global.Proxy) {
- knownGlobals.push(Proxy);
- }
-
- if (global.Symbol) {
- knownGlobals.push(Symbol);
- }
-
const leaked = [];
for (const val in global) {
@@ -104,11 +79,7 @@ export function leakedGlobals() {
}
}
-// Turn this off if the test should not check for global leaks.
-export let globalCheck = true; // eslint-disable-line
-
process.on('exit', function() {
- if (!globalCheck) return;
const leaked = leakedGlobals();
if (leaked.length > 0) {
assert.fail(`Unexpected global(s) found: ${leaked.join(', ')}`);
diff --git a/test/ours/lolex-fake-timers.js b/test/ours/lolex-fake-timers.js
index 8a43c8da78..59af1328ea 100644
--- a/test/ours/lolex-fake-timers.js
+++ b/test/ours/lolex-fake-timers.js
@@ -38,4 +38,4 @@ stream.emit('data');
clock.runAll()
clock.uninstall();
assert(stream2DataCalled);
-t.pass('ok');
+tap.pass('ok');
diff --git a/test/parallel/test-stream-pipe-await-drain-push-while-write.js b/test/parallel/test-stream-pipe-await-drain-push-while-write.js
index 2f8f57ea2b..714647574b 100644
--- a/test/parallel/test-stream-pipe-await-drain-push-while-write.js
+++ b/test/parallel/test-stream-pipe-await-drain-push-while-write.js
@@ -7,7 +7,7 @@ var assert = require('assert/');
var writable = new stream.Writable({
write: common.mustCall(function (chunk, encoding, cb) {
- assert.strictEqual(readable._readableState.awaitDrain, 0, 'State variable awaitDrain is not correct.');
+ assert.strictEqual(readable._readableState.awaitDrain, 0);
if (chunk.length === 32 * 1024) {
// first chunk
@@ -15,7 +15,7 @@ var writable = new stream.Writable({
// We should check if awaitDrain counter is increased in the next
// tick, because awaitDrain is incremented after this method finished
process.nextTick(function () {
- assert.strictEqual(readable._readableState.awaitDrain, 1, 'Counter is not increased for awaitDrain');
+ assert.strictEqual(readable._readableState.awaitDrain, 1);
});
}
diff --git a/test/parallel/test-stream-readable-event.js b/test/parallel/test-stream-readable-event.js
index b9ba727aff..2553fd791e 100644
--- a/test/parallel/test-stream-readable-event.js
+++ b/test/parallel/test-stream-readable-event.js
@@ -119,4 +119,17 @@ var Readable = require('../../').Readable;
assert.deepStrictEqual(result, expected);
}));
}
+
+{
+ // #20923
+ var _r4 = new Readable();
+ _r4._read = function () {
+ // actually doing thing here
+ };
+ _r4.on('data', function () {});
+
+ _r4.removeAllListeners();
+
+ assert.strictEqual(_r4.eventNames().length, 0);
+}
;require('tap').pass('sync run');
\ No newline at end of file
diff --git a/test/parallel/test-stream-readable-setEncoding-null.js b/test/parallel/test-stream-readable-setEncoding-null.js
new file mode 100644
index 0000000000..b557c63239
--- /dev/null
+++ b/test/parallel/test-stream-readable-setEncoding-null.js
@@ -0,0 +1,19 @@
+/**/
+var bufferShim = require('safe-buffer').Buffer;
+/**/
+
+require('../common');
+var assert = require('assert/');
+
+var _require = require('../../'),
+ Readable = _require.Readable;
+
+{
+ var readable = new Readable({ encoding: 'hex' });
+ assert.strictEqual(readable._readableState.encoding, 'hex');
+
+ readable.setEncoding(null);
+
+ assert.strictEqual(readable._readableState.encoding, 'utf8');
+}
+;require('tap').pass('sync run');
\ No newline at end of file