diff --git a/doc/api/stream.markdown b/doc/api/stream.markdown
index 943718660cbcb8..bbd2af0d7a3f95 100644
--- a/doc/api/stream.markdown
+++ b/doc/api/stream.markdown
@@ -718,7 +718,7 @@ of stream class you are writing:
[Writable](#stream_class_stream_writable_1)
- [_write][]
+ [_write][] , _writev
|
@@ -729,7 +729,7 @@ of stream class you are writing:
[Duplex](#stream_class_stream_duplex_1)
- [_read][] , [_write][]
+ [_read][] , [_write][] , _writev
|
@@ -1315,6 +1315,77 @@ for examples and testing, but there are occasionally use cases where
it can come in handy as a building block for novel sorts of streams.
+## Simplified Constructor API
+
+
+
+In simple cases there is now the added benefit of being able to construct a stream without inheritance.
+
+This can be done by passing the appropriate methods as constructor options:
+
+Examples:
+
+### Readable
+```javascript
+var readable = new stream.Readable({
+ read: function(n) {
+ // sets this._read under the hood
+ }
+});
+```
+
+### Writable
+```javascript
+var writable = new stream.Writable({
+ write: function(chunk, encoding, next) {
+ // sets this._write under the hood
+ }
+});
+
+// or
+
+var writable = new stream.Writable({
+ writev: function(chunks, next) {
+ // sets this._writev under the hood
+ }
+});
+```
+
+### Duplex
+```javascript
+var duplex = new stream.Duplex({
+ read: function(n) {
+ // sets this._read under the hood
+ },
+ write: function(chunk, encoding, next) {
+ // sets this._write under the hood
+ }
+});
+
+// or
+
+var duplex = new stream.Duplex({
+ read: function(n) {
+ // sets this._read under the hood
+ },
+ writev: function(chunks, next) {
+ // sets this._writev under the hood
+ }
+});
+```
+
+### Transform
+```javascript
+var transform = new stream.Transform({
+ transform: function(chunk, encoding, next) {
+ // sets this._transform under the hood
+ },
+ flush: function(done) {
+ // sets this._flush under the hood
+ }
+});
+```
+
## Streams: Under the Hood
diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js
index 2418648b69caa0..bf736477e80da6 100644
--- a/lib/_stream_readable.js
+++ b/lib/_stream_readable.js
@@ -85,6 +85,9 @@ function Readable(options) {
// legacy
this.readable = true;
+ if (options && typeof options.read === 'function')
+ this._read = options.read;
+
Stream.call(this);
}
diff --git a/lib/_stream_transform.js b/lib/_stream_transform.js
index d3e7a1348634ce..8ff428e11ffed0 100644
--- a/lib/_stream_transform.js
+++ b/lib/_stream_transform.js
@@ -105,6 +105,14 @@ function Transform(options) {
// sync guard flag.
this._readableState.sync = false;
+ if (options) {
+ if (typeof options.transform === 'function')
+ this._transform = options.transform;
+
+ if (typeof options.flush === 'function')
+ this._flush = options.flush;
+ }
+
this.once('prefinish', function() {
if (typeof this._flush === 'function')
this._flush(function(er) {
diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js
index 0176f4095fc76e..6a008fe76d2dbb 100644
--- a/lib/_stream_writable.js
+++ b/lib/_stream_writable.js
@@ -137,6 +137,14 @@ function Writable(options) {
// legacy.
this.writable = true;
+ if (options) {
+ if (typeof options.write === 'function')
+ this._write = options.write;
+
+ if (typeof options.writev === 'function')
+ this._writev = options.writev;
+ }
+
Stream.call(this);
}
diff --git a/test/parallel/test-stream-readable-constructor-set-methods.js b/test/parallel/test-stream-readable-constructor-set-methods.js
new file mode 100644
index 00000000000000..a88ffcd67a1446
--- /dev/null
+++ b/test/parallel/test-stream-readable-constructor-set-methods.js
@@ -0,0 +1,18 @@
+var common = require('../common');
+var assert = require('assert');
+
+var Readable = require('stream').Readable;
+
+var _readCalled = false;
+function _read(n) {
+ _readCalled = true;
+ this.push(null);
+}
+
+var r = new Readable({ read: _read });
+r.resume();
+
+process.on('exit', function () {
+ assert.equal(r._read, _read);
+ assert(_readCalled);
+});
diff --git a/test/parallel/test-stream-transform-constructor-set-methods.js b/test/parallel/test-stream-transform-constructor-set-methods.js
new file mode 100644
index 00000000000000..55e64ed9b2e733
--- /dev/null
+++ b/test/parallel/test-stream-transform-constructor-set-methods.js
@@ -0,0 +1,31 @@
+var common = require('../common');
+var assert = require('assert');
+
+var Transform = require('stream').Transform;
+
+var _transformCalled = false;
+function _transform(d, e, n) {
+ _transformCalled = true;
+ n();
+}
+
+var _flushCalled = false;
+function _flush(n) {
+ _flushCalled = true;
+ n();
+}
+
+var t = new Transform({
+ transform: _transform,
+ flush: _flush
+});
+
+t.end(new Buffer('blerg'));
+t.resume();
+
+process.on('exit', function () {
+ assert.equal(t._transform, _transform);
+ assert.equal(t._flush, _flush);
+ assert(_transformCalled);
+ assert(_flushCalled);
+});
diff --git a/test/parallel/test-stream-writable-constructor-set-methods.js b/test/parallel/test-stream-writable-constructor-set-methods.js
new file mode 100644
index 00000000000000..496ce6697582d0
--- /dev/null
+++ b/test/parallel/test-stream-writable-constructor-set-methods.js
@@ -0,0 +1,34 @@
+var common = require('../common');
+var assert = require('assert');
+
+var Writable = require('stream').Writable;
+
+var _writeCalled = false;
+function _write(d, e, n) {
+ _writeCalled = true;
+}
+
+var w = new Writable({ write: _write });
+w.end(new Buffer('blerg'));
+
+var _writevCalled = false;
+var dLength = 0;
+function _writev(d, n) {
+ dLength = d.length;
+ _writevCalled = true;
+}
+
+var w2 = new Writable({ writev: _writev });
+w2.cork();
+
+w2.write(new Buffer('blerg'));
+w2.write(new Buffer('blerg'));
+w2.end();
+
+process.on('exit', function () {
+ assert.equal(w._write, _write);
+ assert(_writeCalled);
+ assert.equal(w2._writev, _writev);
+ assert.equal(dLength, 2);
+ assert(_writevCalled);
+});