Skip to content

Commit 1899689

Browse files
committed
stream: emit .write() end error in next tick.
This changes the behaviour of error event emitted when writing to a stream after it has ended, from synchronously to asynchronously. PR-URL: #4749
1 parent eee9dc7 commit 1899689

File tree

3 files changed

+45
-11
lines changed

3 files changed

+45
-11
lines changed

lib/_stream_writable.js

+5-6
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,10 @@ Writable.prototype.pipe = function() {
155155
};
156156

157157

158-
function writeAfterEnd(stream, cb) {
159-
var er = new Error('write after end');
160-
// TODO: defer error events consistently everywhere, not just the cb
161-
stream.emit('error', er);
162-
process.nextTick(cb, er);
158+
function writeAfterEndErr(stream, cb) {
159+
const err = new Error('write after end');
160+
stream.emit('error', err);
161+
cb(err);
163162
}
164163

165164
// If we get something that is not a buffer, string, null, or undefined,
@@ -201,7 +200,7 @@ Writable.prototype.write = function(chunk, encoding, cb) {
201200
cb = nop;
202201

203202
if (state.ended)
204-
writeAfterEnd(this, cb);
203+
process.nextTick(writeAfterEndErr, this, cb);
205204
else if (validChunk(this, state, chunk, cb)) {
206205
state.pendingcb++;
207206
ret = writeOrBuffer(this, state, chunk, encoding, cb);

test/parallel/test-file-write-stream.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ var EXPECTED = '012345678910';
1515
var callbacks = {
1616
open: -1,
1717
drain: -2,
18-
close: -1
18+
close: -1,
19+
error: -1
1920
};
2021

2122
file
@@ -25,6 +26,10 @@ file
2526
assert.equal('number', typeof fd);
2627
})
2728
.on('error', function(err) {
29+
// we're expecting write after end error
30+
if (err.message === 'write after end') {
31+
return callbacks.error++;
32+
}
2833
throw err;
2934
})
3035
.on('drain', function() {
@@ -43,10 +48,9 @@ file
4348
assert.strictEqual(file.bytesWritten, EXPECTED.length * 2);
4449

4550
callbacks.close++;
46-
assert.throws(function() {
47-
console.error('write after end should not be allowed');
48-
file.write('should not work anymore');
49-
});
51+
52+
console.error('write after end should not be allowed');
53+
file.write('should not work anymore');
5054

5155
fs.unlinkSync(fn);
5256
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict';
2+
3+
require('../common');
4+
5+
const assert = require('assert');
6+
const Writable = require('stream').Writable;
7+
8+
const stream = new Writable({ write });
9+
10+
let errorsRecorded = 0;
11+
12+
function write() {
13+
throw new Error('write() should not have been called!');
14+
}
15+
16+
function errorRecorder(err) {
17+
if (err.message === 'write after end') {
18+
errorsRecorded++;
19+
}
20+
}
21+
22+
// should trigger ended errors when writing later
23+
stream.end();
24+
25+
stream.on('error', errorRecorder);
26+
stream.write('this should explode', errorRecorder);
27+
28+
assert.equal(errorsRecorded, 0,
29+
'Waits until next tick before emitting error');
30+
31+
process.nextTick(() => assert.equal(errorsRecorded, 2));

0 commit comments

Comments
 (0)