mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
stream: writableNeedDrain
Don't write to a stream which already has a full buffer. Fixes: https://github.com/nodejs/node/issues/35341 PR-URL: https://github.com/nodejs/node/pull/35348 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
This commit is contained in:
1 parent
da53a3caa3
commit
dd0f8f18c2
7 files changed
+63
-1
No files matched your search
@@ -580,6 +580,15 @@ This property contains the number of bytes (or objects) in the queue
|
||||
ready to be written. The value provides introspection data regarding
|
||||
the status of the `highWaterMark`.
|
||||
|
||||
##### `writable.writableNeedDrain`
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
* {boolean}
|
||||
|
||||
Is `true` if the stream's buffer has been full and stream will emit `'drain'`.
|
||||
|
||||
##### `writable.writableObjectMode`
|
||||
<!-- YAML
|
||||
added: v12.3.0
|
||||
|
||||
@@ -660,6 +660,11 @@ ObjectDefineProperty(OutgoingMessage.prototype, 'writableEnded', {
|
||||
get: function() { return this.finished; }
|
||||
});
|
||||
|
||||
ObjectDefineProperty(OutgoingMessage.prototype, 'writableNeedDrain', {
|
||||
get: function() {
|
||||
return !this.destroyed && !this.finished && this[kNeedDrain];
|
||||
}
|
||||
});
|
||||
|
||||
const crlf_buf = Buffer.from('\r\n');
|
||||
OutgoingMessage.prototype.write = function write(chunk, encoding, callback) {
|
||||
|
||||
@@ -87,6 +87,8 @@ ObjectDefineProperties(Duplex.prototype, {
|
||||
ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableCorked'),
|
||||
writableEnded:
|
||||
ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableEnded'),
|
||||
writableNeedDrain:
|
||||
ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableNeedDrain'),
|
||||
|
||||
destroyed: {
|
||||
get() {
|
||||
|
||||
@@ -123,6 +123,10 @@ async function pump(iterable, writable, finish) {
|
||||
}
|
||||
let error;
|
||||
try {
|
||||
if (writable.writableNeedDrain === true) {
|
||||
await EE.once(writable, 'drain');
|
||||
}
|
||||
|
||||
for await (const chunk of iterable) {
|
||||
if (!writable.write(chunk)) {
|
||||
if (writable.destroyed) return;
|
||||
|
||||
@@ -783,7 +783,12 @@ Readable.prototype.pipe = function(dest, pipeOpts) {
|
||||
dest.emit('pipe', src);
|
||||
|
||||
// Start the flow if it hasn't been started already.
|
||||
if (!state.flowing) {
|
||||
|
||||
if (dest.writableNeedDrain === true) {
|
||||
if (state.flowing) {
|
||||
src.pause();
|
||||
}
|
||||
} else if (!state.flowing) {
|
||||
debug('pipe resume');
|
||||
src.resume();
|
||||
}
|
||||
|
||||
@@ -805,6 +805,14 @@ ObjectDefineProperties(Writable.prototype, {
|
||||
}
|
||||
},
|
||||
|
||||
writableNeedDrain: {
|
||||
get() {
|
||||
const wState = this._writableState;
|
||||
if (!wState) return false;
|
||||
return !wState.destroyed && !wState.ending && wState.needDrain;
|
||||
}
|
||||
},
|
||||
|
||||
writableHighWaterMark: {
|
||||
get() {
|
||||
return this._writableState && this._writableState.highWaterMark;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const Readable = require('_stream_readable');
|
||||
const Writable = require('_stream_writable');
|
||||
|
||||
// Pipe should not continue writing if writable needs drain.
|
||||
{
|
||||
const w = new Writable({
|
||||
write(buf, encoding, callback) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
while (w.write('asd'));
|
||||
|
||||
assert.strictEqual(w.writableNeedDrain, true);
|
||||
|
||||
const r = new Readable({
|
||||
read() {
|
||||
this.push('asd');
|
||||
}
|
||||
});
|
||||
|
||||
w.write = common.mustNotCall();
|
||||
|
||||
r.pipe(w);
|
||||
}
|
||||
Reference in new issue
Block a user