Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions doc/api/stream.md
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,15 @@ process.nextTick(() => {

See also: [`writable.cork()`][].

##### writable.bytesWritten
<!-- YAML
added: REPLACEME
-->

* {number}

Number of bytes written through [`writable.write()`], or `null` in `objectMode`.

##### writable.writable
<!-- YAML
added: v11.4.0
Expand Down Expand Up @@ -1103,6 +1112,15 @@ added: v12.3.0

Getter for the property `objectMode` of a given `Readable` stream.

##### readable.bytesRead
<!-- YAML
added: REPLACEME
-->

* {number}

Number of bytes read, or `null` in `objectMode`.

##### readable.resume()
<!-- YAML
added: v0.9.4
Expand Down
21 changes: 20 additions & 1 deletion lib/_stream_readable.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ function ReadableState(options, stream, isDuplex) {
this.ended = false;
this.endEmitted = false;
this.reading = false;
this.bytesRead = this.objectMode ? null : 0;

// A flag to be able to tell if the event 'readable'/'data' is emitted
// immediately, or on a later tick. We set this to true at first, because
Expand Down Expand Up @@ -172,6 +173,17 @@ function Readable(options) {
Stream.call(this);
}

Object.defineProperty(Readable.prototype, 'bytesRead', {
// Making it explicit this property is not enumerable
// because otherwise some prototype manipulation in
// userland will fail
enumerable: false,
get() {
return this._readableState && this._readableState.bytesRead;
}
});


Object.defineProperty(Readable.prototype, 'destroyed', {
// Making it explicit this property is not enumerable
// because otherwise some prototype manipulation in
Expand Down Expand Up @@ -287,6 +299,9 @@ function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) {
function addChunk(stream, state, chunk, addToFront) {
if (state.flowing && state.length === 0 && !state.sync) {
state.awaitDrain = 0;
if (!state.objectMode) {
state.bytesRead += chunk.length;
}
stream.emit('data', chunk);
} else {
// Update the buffer info.
Expand Down Expand Up @@ -500,8 +515,12 @@ Readable.prototype.read = function(n) {
endReadable(this);
}

if (ret !== null)
if (ret !== null) {
if (!state.objectMode) {
state.bytesRead += ret.length;
}
this.emit('data', ret);
}

return ret;
};
Expand Down
16 changes: 16 additions & 0 deletions lib/_stream_writable.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ function WritableState(options, stream, isDuplex) {
// Has it been destroyed
this.destroyed = false;

this.bytesWritten = this.objectMode ? null : 0;

// Should we decode strings into buffers before passing to _write?
// this is here so that some node-core streams can optimize string
// handling at a lower level.
Expand Down Expand Up @@ -342,6 +344,16 @@ Object.defineProperty(Writable.prototype, 'writableBuffer', {
}
});

Object.defineProperty(Writable.prototype, 'bytesWritten', {
// Making it explicit this property is not enumerable
// because otherwise some prototype manipulation in
// userland will fail
enumerable: false,
get() {
return this._writableState && this._writableState.bytesWritten;
}
});

function decodeChunk(state, chunk, encoding) {
if (!state.objectMode &&
state.decodeStrings !== false &&
Expand Down Expand Up @@ -377,6 +389,10 @@ function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) {

state.length += len;

if (!state.objectMode) {
state.bytesWritten += len;
}

const ret = state.length < state.highWaterMark;
// We must ensure that previous needDrain will not be reset to false.
if (!ret)
Expand Down