@@ -1033,6 +1033,25 @@ function write_(msg, chunk, encoding, callback, fromEnd) {
10331033}
10341034
10351035
1036+ // If this last write can be delivered immediately as the final chunk, this
1037+ // prepares to do so, and then returns true. If not, it returns false and
1038+ // a separate _send call and tick will be required to finish up.
1039+ function maybePrepareFinalChunk ( msg , chunk , encoding ) {
1040+ if ( typeof chunk !== 'string' && ! isUint8Array ( chunk ) )
1041+ return false ;
1042+
1043+ if ( msg . destroyed || msg . strictContentLength )
1044+ return false ;
1045+
1046+ if ( ! msg . _header ) {
1047+ msg . _contentLength = typeof chunk === 'string' ?
1048+ Buffer . byteLength ( chunk , encoding ) : chunk . byteLength ;
1049+ msg . _implicitHeader ( ) ;
1050+ }
1051+
1052+ return ! ! msg . _header && msg . _hasBody && ! msg . chunkedEncoding ;
1053+ }
1054+
10361055function connectionCorkNT ( conn ) {
10371056 conn . uncork ( ) ;
10381057}
@@ -1142,6 +1161,8 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
11421161 encoding = null ;
11431162 }
11441163
1164+ let finishCallback = null ;
1165+
11451166 if ( chunk ) {
11461167 if ( this . finished ) {
11471168 onError ( this ,
@@ -1154,7 +1175,18 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
11541175 this [ kSocket ] . cork ( ) ;
11551176 }
11561177
1157- write_ ( this , chunk , encoding , null , true ) ;
1178+ if ( maybePrepareFinalChunk ( this , chunk , encoding ) ) {
1179+ // If just one final write is required, with nothing to follow, we
1180+ // attach finish to the write to avoid a separate send() & tick step
1181+ // later on - this is purely a performance optimization.
1182+ if ( typeof callback === 'function' ) {
1183+ queueEndCallback ( this , callback ) ;
1184+ callback = undefined ;
1185+ }
1186+ finishCallback = onFinish . bind ( undefined , this ) ;
1187+ }
1188+
1189+ write_ ( this , chunk , encoding , finishCallback , true ) ;
11581190 } else if ( this . finished ) {
11591191 if ( typeof callback === 'function' ) {
11601192 queueEndCallback ( this , callback ) ;
@@ -1176,14 +1208,17 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
11761208 throw new ERR_HTTP_CONTENT_LENGTH_MISMATCH ( this [ kBytesWritten ] , this . _contentLength ) ;
11771209 }
11781210
1179- const finish = onFinish . bind ( undefined , this ) ;
1211+ if ( finishCallback === null ) {
1212+ // If we didn't early finish, send the last data and schedule 'finish' now:
1213+ finishCallback = onFinish . bind ( undefined , this ) ;
11801214
1181- if ( this . _hasBody && this . chunkedEncoding ) {
1182- this . _send ( '0\r\n' + this . _trailer + '\r\n' , 'latin1' , finish ) ;
1183- } else if ( ! this . _headerSent || this . writableLength || chunk ) {
1184- this . _send ( '' , 'latin1' , finish ) ;
1185- } else {
1186- process . nextTick ( finish ) ;
1215+ if ( this . _hasBody && this . chunkedEncoding ) {
1216+ this . _send ( '0\r\n' + this . _trailer + '\r\n' , 'latin1' , finishCallback ) ;
1217+ } else if ( ! this . _headerSent || this . writableLength || chunk ) {
1218+ this . _send ( '' , 'latin1' , finishCallback ) ;
1219+ } else {
1220+ process . nextTick ( finishCallback ) ;
1221+ }
11871222 }
11881223
11891224 if ( this [ kSocket ] ) {
0 commit comments