From 334f044afeefc2fb489433a9c970fc21f656744f Mon Sep 17 00:00:00 2001 From: Ujjwal Sharma Date: Thu, 10 May 2018 02:47:56 +0530 Subject: [PATCH] net,http2: refactor _write and _writev Refactor writable part (the _write and _writev functions) in net.Socket and http2.Http2Stream classes. Also involves adding a generic "WriteGeneric" method to the Http2Stream class based on net.Socket._writeGeneric, but behind a symbol. --- lib/internal/http2/core.js | 47 ++++++++++++-------------------------- lib/net.js | 4 ++-- 2 files changed, 17 insertions(+), 34 deletions(-) diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 0efdf9c063bf35..182090792255eb 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -146,6 +146,7 @@ const kSession = Symbol('session'); const kState = Symbol('state'); const kType = Symbol('type'); const kUpdateTimer = Symbol('update-timer'); +const kWriteGeneric = Symbol('write-generic'); const kDefaultSocketTimeout = 2 * 60 * 1000; @@ -1657,13 +1658,16 @@ class Http2Stream extends Duplex { 'bug in Node.js'); } - _write(data, encoding, cb) { + [kWriteGeneric](writev, data, encoding, cb) { // When the Http2Stream is first created, it is corked until the // handle and the stream ID is assigned. However, if the user calls // uncork() before that happens, the Duplex will attempt to pass // writes through. Those need to be queued up here. if (this.pending) { - this.once('ready', this._write.bind(this, data, encoding, cb)); + this.once( + 'ready', + this[kWriteGeneric].bind(this, writev, data, encoding, cb) + ); return; } @@ -1683,41 +1687,20 @@ class Http2Stream extends Duplex { const req = createWriteWrap(this[kHandle], afterDoStreamWrite); req.stream = this[kID]; - writeGeneric(this, req, data, encoding, cb); + if (writev) + writevGeneric(this, req, data, cb); + else + writeGeneric(this, req, data, encoding, cb); trackWriteState(this, req.bytes); } - _writev(data, cb) { - // When the Http2Stream is first created, it is corked until the - // handle and the stream ID is assigned. However, if the user calls - // uncork() before that happens, the Duplex will attempt to pass - // writes through. Those need to be queued up here. - if (this.pending) { - this.once('ready', this._writev.bind(this, data, cb)); - return; - } - - // If the stream has been destroyed, there's nothing else we can do - // because the handle has been destroyed. This should only be an - // issue if a write occurs before the 'ready' event in the case where - // the duplex is uncorked before the stream is ready to go. In that - // case, drop the data on the floor. An error should have already been - // emitted. - if (this.destroyed) - return; - - this[kUpdateTimer](); - - if (!this.headersSent) - this[kProceed](); - - var req = createWriteWrap(this[kHandle], afterDoStreamWrite); - req.stream = this[kID]; - - writevGeneric(this, req, data, cb); + _write(data, encoding, cb) { + this[kWriteGeneric](false, data, encoding, cb); + } - trackWriteState(this, req.bytes); + _writev(data, cb) { + this[kWriteGeneric](true, data, '', cb); } _final(cb) { diff --git a/lib/net.js b/lib/net.js index 5537c472fe05e3..ed4935c4fff1fa 100644 --- a/lib/net.js +++ b/lib/net.js @@ -745,13 +745,13 @@ Socket.prototype._writeGeneric = function(writev, data, encoding, cb) { this._pendingData = null; this._pendingEncoding = ''; - this._unrefTimer(); - if (!this._handle) { this.destroy(new ERR_SOCKET_CLOSED(), cb); return false; } + this._unrefTimer(); + var req = createWriteWrap(this._handle, afterWrite); if (writev) writevGeneric(this, req, data, cb);