stream: call write cb before finish event

Since 049903e, an end callback could be called before a write
callback if end() is called before the write is done. This patch
resolves the issue.

In collaboration with @gne

Fixes felixge/node-formidable#209
Fixes #5215
This commit is contained in:
isaacs 2013-04-08 11:00:26 -07:00 committed by Fedor Indutny
parent e4b716efaa
commit c93af860a0
2 changed files with 44 additions and 6 deletions

View File

@ -240,7 +240,8 @@ function onwrite(stream, er) {
if (er)
onwriteError(stream, state, sync, er, cb);
else {
var finished = finishMaybe(stream, state);
// Check if we're actually ready to finish, but don't emit yet
var finished = needFinish(stream, state);
if (!finished && !state.bufferProcessing && state.buffer.length)
clearBuffer(stream, state);
@ -259,6 +260,8 @@ function afterWrite(stream, state, finished, cb) {
if (!finished)
onwriteDrain(stream, state);
cb();
if (finished)
finishMaybe(stream, state);
}
// Must force callback to be called on nextTick, so that we don't
@ -326,15 +329,21 @@ Writable.prototype.end = function(chunk, encoding, cb) {
endWritable(this, state, cb);
};
function needFinish(stream, state) {
return (state.ending &&
state.length === 0 &&
!state.finished &&
!state.writing);
}
function finishMaybe(stream, state) {
if (state.ending &&
state.length === 0 &&
!state.finished &&
!state.writing) {
var need = needFinish(stream, state);
if (need) {
state.finished = true;
stream.emit('finish');
}
return state.finished;
return need;
}
function endWritable(stream, state, cb) {

View File

@ -275,6 +275,18 @@ test('end callback after .write() call', function (t) {
});
});
test('end callback called after write callback', function (t) {
var tw = new TestWriter();
var writeCalledback = false;
tw.write(new Buffer('hello world'), function() {
writeCalledback = true;
});
tw.end(function () {
t.equal(writeCalledback, true);
t.end();
});
});
test('encoding should be ignored for buffers', function(t) {
var tw = new W();
var hex = '018b5e9a8f6236ffe30e31baf80d2cf6eb';
@ -346,3 +358,20 @@ test('dont end while writing', function(t) {
w.write(Buffer(0));
w.end();
});
test('finish does not come before write cb', function(t) {
var w = new W();
var writeCb = false;
w._write = function(chunk, e, cb) {
setTimeout(function() {
writeCb = true;
cb();
}, 10);
};
w.on('finish', function() {
assert(writeCb);
t.end();
});
w.write(Buffer(0));
w.end();
});