stream: Writables are not pipe()able
authorisaacs <i@izs.me>
Mon, 25 Feb 2013 06:14:30 +0000 (22:14 -0800)
committerisaacs <i@izs.me>
Wed, 27 Feb 2013 02:54:05 +0000 (18:54 -0800)
This handles the fact that stream.Writable inherits from the Stream class,
meaning that it has the legacy pipe() method.  Override that with a pipe()
method that emits an error.

Ensure that Duplex streams ARE still pipe()able, however.

Since the 'readable' flag on streams is sometimes temporary, it's probably
better not to put too much weight on that.  But if something is an instanceof
Writable, rather than of Readable or Duplex, then it's safe to say that
reading from it is the wrong thing to do.

Fix #3647

lib/_stream_writable.js
test/simple/test-stream2-writable.js

index 9a5e7f0..b8f88be 100644 (file)
@@ -111,6 +111,11 @@ function Writable(options) {
   Stream.call(this);
 }
 
+// Otherwise people can pipe Writable streams, which is just wrong.
+Writable.prototype.pipe = function() {
+  this.emit('error', new Error('Cannot pipe. Not readable.'));
+};
+
 // Override this method or _write(chunk, cb)
 Writable.prototype.write = function(chunk, encoding, cb) {
   var state = this._writableState;
index 4cd37fd..efd4902 100644 (file)
@@ -21,6 +21,7 @@
 
 var common = require('../common.js');
 var W = require('_stream_writable');
+var D = require('_stream_duplex');
 var assert = require('assert');
 
 var util = require('util');
@@ -285,3 +286,28 @@ test('encoding should be ignored for buffers', function(t) {
   var buf = new Buffer(hex, 'hex');
   tw.write(buf, 'binary');
 });
+
+test('writables are not pipable', function(t) {
+  var w = new W();
+  w._write = function() {};
+  var gotError = false;
+  w.on('error', function(er) {
+    gotError = true;
+  });
+  w.pipe(process.stdout);
+  assert(gotError);
+  t.end();
+});
+
+test('duplexes are pipable', function(t) {
+  var d = new D();
+  d._read = function() {};
+  d._write = function() {};
+  var gotError = false;
+  d.on('error', function(er) {
+    gotError = true;
+  });
+  d.pipe(process.stdout);
+  assert(!gotError);
+  t.end();
+});