From 784bce39d769b2de977feaf434ca515b568a9d83 Mon Sep 17 00:00:00 2001 From: Calvin Metcalf Date: Fri, 30 Jan 2015 09:03:02 -0500 Subject: [PATCH] streams: make streams lazy by default Makes streams lazy by default so crypto does not need to monky patch them in order to get good performance. This helps the state objects become part of the private api in #445. --- lib/_stream_duplex.js | 19 +++++++++++++++++++ lib/_stream_readable.js | 19 ++++++++++++++++++- lib/_stream_transform.js | 16 ++++++++++++++++ lib/_stream_writable.js | 20 +++++++++++++++++++- lib/crypto.js | 30 ++++-------------------------- 5 files changed, 76 insertions(+), 28 deletions(-) diff --git a/lib/_stream_duplex.js b/lib/_stream_duplex.js index 159e1f2aca6614..7f870fe3f1a302 100644 --- a/lib/_stream_duplex.js +++ b/lib/_stream_duplex.js @@ -27,6 +27,8 @@ function Duplex(options) { Readable.call(this, options); Writable.call(this, options); + this._options = this._options; + if (options && options.readable === false) this.readable = false; @@ -40,6 +42,23 @@ function Duplex(options) { this.once('end', onend); } +Object.defineProperty(Duplex.prototype, '_writableState', { + get: function() { + this._writableState = new Writable.WritableState(this._options, this); + return this._writableState; + }, + set: function(val) { + Object.defineProperty(this, '_writableState', { + value: val, + enumerable: true, + configurable: true, + writable: true + }); + }, + configurable: true, + enumerable: false +}); + // the no-half-open enforcer function onend() { // if we allow half-open state, or if the writable side ended, diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index da164208289d1f..522ba221233f05 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -80,7 +80,7 @@ function Readable(options) { if (!(this instanceof Readable)) return new Readable(options); - this._readableState = new ReadableState(options, this); + this._options = options; // legacy this.readable = true; @@ -88,6 +88,23 @@ function Readable(options) { Stream.call(this); } +Object.defineProperty(Readable.prototype, '_readableState', { + get: function() { + this._readableState = new ReadableState(this._options, this); + return this._readableState; + }, + set: function(val) { + Object.defineProperty(this, '_readableState', { + value: val, + enumerable: true, + configurable: true, + writable: true + }); + }, + configurable: true, + enumerable: true +}); + // Manually shove something into the read() buffer. // This returns true if the highWaterMark has not been hit yet, // similar to how Writable.write() returns true if you should diff --git a/lib/_stream_transform.js b/lib/_stream_transform.js index f83620863308dc..0312376017de13 100644 --- a/lib/_stream_transform.js +++ b/lib/_stream_transform.js @@ -115,6 +115,22 @@ function Transform(options) { }); } +Object.defineProperty(Transform.prototype, '_transformState', { + get: function() { + this._transformState = new TransformState(this); + return this._transformState; + }, + set: function(val) { + Object.defineProperty(this, '_transformState', { + value: val, + enumerable: true, + configurable: true, + writable: true + }); + }, + configurable: true, + enumerable: true +}); Transform.prototype.push = function(chunk, encoding) { this._transformState.needTransform = false; return Duplex.prototype.push.call(this, chunk, encoding); diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js index a3c65f45951800..4590e87d9008fe 100644 --- a/lib/_stream_writable.js +++ b/lib/_stream_writable.js @@ -132,7 +132,7 @@ function Writable(options) { if (!(this instanceof Writable) && !(this instanceof Stream.Duplex)) return new Writable(options); - this._writableState = new WritableState(options, this); + this._options = options; // legacy. this.writable = true; @@ -140,6 +140,24 @@ function Writable(options) { Stream.call(this); } + +Object.defineProperty(Writable.prototype, '_writableState', { + get: function() { + this._writableState = new WritableState(this._options, this); + return this._writableState; + }, + set: function(val) { + Object.defineProperty(this, '_writableState', { + value: val, + enumerable: true, + configurable: true, + writable: true + }); + }, + configurable: true, + enumerable: false +}); + // Otherwise people can pipe Writable streams, which is just wrong. Writable.prototype.pipe = function() { this.emit('error', new Error('Cannot pipe. Not readable.')); diff --git a/lib/crypto.js b/lib/crypto.js index f8efffda483ec7..d01ef7fa3c7424 100644 --- a/lib/crypto.js +++ b/lib/crypto.js @@ -40,35 +40,13 @@ const StringDecoder = require('string_decoder').StringDecoder; function LazyTransform(options) { - this._options = options; + options = options || {}; + options.defaultEncoding = 'binary'; + options.decodeStrings = false; + stream.Transform.call(this, options); } util.inherits(LazyTransform, stream.Transform); -[ - '_readableState', - '_writableState', - '_transformState' -].forEach(function(prop, i, props) { - Object.defineProperty(LazyTransform.prototype, prop, { - get: function() { - stream.Transform.call(this, this._options); - this._writableState.decodeStrings = false; - this._writableState.defaultEncoding = 'binary'; - return this[prop]; - }, - set: function(val) { - Object.defineProperty(this, prop, { - value: val, - enumerable: true, - configurable: true, - writable: true - }); - }, - configurable: true, - enumerable: true - }); -}); - exports.createHash = exports.Hash = Hash; function Hash(algorithm, options) {