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
6 changes: 4 additions & 2 deletions doc/api/fs.md
Original file line number Diff line number Diff line change
Expand Up @@ -892,8 +892,10 @@ Fires immediately after `'open'`.
added: v0.4.7
-->

The number of bytes written so far. Does not include data that is still queued
for writing.
{integer}

Integer value that indicates how many bytes has been written to
the response body (not the amount flushed).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we even need this here since WriteStream inherits from Writable which now documents this property? Remove?

### writeStream.path
<!-- YAML
Expand Down
10 changes: 10 additions & 0 deletions doc/api/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -1166,6 +1166,16 @@ response.end();
Attempting to set a header field name or value that contains invalid characters
will result in a [`TypeError`][] being thrown.

### response.bytesWritten
<!-- YAML
added: CHANGEME
-->

* {integer}

Integer value that indicates how many bytes has been written to
the response body (not the amount flushed).

### response.connection
<!-- YAML
added: v0.3.0
Expand Down
10 changes: 10 additions & 0 deletions doc/api/http2.md
Original file line number Diff line number Diff line change
Expand Up @@ -2977,6 +2977,16 @@ message) to the response.
Attempting to set a header field name or value that contains invalid characters
will result in a [`TypeError`][] being thrown.

#### response.bytesWritten
<!-- YAML
added: CHANGEME
-->

* {integer}

Integer value that indicates how many bytes has been written to
the response body (not the amount flushed).

#### response.connection
<!-- YAML
added: v8.4.0
Expand Down
10 changes: 10 additions & 0 deletions doc/api/stream.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,16 @@ writer.on('unpipe', (src) => {
reader.pipe(writer);
reader.unpipe(writer);
```
##### writable.bytesWritten
<!-- YAML
added: CHANGEME
-->

* {integer}

Integer value that indicates how many bytes has been written to
the stream (not the amount flushed). In `objectMode` this
value represents the number of objects written.

##### writable.cork()
<!-- YAML
Expand Down
5 changes: 5 additions & 0 deletions lib/_http_outgoing.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ function OutgoingMessage() {
// TCP socket and HTTP Parser and thus handle the backpressure.
this.outputSize = 0;

this.bytesWritten = 0;

this.writable = true;

this._last = false;
Expand Down Expand Up @@ -646,9 +648,12 @@ function write_(msg, chunk, encoding, callback, fromEnd) {
msg._send(chunk, encoding, null);
ret = msg._send(crlf_buf, null, callback);
} else {
len = chunk.length;
ret = msg._send(chunk, encoding, callback);
}

msg.bytesWritten += len;

debug('write ret = ' + ret);
return ret;
}
Expand Down
10 changes: 10 additions & 0 deletions lib/_stream_duplex.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@ Object.defineProperty(Duplex.prototype, 'writableEnded', {
}
});

Object.defineProperty(Duplex.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.written : null;
}
});

// The no-half-open enforcer
function onend() {
// If the writable side ended, then we're ok.
Expand Down
14 changes: 14 additions & 0 deletions lib/_stream_writable.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ function WritableState(options, stream, isDuplex) {
// The callback that the user supplies to write(chunk,encoding,cb)
this.writecb = null;

// The amount that has been written.
this.written = 0;

// The amount that is being written when _write is called.
this.writelen = 0;

Expand Down Expand Up @@ -373,6 +376,16 @@ Object.defineProperty(Writable.prototype, 'writableHighWaterMark', {
}
});

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: function() {
return this._writableState.written;
}
});

// If we're already writing something, then just put this
// in the queue, and wait our turn. Otherwise, call _write
// If we return false, then we need a drain event, so set that flag.
Expand All @@ -388,6 +401,7 @@ function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) {
const len = state.objectMode ? 1 : chunk.length;

state.length += len;
state.written += len;

const ret = state.length < state.highWaterMark;
// We must ensure that previous needDrain will not be reset to false.
Expand Down
3 changes: 0 additions & 3 deletions lib/internal/fs/streams.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,6 @@ function WriteStream(path, options) {
this.start = options.start;
this.autoClose = options.autoClose === undefined ? true : !!options.autoClose;
this.pos = undefined;
this.bytesWritten = 0;
this.closed = false;

if (this.start !== undefined) {
Expand Down Expand Up @@ -312,7 +311,6 @@ WriteStream.prototype._write = function(data, encoding, cb) {
}
return cb(er);
}
this.bytesWritten += bytes;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notice that WriteStream increments bytesWritten inside _write() callback and not in write(). I think this is actually wrong and slightly contradicts the previous documentation as well (and possibly expected behaviour, it surprised me).

cb();
});

Expand Down Expand Up @@ -345,7 +343,6 @@ WriteStream.prototype._writev = function(data, cb) {
self.destroy();
return cb(er);
}
self.bytesWritten += bytes;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment above.

cb();
});

Expand Down
5 changes: 5 additions & 0 deletions lib/internal/http2/compat.js
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,11 @@ class Http2ServerResponse extends Stream {
return this.headersSent;
}

get bytesWritten () {
const stream = this[kStream];
return stream.bytesWritten;
}

get writableEnded() {
const state = this[kState];
return state.ending;
Expand Down
25 changes: 25 additions & 0 deletions test/parallel/test-http-outgoing-bytes-written.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const http = require('http');

const server = http.createServer(common.mustCall(function(req, res) {
res.setHeader('test-header', 'header');
assert.strictEqual(res.bytesWritten, 0);
res.write('hello');
assert.strictEqual(res.bytesWritten, 5);
res.end('world');
assert.strictEqual(res.bytesWritten, 10);
server.close();
}));

server.listen(0);

server.on('listening', common.mustCall(function() {
const clientRequest = http.request({
port: server.address().port,
method: 'GET',
path: '/'
});
clientRequest.end();
}));
26 changes: 26 additions & 0 deletions test/parallel/test-http2-compat-serverresponse-bytes-written.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict';
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');
const assert = require('assert');
const h2 = require('http2');

const server = h2.createServer(common.mustCall(function(req, res) {
res.setHeader('test-header', 'header');
assert.strictEqual(res.bytesWritten, 0);
res.write('hello');
assert.strictEqual(res.bytesWritten, 5);
res.end('world');
assert.strictEqual(res.bytesWritten, 10);
server.close();
}));

server.listen(0);

server.on('listening', common.mustCall(function() {
const url = `http://localhost:${server.address().port}`;
const client = h2.connect(url, common.mustCall(() => {
const request = client.request();
request.end();
}));
}));
31 changes: 31 additions & 0 deletions test/parallel/test-stream-writable-bytes-written.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict';
const common = require('../common');
const { Writable } = require('stream');
const assert = require('assert');

{
const writable = new Writable({
write: (buf, enc, cb) => {
cb();
}
});
assert.strictEqual(writable.bytesWritten, 0);
writable.write('hello');
assert.strictEqual(writable.bytesWritten, 5);
writable.end('world');
assert.strictEqual(writable.bytesWritten, 10);
}

{
const writable = new Writable({
objectMode: true,
write: (buf, enc, cb) => {
cb();
}
});
assert.strictEqual(writable.bytesWritten, 0);
writable.write({});
assert.strictEqual(writable.bytesWritten, 1);
writable.end({});
assert.strictEqual(writable.bytesWritten, 2);
}