Skip to content

Commit e056535

Browse files
committed
stream: don't emit errors after destroy
- Don't emit any error on destroy(). - Emit error on destroy(err). - Always pass any error to callbak in destroy(err, cb).
1 parent 3238232 commit e056535

File tree

5 files changed

+43
-25
lines changed

5 files changed

+43
-25
lines changed

lib/internal/streams/destroy.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,8 @@ function destroy(err, cb) {
2929

3030
if ((w && w.destroyed) || (r && r.destroyed)) {
3131
if (cb) {
32-
cb(err);
33-
} else if (needError(this, err)) {
34-
process.nextTick(emitErrorNT, this, err);
32+
cb(err || null);
3533
}
36-
3734
return this;
3835
}
3936

@@ -47,11 +44,11 @@ function destroy(err, cb) {
4744
r.destroyed = true;
4845
}
4946

50-
this._destroy(err || null, (err) => {
47+
this._destroy(err || null, (er) => {
5148
if (cb) {
52-
process.nextTick(emitCloseNT, this);
53-
cb(err);
54-
} else if (needError(this, err)) {
49+
cb(er || null);
50+
}
51+
if (err && needError(this, er || null)) {
5552
process.nextTick(emitErrorAndCloseNT, this, err);
5653
} else {
5754
process.nextTick(emitCloseNT, this);
@@ -114,6 +111,11 @@ function errorOrDestroy(stream, err) {
114111
const r = stream._readableState;
115112
const w = stream._writableState;
116113

114+
// Don't emit errors if already destroyed.
115+
if ((w && w.destroyed) || (r && r.destroyed)) {
116+
return;
117+
}
118+
117119
if ((r && r.autoDestroy) || (w && w.autoDestroy))
118120
stream.destroy(err);
119121
else if (needError(stream, err))

test/parallel/test-stream-duplex-destroy.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,7 @@ const assert = require('assert');
144144

145145
duplex.on('finish', common.mustNotCall('no finish event'));
146146
duplex.on('end', common.mustNotCall('no end event'));
147-
duplex.on('error', common.mustCall((err) => {
148-
assert.strictEqual(err, expected);
149-
}));
147+
duplex.on('error', common.mustNotCall());
150148

151149
duplex.destroy();
152150
assert.strictEqual(duplex.destroyed, true);

test/parallel/test-stream-readable-destroy.js

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,7 @@ const assert = require('assert');
130130
});
131131

132132
read.on('end', common.mustNotCall('no end event'));
133-
read.on('error', common.mustCall((err) => {
134-
assert.strictEqual(err, expected);
135-
}));
133+
read.on('error', common.mustNotCall());
136134

137135
read.destroy();
138136
assert.strictEqual(read.destroyed, true);
@@ -175,6 +173,7 @@ const assert = require('assert');
175173
const expected = new Error('kaboom');
176174

177175
read.on('close', common.mustCall());
176+
read.on('error', common.mustCall());
178177
read.destroy(expected, common.mustCall(function(err) {
179178
assert.strictEqual(err, expected);
180179
}));
@@ -189,3 +188,29 @@ const assert = require('assert');
189188
read.push('hi');
190189
read.on('data', common.mustNotCall());
191190
}
191+
192+
{
193+
const read = new Readable({
194+
read() {},
195+
destroy: common.mustCall((err, cb) => {
196+
cb(new Error('test'));
197+
})
198+
});
199+
200+
read.on('error', common.mustNotCall());
201+
read.destroy();
202+
}
203+
204+
{
205+
const read = new Readable({
206+
read() {},
207+
destroy: common.mustCall((err, cb) => {
208+
cb(new Error('test'))
209+
})
210+
});
211+
212+
read.on('error', common.mustCall(err => {
213+
assert.strictEqual(err.message, 'destroyed');
214+
}));
215+
read.destroy(new Error('destroyed'));
216+
}

test/parallel/test-stream-transform-destroy.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,7 @@ const assert = require('assert');
135135
transform.on('close', common.mustCall());
136136
transform.on('finish', common.mustNotCall('no finish event'));
137137
transform.on('end', common.mustNotCall('no end event'));
138-
transform.on('error', common.mustCall((err) => {
139-
assert.strictEqual(err, expected);
140-
}));
138+
transform.on('error', common.mustNotCall());
141139

142140
transform.destroy();
143141
}

test/parallel/test-stream-writable-destroy.js

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,7 @@ const assert = require('assert');
129129

130130
write.on('close', common.mustCall());
131131
write.on('finish', common.mustNotCall('no finish event'));
132-
write.on('error', common.mustCall((err) => {
133-
assert.strictEqual(err, expected);
134-
}));
132+
write.on('error', common.mustNotCall());
135133

136134
write.destroy();
137135
assert.strictEqual(write.destroyed, true);
@@ -163,10 +161,7 @@ const assert = require('assert');
163161
});
164162

165163
writable.on('close', common.mustCall());
166-
writable.on('error', common.expectsError({
167-
type: Error,
168-
message: 'kaboom 2'
169-
}));
164+
writable.on('error', common.mustNotCall());
170165

171166
writable.destroy();
172167
assert.strictEqual(writable.destroyed, true);
@@ -175,7 +170,7 @@ const assert = require('assert');
175170
// Test case where `writable.destroy()` is called again with an error before
176171
// the `_destroy()` callback is called.
177172
writable.destroy(new Error('kaboom 2'));
178-
assert.strictEqual(writable._writableState.errorEmitted, true);
173+
assert.strictEqual(writable._writableState.errorEmitted, false);
179174
}
180175

181176
{

0 commit comments

Comments
 (0)