diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js index 98ca05da395..daef34b50c4 100644 --- a/lib/_stream_writable.js +++ b/lib/_stream_writable.js @@ -176,13 +176,19 @@ function writeAfterEnd(stream, cb) { // how many bytes or characters. function validChunk(stream, state, chunk, cb) { var valid = true; - - if (!(chunk instanceof Buffer) && + var er = false; + // Always throw error if a null is written + // if we are not in object mode then throw + // if it is not a buffer, string, or undefined. + if (chunk === null) { + er = new TypeError('May not write null values to stream'); + } else if (!(chunk instanceof Buffer) && typeof chunk !== 'string' && - chunk !== null && chunk !== undefined && !state.objectMode) { - var er = new TypeError('Invalid non-string/buffer chunk'); + er = new TypeError('Invalid non-string/buffer chunk'); + } + if (er) { stream.emit('error', er); process.nextTick(cb, er); valid = false; diff --git a/test/parallel/test-stream-writable-null.js b/test/parallel/test-stream-writable-null.js new file mode 100644 index 00000000000..2cc396bd916 --- /dev/null +++ b/test/parallel/test-stream-writable-null.js @@ -0,0 +1,56 @@ +'use strict'; +require('../common'); +const assert = require('assert'); + +const stream = require('stream'); +const util = require('util'); + +function MyWritable(options) { + stream.Writable.call(this, options); +} + +util.inherits(MyWritable, stream.Writable); + +MyWritable.prototype._write = function(chunk, encoding, callback) { + assert.notStrictEqual(chunk, null); + callback(); +}; + +assert.throws(() => { + var m = new MyWritable({objectMode: true}); + m.write(null, (err) => assert.ok(err)); +}, TypeError, 'May not write null values to stream'); +assert.doesNotThrow(() => { + var m = new MyWritable({objectMode: true}).on('error', (e) => { + assert.ok(e); + }); + m.write(null, (err) => { + assert.ok(err); + }); +}); + +assert.throws(() => { + var m = new MyWritable(); + m.write(false, (err) => assert.ok(err)); +}, TypeError, 'Invalid non-string/buffer chunk'); +assert.doesNotThrow(() => { + var m = new MyWritable().on('error', (e) => { + assert.ok(e); + }); + m.write(false, (err) => { + assert.ok(err); + }); +}); + +assert.doesNotThrow(() => { + var m = new MyWritable({objectMode: true}); + m.write(false, (err) => assert.ifError(err)); +}); +assert.doesNotThrow(() => { + var m = new MyWritable({objectMode: true}).on('error', (e) => { + assert.ifError(e || new Error('should not get here')); + }); + m.write(false, (err) => { + assert.ifError(err); + }); +});