@@ -196,23 +196,18 @@ function writeAfterEnd(stream, cb) { |
196 | 196 | process.nextTick(cb, er); |
197 | 197 | } |
198 | 198 |
|
199 | | -// If we get something that is not a buffer, string, null, or undefined, |
200 | | -// and we're not in objectMode, then that's an error. |
201 | | -// Otherwise stream chunks are all considered to be of length=1, and the |
202 | | -// watermarks determine how many objects to keep in the buffer, rather than |
203 | | -// how many bytes or characters. |
| 199 | +// Checks that a user-supplied chunk is valid, especially for the particular |
| 200 | +// mode the stream is in. Currently this means that `null` is never accepted |
| 201 | +// and undefined/non-string values are only allowed in object mode. |
204 | 202 | function validChunk(stream, state, chunk, cb) { |
205 | 203 | var valid = true; |
206 | 204 | var er = false; |
207 | | - // Always throw error if a null is written |
208 | | - // if we are not in object mode then throw |
209 | | - // if it is not a buffer, string, or undefined. |
| 205 | + |
210 | 206 | if (chunk === null) { |
211 | 207 | er = new TypeError('May not write null values to stream'); |
212 | | - } else if (!(chunk instanceof Buffer) && |
213 | | - typeof chunk !== 'string' && |
214 | | - chunk !== undefined && |
215 | | - !state.objectMode) { |
| 208 | + } else if (typeof chunk !== 'string' && |
| 209 | + chunk !== undefined && |
| 210 | + !state.objectMode) { |
216 | 211 | er = new TypeError('Invalid non-string/buffer chunk'); |
217 | 212 | } |
218 | 213 | if (er) { |
@@ -226,13 +221,14 @@ function validChunk(stream, state, chunk, cb) { |
226 | 221 | Writable.prototype.write = function(chunk, encoding, cb) { |
227 | 222 | var state = this._writableState; |
228 | 223 | var ret = false; |
| 224 | + var isBuf = (chunk instanceof Buffer); |
229 | 225 |
|
230 | 226 | if (typeof encoding === 'function') { |
231 | 227 | cb = encoding; |
232 | 228 | encoding = null; |
233 | 229 | } |
234 | 230 |
|
235 | | - if (chunk instanceof Buffer) |
| 231 | + if (isBuf) |
236 | 232 | encoding = 'buffer'; |
237 | 233 | else if (!encoding) |
238 | 234 | encoding = state.defaultEncoding; |
@@ -242,9 +238,9 @@ Writable.prototype.write = function(chunk, encoding, cb) { |
242 | 238 |
|
243 | 239 | if (state.ended) |
244 | 240 | writeAfterEnd(this, cb); |
245 | | - else if (validChunk(this, state, chunk, cb)) { |
| 241 | + else if (isBuf || validChunk(this, state, chunk, cb)) { |
246 | 242 | state.pendingcb++; |
247 | | - ret = writeOrBuffer(this, state, chunk, encoding, cb); |
| 243 | + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); |
248 | 244 | } |
249 | 245 |
|
250 | 246 | return ret; |
@@ -293,11 +289,12 @@ function decodeChunk(state, chunk, encoding) { |
293 | 289 | // if we're already writing something, then just put this |
294 | 290 | // in the queue, and wait our turn. Otherwise, call _write |
295 | 291 | // If we return false, then we need a drain event, so set that flag. |
296 | | -function writeOrBuffer(stream, state, chunk, encoding, cb) { |
297 | | - chunk = decodeChunk(state, chunk, encoding); |
298 | | - |
299 | | - if (chunk instanceof Buffer) |
300 | | - encoding = 'buffer'; |
| 292 | +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { |
| 293 | + if (!isBuf) { |
| 294 | + chunk = decodeChunk(state, chunk, encoding); |
| 295 | + if (chunk instanceof Buffer) |
| 296 | + encoding = 'buffer'; |
| 297 | + } |
301 | 298 | var len = state.objectMode ? 1 : chunk.length; |
302 | 299 |
|
303 | 300 | state.length += len; |
|