Skip to content

Commit

Permalink
stream: destroying stream without error is abort
Browse files Browse the repository at this point in the history
If an autoDestroy stream is destroyed by user without
an error we automatically convert it to an AbortError in
order to avoid a weird state.
  • Loading branch information
ronag committed Nov 13, 2021
1 parent f217025 commit 873d061
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 1 deletion.
12 changes: 12 additions & 0 deletions doc/api/stream.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,10 @@ This is a destructive and immediate way to destroy a stream. Previous calls to
Use `end()` instead of destroy if data should flush before close, or wait for
the `'drain'` event before destroying the stream.

If `.destroy()` is called without an `error` and `autoDestroy` is
enabled, then if the stream has not completed it will be
automatically destroyed with an `AbortError`.

```cjs
const { Writable } = require('stream');

Expand Down Expand Up @@ -1101,6 +1105,10 @@ further errors except from `_destroy()` may be emitted as `'error'`.
Implementors should not override this method, but instead implement
[`readable._destroy()`][readable-_destroy].

If `.destroy()` is called without an `error` and `autoDestroy` is
enabled, then if the stream has not completed it will be
automatically destroyed with an `AbortError`.

##### `readable.closed`

<!-- YAML
Expand Down Expand Up @@ -1805,6 +1813,10 @@ unless `emitClose` is set in false.
Once `destroy()` has been called, any further calls will be a no-op and no
further errors except from `_destroy()` may be emitted as `'error'`.

If `.destroy()` is called without an `error` and `autoDestroy` is
enabled, then if the stream has not completed it will be
automatically destroyed with an `AbortError`.

### `stream.finished(stream[, options], callback)`

<!-- YAML
Expand Down
14 changes: 13 additions & 1 deletion lib/internal/streams/destroy.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';

const console = require('console');
const {
aggregateTwoErrors,
codes: {
Expand All @@ -14,7 +15,10 @@ const {
kDestroyed,
isDestroyed,
isFinished,
isServerRequest
isServerRequest,
isReadable,
isReadableFinished,
isWritableEnded
} = require('internal/streams/utils');

const kDestroy = Symbol('kDestroy');
Expand Down Expand Up @@ -86,6 +90,14 @@ function _destroy(self, err, cb) {
const r = self._readableState;
const w = self._writableState;

if (!err) {
if (r?.autoDestroy && !isReadableFinished(self)) {
err = new AbortError();
} else if (w?.autoDestroy && !isWritableEnded(self)) {
err = new AbortError();
}
}

checkError(err, w, r);

if (w) {
Expand Down
29 changes: 29 additions & 0 deletions test/parallel/test-stream-auto-abort.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict';

const { Readable, Writable } = require('stream');
const common = require('../common');
const assert = require('assert');

{
const w = new Writable({
write() {

}
});
w.on('error', common.mustCall((err) => {
assert.strictEqual(err.name, 'AbortError');
}));
w.destroy();
}

{
const r = new Readable({
read() {

}
});
r.on('error', common.mustCall((err) => {
assert.strictEqual(err.name, 'AbortError');
}));
r.destroy();
}

0 comments on commit 873d061

Please sign in to comment.