diff --git a/doc/api/stream.markdown b/doc/api/stream.markdown
index 943718660cbcb8..4cb7b1b4f9599c 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,135 @@ 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 API Via Revealing Constructor Pattern
+
+
+
+To implement any sort of stream you can now pass that streams specific methods as parameters to the constructors options:
+
+
+
+
+
+ Use-case
+ |
+
+ Class
+ |
+
+ Method(s) to implement
+ |
+
+
+
+
+ Reading only
+ |
+
+ [Readable](#stream_class_stream_readable_1)
+ |
+
+ [read][_read]
+ |
+
+
+
+ Writing only
+ |
+
+ [Writable](#stream_class_stream_writable_1)
+ |
+
+ [write][_write]
+ |
+
+
+
+ Reading and writing
+ |
+
+ [Duplex](#stream_class_stream_duplex_1)
+ |
+
+ [read][_read] , [write][_write] , writev
+ |
+
+
+
+ Operate on written data, then read the result
+ |
+
+ [Transform](#stream_class_stream_transform_1)
+ |
+
+ transform , flush
+ |
+
+
+
+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-revealing-constructor.js b/test/parallel/test-stream-readable-revealing-constructor.js
new file mode 100644
index 00000000000000..ea1703fa46ef9b
--- /dev/null
+++ b/test/parallel/test-stream-readable-revealing-constructor.js
@@ -0,0 +1,19 @@
+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);
+ console.log('ok');
+});
diff --git a/test/parallel/test-stream-transform-revealing-constructor.js b/test/parallel/test-stream-transform-revealing-constructor.js
new file mode 100644
index 00000000000000..e354612798ecb7
--- /dev/null
+++ b/test/parallel/test-stream-transform-revealing-constructor.js
@@ -0,0 +1,32 @@
+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);
+ console.log('ok');
+});
diff --git a/test/parallel/test-stream-writable-revealing-constructor.js b/test/parallel/test-stream-writable-revealing-constructor.js
new file mode 100644
index 00000000000000..42ecf419e4420a
--- /dev/null
+++ b/test/parallel/test-stream-writable-revealing-constructor.js
@@ -0,0 +1,44 @@
+var common = require('../common');
+var assert = require('assert');
+
+var Writable = require('stream').Writable;
+
+(function one() {
+ var _writeCalled = false;
+ function _write(d, e, n) {
+ _writeCalled = true;
+ }
+
+ var w = new Writable({ write: _write });
+ w.end(new Buffer('blerg'));
+
+ process.on('exit', function () {
+ assert.equal(w._write, _write);
+ assert(_writeCalled);
+ console.log('ok 1');
+ });
+}());
+
+(function two() {
+ var _writevCalled = false;
+ var dLength = 0;
+
+ function _writev(d, n) {
+ dLength = d.length;
+ _writevCalled = true;
+ }
+
+ var w = new Writable({ writev: _writev });
+ w.cork();
+
+ w.write(new Buffer('blerg'));
+ w.write(new Buffer('blerg'));
+ w.end();
+
+ process.on('exit', function () {
+ assert.equal(w._writev, _writev);
+ assert.equal(dLength, 2);
+ assert(_writevCalled);
+ console.log('ok 2');
+ });
+}());