Skip to content
This repository was archived by the owner on Apr 22, 2023. It is now read-only.

Commit bdb78b9

Browse files
committed
stream: don't create unnecessary buffers in Readable
If there is an encoding, and we do 'stream.push(chunk, enc)', and the encoding argument matches the stated encoding, then we're converting from a string, to a buffer, and then back to a string. Of course, this is a completely pointless bit of work, so it's best to avoid it when we know that we can do so safely.
1 parent 0b8af89 commit bdb78b9

File tree

3 files changed

+24
-11
lines changed

3 files changed

+24
-11
lines changed

doc/api/stream.markdown

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,15 @@ TLS, may ignore this argument, and simply provide data whenever it
131131
becomes available. There is no need, for example to "wait" until
132132
`size` bytes are available before calling `stream.push(chunk)`.
133133

134-
### readable.push(chunk)
134+
### readable.push(chunk, [encoding])
135135

136136
* `chunk` {Buffer | null | String} Chunk of data to push into the read queue
137+
* `encoding` {String} Encoding of String chunks. Must be a valid
138+
Buffer encoding, such as `'utf8'` or `'ascii'`
137139
* return {Boolean} Whether or not more pushes should be performed
138140

139141
Note: **This function should be called by Readable implementors, NOT
140-
by consumers of Readable subclasses.** The `_read()` function will not
142+
by consumers of Readable streams.** The `_read()` function will not
141143
be called again until at least one `push(chunk)` call is made. If no
142144
data is available, then you MAY call `push('')` (an empty string) to
143145
allow a future `_read` call, without adding any data to the queue.

lib/_stream_readable.js

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,12 @@ function ReadableState(options, stream) {
8383
this.readingMore = false;
8484

8585
this.decoder = null;
86+
this.encoding = null;
8687
if (options.encoding) {
8788
if (!StringDecoder)
8889
StringDecoder = require('string_decoder').StringDecoder;
8990
this.decoder = new StringDecoder(options.encoding);
91+
this.encoding = options.encoding;
9092
}
9193
}
9294

@@ -106,19 +108,27 @@ function Readable(options) {
106108
// This returns true if the highWaterMark has not been hit yet,
107109
// similar to how Writable.write() returns true if you should
108110
// write() some more.
109-
Readable.prototype.push = function(chunk) {
111+
Readable.prototype.push = function(chunk, encoding) {
110112
var state = this._readableState;
111-
if (typeof chunk === 'string' && !state.objectMode)
112-
chunk = new Buffer(chunk, arguments[1]);
113-
return readableAddChunk(this, state, chunk, false);
113+
114+
if (typeof chunk === 'string' && !state.objectMode) {
115+
encoding = encoding || 'utf8';
116+
if (encoding !== state.encoding) {
117+
chunk = new Buffer(chunk, encoding);
118+
encoding = '';
119+
}
120+
}
121+
122+
return readableAddChunk(this, state, chunk, encoding, false);
114123
};
115124

125+
// Unshift should *always* be something directly out of read()
116126
Readable.prototype.unshift = function(chunk) {
117127
var state = this._readableState;
118-
return readableAddChunk(this, state, chunk, true);
128+
return readableAddChunk(this, state, chunk, '', true);
119129
};
120130

121-
function readableAddChunk(stream, state, chunk, addToFront) {
131+
function readableAddChunk(stream, state, chunk, encoding, addToFront) {
122132
var er = chunkInvalid(state, chunk);
123133
if (er) {
124134
stream.emit('error', er);
@@ -134,7 +144,7 @@ function readableAddChunk(stream, state, chunk, addToFront) {
134144
var e = new Error('stream.unshift() after end event');
135145
stream.emit('error', e);
136146
} else {
137-
if (state.decoder && !addToFront)
147+
if (state.decoder && !addToFront && !encoding)
138148
chunk = state.decoder.write(chunk);
139149

140150
// update the buffer info.
@@ -179,6 +189,7 @@ Readable.prototype.setEncoding = function(enc) {
179189
if (!StringDecoder)
180190
StringDecoder = require('string_decoder').StringDecoder;
181191
this._readableState.decoder = new StringDecoder(enc);
192+
this._readableState.encoding = enc;
182193
};
183194

184195
// Don't raise the hwm > 128MB

lib/_stream_transform.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,9 @@ function Transform(options) {
135135
});
136136
}
137137

138-
Transform.prototype.push = function(chunk) {
138+
Transform.prototype.push = function(chunk, encoding) {
139139
this._transformState.needTransform = false;
140-
return Duplex.prototype.push.call(this, chunk);
140+
return Duplex.prototype.push.call(this, chunk, encoding);
141141
};
142142

143143
// This is the part where you do stuff!

0 commit comments

Comments
 (0)