diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js index 62e0705763..debbab66de 100644 --- a/lib/_stream_writable.js +++ b/lib/_stream_writable.js @@ -304,10 +304,6 @@ Writable.prototype._write = function(chunk, cb) { Writable.prototype.end = function(chunk, encoding, cb) { var state = this._writableState; - // ignore unnecessary end() calls. - if (state.ending || state.ended || state.finished) - return; - if (typeof chunk === 'function') { cb = chunk; chunk = null; @@ -317,17 +313,26 @@ Writable.prototype.end = function(chunk, encoding, cb) { encoding = null; } + if (typeof chunk !== 'undefined' && chunk !== null) + this.write(chunk, encoding); + + // ignore unnecessary end() calls. + if (!state.ending && !state.ended && !state.finished) + endWritable(this, state, cb); +}; + +function endWritable(stream, state, cb) { state.ending = true; - if (chunk) - this.write(chunk, encoding, cb); - else if (state.length === 0 && !state.finishing && !state.finished) { + if (state.length === 0 && !state.finishing) { state.finishing = true; - this.emit('finish'); + stream.emit('finish'); state.finished = true; - if (cb) process.nextTick(cb); - } else if (cb) { - this.once('finish', cb); } - + if (cb) { + if (state.finished || state.finishing) + process.nextTick(cb); + else + stream.once('finish', cb); + } state.ended = true; -}; +} diff --git a/test/simple/test-stream2-writable.js b/test/simple/test-stream2-writable.js index efd49021bb..537660263b 100644 --- a/test/simple/test-stream2-writable.js +++ b/test/simple/test-stream2-writable.js @@ -311,3 +311,19 @@ test('duplexes are pipable', function(t) { assert(!gotError); t.end(); }); + +test('end(chunk) two times is an error', function(t) { + var w = new W(); + w._write = function() {}; + var gotError = false; + w.on('error', function(er) { + gotError = true; + t.equal(er.message, 'write after end'); + }); + w.end('this is the end'); + w.end('and so is this'); + process.nextTick(function() { + assert(gotError); + t.end(); + }); +});