mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 00:20:08 +01: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:
parent
da53a3caa3
commit
dd0f8f18c2
|
|
@ -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;
|
||||
|
|
|
|||
29
test/parallel/test-stream-pipe-needDrain.js
Normal file
29
test/parallel/test-stream-pipe-needDrain.js
Normal file
|
|
@ -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);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user