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;
encoding = null;
}
- state.ending = true;
if (chunk)
- this.write(chunk, encoding, cb);
- else if (state.length === 0 && !state.finishing && !state.finished) {
+ this.write(chunk, encoding);
+
+ // ignore unnecessary end() calls.
+ if (!state.ending && !state.ended && !state.finished)
+ endWritable(this, state, !!chunk, cb);
+};
+
+function endWritable(stream, state, hadChunk, cb) {
+ state.ending = true;
+ if (!hadChunk &&
+ 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;
};
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();
+ });
+});