diff --git a/.gitignore b/.gitignore
index 1d32beafcd..2d95bfb658 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@ node_modules/
.zuul.yml
.nyc_output
coverage
+package-lock.json
diff --git a/.travis.yml b/.travis.yml
index 76b4b0cfcb..0c5d2bc262 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,26 +2,40 @@ sudo: false
language: node_js
before_install:
- npm install -g npm@2
- - npm install -g npm
+ - test $NPM_LEGACY && npm install -g npm@latest-3 || npm install npm -g
notifications:
email: false
matrix:
fast_finish: true
include:
- node_js: '0.8'
- env: TASK=test
+ env:
+ - TASK=test
+ - NPM_LEGACY=true
- node_js: '0.10'
- env: TASK=test
+ env:
+ - TASK=test
+ - NPM_LEGACY=true
- node_js: '0.11'
- env: TASK=test
+ env:
+ - TASK=test
+ - NPM_LEGACY=true
- node_js: '0.12'
- env: TASK=test
+ env:
+ - TASK=test
+ - NPM_LEGACY=true
- node_js: 1
- env: TASK=test
+ env:
+ - TASK=test
+ - NPM_LEGACY=true
- node_js: 2
- env: TASK=test
+ env:
+ - TASK=test
+ - NPM_LEGACY=true
- node_js: 3
- env: TASK=test
+ env:
+ - TASK=test
+ - NPM_LEGACY=true
- node_js: 4
env: TASK=test
- node_js: 5
@@ -30,17 +44,19 @@ matrix:
env: TASK=test
- node_js: 7
env: TASK=test
- - node_js: 5
+ - node_js: 8
+ env: TASK=test
+ - node_js: 6
env: TASK=browser BROWSER_NAME=ie BROWSER_VERSION="9..latest"
- - node_js: 5
+ - node_js: 6
env: TASK=browser BROWSER_NAME=opera BROWSER_VERSION="11..latest"
- - node_js: 5
+ - node_js: 6
env: TASK=browser BROWSER_NAME=chrome BROWSER_VERSION="-3..latest"
- - node_js: 5
+ - node_js: 6
env: TASK=browser BROWSER_NAME=firefox BROWSER_VERSION="-3..latest"
- - node_js: 5
+ - node_js: 6
env: TASK=browser BROWSER_NAME=safari BROWSER_VERSION="5..latest"
- - node_js: 5
+ - node_js: 6
env: TASK=browser BROWSER_NAME=microsoftedge BROWSER_VERSION=latest
script: "npm run $TASK"
env:
diff --git a/README.md b/README.md
index e60744013b..3024d77c69 100644
--- a/README.md
+++ b/README.md
@@ -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/v7.8.0/docs/api/stream.html).
+Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v7.10.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/build.js b/build/build.js
index 2563274b11..3e4b7ea096 100644
--- a/build/build.js
+++ b/build/build.js
@@ -60,6 +60,7 @@ function processFile (inputLoc, out, replacements) {
'transform-es2015-template-literals',
'transform-es2015-shorthand-properties',
'transform-es2015-for-of',
+ 'transform-es2015-classes',
'transform-es2015-destructuring'
]
})
diff --git a/build/package.json b/build/package.json
index 701fbb18c0..384a3fc406 100644
--- a/build/package.json
+++ b/build/package.json
@@ -4,20 +4,21 @@
"description": "",
"main": "build.js",
"dependencies": {
- "babel-core": "^6.5.2",
+ "babel-core": "^6.24.1",
"babel-plugin-transform-es2015-arrow-functions": "^6.5.2",
- "babel-plugin-transform-es2015-block-scoping": "^6.5.0",
+ "babel-plugin-transform-es2015-block-scoping": "^6.24.1",
+ "babel-plugin-transform-es2015-classes": "^6.24.1",
"babel-plugin-transform-es2015-destructuring": "^6.18.0",
"babel-plugin-transform-es2015-for-of": "^6.8.0",
- "babel-plugin-transform-es2015-parameters": "^6.11.4",
- "babel-plugin-transform-es2015-shorthand-properties": "^6.8.0",
+ "babel-plugin-transform-es2015-parameters": "^6.24.1",
+ "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1",
"babel-plugin-transform-es2015-template-literals": "^6.8.0",
- "bl": "^1.2.0",
- "glob": "^7.1.1",
+ "bl": "^1.2.1",
+ "glob": "^7.1.2",
"gunzip-maybe": "^1.4.0",
"hyperquest": "^2.1.2",
"pump": "^1.0.2",
"rimraf": "^2.6.1",
- "tar-fs": "^1.15.1"
+ "tar-fs": "^1.15.2"
}
}
diff --git a/build/test-replacements.js b/build/test-replacements.js
index 82a60449c1..c3b0790442 100644
--- a/build/test-replacements.js
+++ b/build/test-replacements.js
@@ -311,3 +311,10 @@ module.exports['test-stream-transform-constructor-set-methods.js'] = [
'Error: .*[Nn]'
]
]
+
+module.exports['test-stream-unpipe-event.js'] = [
+ [
+ /^/,
+ 'if (process.version.indexOf(\'v0.8\') === 0) { process.exit(0) }\n'
+ ]
+]
diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js
index 2675fe127b..a01012e3cf 100644
--- a/lib/_stream_readable.js
+++ b/lib/_stream_readable.js
@@ -482,7 +482,7 @@ Readable.prototype.pipe = function (dest, pipeOpts) {
var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr;
- var endFn = doEnd ? onend : cleanup;
+ var endFn = doEnd ? onend : unpipe;
if (state.endEmitted) processNextTick(endFn);else src.once('end', endFn);
dest.on('unpipe', onunpipe);
@@ -515,7 +515,7 @@ Readable.prototype.pipe = function (dest, pipeOpts) {
dest.removeListener('error', onerror);
dest.removeListener('unpipe', onunpipe);
src.removeListener('end', onend);
- src.removeListener('end', cleanup);
+ src.removeListener('end', unpipe);
src.removeListener('data', ondata);
cleanedUp = true;
diff --git a/test/common.js b/test/common.js
index 6ff0a664ec..e564be1271 100644
--- a/test/common.js
+++ b/test/common.js
@@ -377,6 +377,7 @@ if (global.__coverage__) knownGlobals.push(__coverage__);
function leakedGlobals() {
var leaked = [];
+ // eslint-disable-next-line no-var
for (var val in global) {
if (!knownGlobals.includes(global[val])) leaked.push(val);
}if (global.__coverage__) {
@@ -564,15 +565,46 @@ exports.isAlive = function isAlive(pid) {
}
};
-exports.expectWarning = function (name, expected) {
- if (typeof expected === 'string') expected = [expected];
- process.on('warning', exports.mustCall(function (warning) {
+function expectWarning(name, expectedMessages) {
+ return exports.mustCall(function (warning) {
assert.strictEqual(warning.name, name);
- assert.ok(expected.includes(warning.message), 'unexpected error message: "' + warning.message + '"');
+ assert.ok(expectedMessages.includes(warning.message), 'unexpected error message: "' + warning.message + '"');
// Remove a warning message after it is seen so that we guarantee that we
// get each message only once.
- expected.splice(expected.indexOf(warning.message), 1);
- }, expected.length));
+ expectedMessages.splice(expectedMessages.indexOf(warning.message), 1);
+ }, expectedMessages.length);
+}
+
+function expectWarningByName(name, expected) {
+ if (typeof expected === 'string') {
+ expected = [expected];
+ }
+ process.on('warning', expectWarning(name, expected));
+}
+
+function expectWarningByMap(warningMap) {
+ var catchWarning = {};
+ forEach(objectKeys(warningMap), function (name) {
+ var expected = warningMap[name];
+ if (typeof expected === 'string') {
+ expected = [expected];
+ }
+ catchWarning[name] = expectWarning(name, expected);
+ });
+ process.on('warning', function (warning) {
+ return catchWarning[warning.name](warning);
+ });
+}
+
+// accepts a warning name and description or array of descriptions or a map
+// of warning names to description(s)
+// ensures a warning is generated for each name/description pair
+exports.expectWarning = function (nameOrMap, expected) {
+ if (typeof nameOrMap === 'string') {
+ expectWarningByName(nameOrMap, expected);
+ } else {
+ expectWarningByMap(nameOrMap);
+ }
};
/**/if (!process.browser) {
diff --git a/test/parallel/test-stream-duplex.js b/test/parallel/test-stream-duplex.js
index 9bf55ab3b4..7fa28eff69 100644
--- a/test/parallel/test-stream-duplex.js
+++ b/test/parallel/test-stream-duplex.js
@@ -3,7 +3,7 @@ var bufferShim = require('safe-buffer').Buffer;
/**/
require('../common');
var assert = require('assert/');
-var Duplex = require('../../').Transform;
+var Duplex = require('../../').Duplex;
var stream = new Duplex({ objectMode: true });
diff --git a/test/parallel/test-stream-unpipe-event.js b/test/parallel/test-stream-unpipe-event.js
new file mode 100644
index 0000000000..71098af93f
--- /dev/null
+++ b/test/parallel/test-stream-unpipe-event.js
@@ -0,0 +1,145 @@
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+if (process.version.indexOf('v0.8') === 0) {
+ process.exit(0);
+}
+/**/
+var bufferShim = require('safe-buffer').Buffer;
+/**/
+var common = require('../common');
+var assert = require('assert/');
+
+var _require = require('../../'),
+ Writable = _require.Writable,
+ Readable = _require.Readable;
+
+var NullWriteable = function (_Writable) {
+ _inherits(NullWriteable, _Writable);
+
+ function NullWriteable() {
+ _classCallCheck(this, NullWriteable);
+
+ return _possibleConstructorReturn(this, (NullWriteable.__proto__ || Object.getPrototypeOf(NullWriteable)).apply(this, arguments));
+ }
+
+ _createClass(NullWriteable, [{
+ key: '_write',
+ value: function _write(chunk, encoding, callback) {
+ return callback();
+ }
+ }]);
+
+ return NullWriteable;
+}(Writable);
+
+var QuickEndReadable = function (_Readable) {
+ _inherits(QuickEndReadable, _Readable);
+
+ function QuickEndReadable() {
+ _classCallCheck(this, QuickEndReadable);
+
+ return _possibleConstructorReturn(this, (QuickEndReadable.__proto__ || Object.getPrototypeOf(QuickEndReadable)).apply(this, arguments));
+ }
+
+ _createClass(QuickEndReadable, [{
+ key: '_read',
+ value: function _read() {
+ this.push(null);
+ }
+ }]);
+
+ return QuickEndReadable;
+}(Readable);
+
+var NeverEndReadable = function (_Readable2) {
+ _inherits(NeverEndReadable, _Readable2);
+
+ function NeverEndReadable() {
+ _classCallCheck(this, NeverEndReadable);
+
+ return _possibleConstructorReturn(this, (NeverEndReadable.__proto__ || Object.getPrototypeOf(NeverEndReadable)).apply(this, arguments));
+ }
+
+ _createClass(NeverEndReadable, [{
+ key: '_read',
+ value: function _read() {}
+ }]);
+
+ return NeverEndReadable;
+}(Readable);
+
+function noop() {}
+
+{
+ var dest = new NullWriteable();
+ var src = new QuickEndReadable();
+ dest.on('pipe', common.mustCall(noop));
+ dest.on('unpipe', common.mustCall(noop));
+ src.pipe(dest);
+ setImmediate(function () {
+ assert.strictEqual(src._readableState.pipesCount, 0);
+ });
+}
+
+{
+ var _dest = new NullWriteable();
+ var _src = new NeverEndReadable();
+ _dest.on('pipe', common.mustCall(noop));
+ _dest.on('unpipe', common.mustNotCall('unpipe should not have been emitted'));
+ _src.pipe(_dest);
+ setImmediate(function () {
+ assert.strictEqual(_src._readableState.pipesCount, 1);
+ });
+}
+
+{
+ var _dest2 = new NullWriteable();
+ var _src2 = new NeverEndReadable();
+ _dest2.on('pipe', common.mustCall(noop));
+ _dest2.on('unpipe', common.mustCall(noop));
+ _src2.pipe(_dest2);
+ _src2.unpipe(_dest2);
+ setImmediate(function () {
+ assert.strictEqual(_src2._readableState.pipesCount, 0);
+ });
+}
+
+{
+ var _dest3 = new NullWriteable();
+ var _src3 = new QuickEndReadable();
+ _dest3.on('pipe', common.mustCall(noop));
+ _dest3.on('unpipe', common.mustCall(noop));
+ _src3.pipe(_dest3, { end: false });
+ setImmediate(function () {
+ assert.strictEqual(_src3._readableState.pipesCount, 0);
+ });
+}
+
+{
+ var _dest4 = new NullWriteable();
+ var _src4 = new NeverEndReadable();
+ _dest4.on('pipe', common.mustCall(noop));
+ _dest4.on('unpipe', common.mustNotCall('unpipe should not have been emitted'));
+ _src4.pipe(_dest4, { end: false });
+ setImmediate(function () {
+ assert.strictEqual(_src4._readableState.pipesCount, 1);
+ });
+}
+
+{
+ var _dest5 = new NullWriteable();
+ var _src5 = new NeverEndReadable();
+ _dest5.on('pipe', common.mustCall(noop));
+ _dest5.on('unpipe', common.mustCall(noop));
+ _src5.pipe(_dest5, { end: false });
+ _src5.unpipe(_dest5);
+ setImmediate(function () {
+ assert.strictEqual(_src5._readableState.pipesCount, 0);
+ });
+}
\ No newline at end of file