mirror of
https://github.com/nodejs/node.git
synced 2025-05-10 01:07:57 +00:00

This improves error handling for streams in a few ways. 1. It ensures that no user defined methods (_read, _write, ...) are run after .destroy has been called. 2. It introduces an explicit error to tell the user if they are write to write, etc to the stream after it has been destroyed. 3. It makes streams always emit close as the last thing after they have been destroyed 4. Changes the default _destroy to not gracefully end streams. It also updates net, http2, zlib and fs to the new error handling. PR-URL: https://github.com/nodejs/node/pull/18438 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net>
82 lines
2.0 KiB
JavaScript
82 lines
2.0 KiB
JavaScript
'use strict';
|
|
|
|
// undocumented cb() API, needed for core, not for public API
|
|
function destroy(err, cb) {
|
|
const readableDestroyed = this._readableState &&
|
|
this._readableState.destroyed;
|
|
const writableDestroyed = this._writableState &&
|
|
this._writableState.destroyed;
|
|
|
|
if (readableDestroyed || writableDestroyed) {
|
|
if (cb) {
|
|
cb(err);
|
|
} else if (err &&
|
|
(!this._writableState || !this._writableState.errorEmitted)) {
|
|
process.nextTick(emitErrorNT, this, err);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
// we set destroyed to true before firing error callbacks in order
|
|
// to make it re-entrance safe in case destroy() is called within callbacks
|
|
|
|
if (this._readableState) {
|
|
this._readableState.destroyed = true;
|
|
}
|
|
|
|
// if this is a duplex stream mark the writable part as destroyed as well
|
|
if (this._writableState) {
|
|
this._writableState.destroyed = true;
|
|
}
|
|
|
|
this._destroy(err || null, (err) => {
|
|
process.nextTick(emitCloseNT, this);
|
|
if (!cb && err) {
|
|
process.nextTick(emitErrorNT, this, err);
|
|
if (this._writableState) {
|
|
this._writableState.errorEmitted = true;
|
|
}
|
|
} else if (cb) {
|
|
cb(err);
|
|
}
|
|
});
|
|
|
|
return this;
|
|
}
|
|
|
|
function emitCloseNT(self) {
|
|
if (self._writableState && !self._writableState.emitClose)
|
|
return;
|
|
if (self._readableState && !self._readableState.emitClose)
|
|
return;
|
|
self.emit('close');
|
|
}
|
|
|
|
function undestroy() {
|
|
if (this._readableState) {
|
|
this._readableState.destroyed = false;
|
|
this._readableState.reading = false;
|
|
this._readableState.ended = false;
|
|
this._readableState.endEmitted = false;
|
|
}
|
|
|
|
if (this._writableState) {
|
|
this._writableState.destroyed = false;
|
|
this._writableState.ended = false;
|
|
this._writableState.ending = false;
|
|
this._writableState.finalCalled = false;
|
|
this._writableState.prefinished = false;
|
|
this._writableState.finished = false;
|
|
this._writableState.errorEmitted = false;
|
|
}
|
|
}
|
|
|
|
function emitErrorNT(self, err) {
|
|
self.emit('error', err);
|
|
}
|
|
|
|
module.exports = {
|
|
destroy,
|
|
undestroy
|
|
};
|