@@ -82,6 +82,9 @@ let debug = require('internal/util/debuglog').debuglog('http', (fn) =>{
8282} ) ;
8383
8484const kCorked = Symbol ( 'corked' ) ;
85+ const kSocket = Symbol ( 'kSocket' ) ;
86+ const kChunkedBuffer = Symbol ( 'kChunkedBuffer' ) ;
87+ const kChunkedLength = Symbol ( 'kChunkedLength' ) ;
8588const kUniqueHeaders = Symbol ( 'kUniqueHeaders' ) ;
8689const kBytesWritten = Symbol ( 'kBytesWritten' ) ;
8790const kErrored = Symbol ( 'errored' ) ;
@@ -140,9 +143,11 @@ function OutgoingMessage(options){
140143this . finished = false ;
141144this . _headerSent = false ;
142145this [ kCorked ] = 0 ;
146+ this [ kChunkedBuffer ] = [ ] ;
147+ this [ kChunkedLength ] = 0 ;
143148this . _closed = false ;
144149
145- this . socket = null ;
150+ this [ kSocket ] = null ;
146151this . _header = null ;
147152this [ kOutHeaders ] = null ;
148153
@@ -177,7 +182,7 @@ ObjectDefineProperty(OutgoingMessage.prototype, 'writableFinished',{
177182return (
178183this . finished &&
179184this . outputSize === 0 &&
180- ( ! this . socket || this . socket . writableLength === 0 )
185+ ( ! this [ kSocket ] || this [ kSocket ] . writableLength === 0 )
181186) ;
182187} ,
183188} ) ;
@@ -192,22 +197,21 @@ ObjectDefineProperty(OutgoingMessage.prototype, 'writableObjectMode',{
192197ObjectDefineProperty ( OutgoingMessage . prototype , 'writableLength' , {
193198__proto__ : null ,
194199get ( ) {
195- return this . outputSize + ( this . socket ? this . socket . writableLength : 0 ) ;
200+ return this . outputSize + this [ kChunkedLength ] + ( this [ kSocket ] ? this [ kSocket ] . writableLength : 0 ) ;
196201} ,
197202} ) ;
198203
199204ObjectDefineProperty ( OutgoingMessage . prototype , 'writableHighWaterMark' , {
200205__proto__ : null ,
201206get ( ) {
202- return this . socket ? this . socket . writableHighWaterMark : this [ kHighWaterMark ] ;
207+ return this [ kSocket ] ? this [ kSocket ] . writableHighWaterMark : this [ kHighWaterMark ] ;
203208} ,
204209} ) ;
205210
206211ObjectDefineProperty ( OutgoingMessage . prototype , 'writableCorked' , {
207212__proto__ : null ,
208213get ( ) {
209- const corked = this . socket ? this . socket . writableCorked : 0 ;
210- return corked + this [ kCorked ] ;
214+ return this [ kCorked ] ;
211215} ,
212216} ) ;
213217
@@ -235,13 +239,27 @@ ObjectDefineProperty(OutgoingMessage.prototype, '_headers',{
235239ObjectDefineProperty ( OutgoingMessage . prototype , 'connection' , {
236240__proto__ : null ,
237241get : function ( ) {
238- return this . socket ;
242+ return this [ kSocket ] ;
239243} ,
240244set : function ( val ) {
241245this . socket = val ;
242246} ,
243247} ) ;
244248
249+ ObjectDefineProperty ( OutgoingMessage . prototype , 'socket' , {
250+ __proto__ : null ,
251+ get : function ( ) {
252+ return this [ kSocket ] ;
253+ } ,
254+ set : function ( val ) {
255+ for ( let n = 0 ; n < this [ kCorked ] ; n ++ ) {
256+ val ?. cork ( ) ;
257+ this [ kSocket ] ?. uncork ( ) ;
258+ }
259+ this [ kSocket ] = val ;
260+ } ,
261+ } ) ;
262+
245263ObjectDefineProperty ( OutgoingMessage . prototype , '_headerNames' , {
246264__proto__ : null ,
247265get : internalUtil . deprecate ( function ( ) {
@@ -299,19 +317,45 @@ OutgoingMessage.prototype._renderHeaders = function _renderHeaders(){
299317} ;
300318
301319OutgoingMessage . prototype . cork = function ( ) {
302- if ( this . socket ) {
303- this . socket . cork ( ) ;
304- } else {
305- this [ kCorked ] ++ ;
320+ this [ kCorked ] ++ ;
321+ if ( this [ kSocket ] ) {
322+ this [ kSocket ] . cork ( ) ;
306323}
307324} ;
308325
309326OutgoingMessage . prototype . uncork = function ( ) {
310- if ( this . socket ) {
311- this . socket . uncork ( ) ;
312- } else if ( this [ kCorked ] ) {
313- this [ kCorked ] -- ;
327+ this [ kCorked ] -- ;
328+ if ( this [ kSocket ] ) {
329+ this [ kSocket ] . uncork ( ) ;
330+ }
331+
332+ if ( this [ kCorked ] || this [ kChunkedBuffer ] . length === 0 ) {
333+ return ;
314334}
335+
336+ const len = this [ kChunkedLength ] ;
337+ const buf = this [ kChunkedBuffer ] ;
338+
339+ assert ( this . chunkedEncoding ) ;
340+
341+ let callbacks ;
342+ this . _send ( NumberPrototypeToString ( len , 16 ) , 'latin1' , null ) ;
343+ this . _send ( crlf_buf , null , null ) ;
344+ for ( let n = 0 ; n < buf . length ; n += 3 ) {
345+ this . _send ( buf [ n + 0 ] , buf [ n + 1 ] , null ) ;
346+ if ( buf [ n + 2 ] ) {
347+ callbacks ??= [ ] ;
348+ callbacks . push ( buf [ n + 2 ] ) ;
349+ }
350+ }
351+ this . _send ( crlf_buf , null , callbacks . length ? ( err ) => {
352+ for ( const callback of callbacks ) {
353+ callback ( err ) ;
354+ }
355+ } : null ) ;
356+
357+ this [ kChunkedBuffer ] . length = 0 ;
358+ this [ kChunkedLength ] = 0 ;
315359} ;
316360
317361OutgoingMessage . prototype . setTimeout = function setTimeout ( msecs , callback ) {
@@ -320,12 +364,12 @@ OutgoingMessage.prototype.setTimeout = function setTimeout(msecs, callback){
320364this . on ( 'timeout' , callback ) ;
321365}
322366
323- if ( ! this . socket ) {
367+ if ( ! this [ kSocket ] ) {
324368this . once ( 'socket' , function socketSetTimeoutOnConnect ( socket ) {
325369socket . setTimeout ( msecs ) ;
326370} ) ;
327371} else {
328- this . socket . setTimeout ( msecs ) ;
372+ this [ kSocket ] . setTimeout ( msecs ) ;
329373}
330374return this ;
331375} ;
@@ -342,8 +386,8 @@ OutgoingMessage.prototype.destroy = function destroy(error){
342386
343387this [ kErrored ] = error ;
344388
345- if ( this . socket ) {
346- this . socket . destroy ( error ) ;
389+ if ( this [ kSocket ] ) {
390+ this [ kSocket ] . destroy ( error ) ;
347391} else {
348392this . once ( 'socket' , function socketDestroyOnConnect ( socket ) {
349393socket . destroy ( error ) ;
@@ -382,7 +426,7 @@ OutgoingMessage.prototype._send = function _send(data, encoding, callback, byteL
382426
383427OutgoingMessage . prototype . _writeRaw = _writeRaw ;
384428function _writeRaw ( data , encoding , callback , size ) {
385- const conn = this . socket ;
429+ const conn = this [ kSocket ] ;
386430if ( conn && conn . destroyed ) {
387431// The socket was destroyed. If we're still trying to write to it,
388432// then we haven't gotten the 'close' event yet.
@@ -938,10 +982,16 @@ function write_(msg, chunk, encoding, callback, fromEnd){
938982let ret ;
939983if ( msg . chunkedEncoding && chunk . length !== 0 ) {
940984len ??= typeof chunk === 'string' ? Buffer . byteLength ( chunk , encoding ) : chunk . byteLength ;
941- msg . _send ( NumberPrototypeToString ( len , 16 ) , 'latin1' , null ) ;
942- msg . _send ( crlf_buf , null , null ) ;
943- msg . _send ( chunk , encoding , null , len ) ;
944- ret = msg . _send ( crlf_buf , null , callback ) ;
985+ if ( msg [ kCorked ] && msg . _headerSent ) {
986+ msg [ kChunkedBuffer ] . push ( chunk , encoding , callback ) ;
987+ msg [ kChunkedLength ] += len ;
988+ ret = msg [ kChunkedLength ] < msg [ kHighWaterMark ] ;
989+ } else {
990+ msg . _send ( NumberPrototypeToString ( len , 16 ) , 'latin1' , null ) ;
991+ msg . _send ( crlf_buf , null , null ) ;
992+ msg . _send ( chunk , encoding , null , len ) ;
993+ ret = msg . _send ( crlf_buf , null , callback ) ;
994+ }
945995} else {
946996ret = msg . _send ( chunk , encoding , callback , len ) ;
947997}
@@ -1023,8 +1073,8 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback){
10231073return this ;
10241074}
10251075
1026- if ( this . socket ) {
1027- this . socket . cork ( ) ;
1076+ if ( this [ kSocket ] ) {
1077+ this [ kSocket ] . cork ( ) ;
10281078}
10291079
10301080write_ ( this , chunk , encoding , null , true ) ;
@@ -1038,8 +1088,8 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback){
10381088}
10391089return this ;
10401090} else if ( ! this . _header ) {
1041- if ( this . socket ) {
1042- this . socket . cork ( ) ;
1091+ if ( this [ kSocket ] ) {
1092+ this [ kSocket ] . cork ( ) ;
10431093}
10441094
10451095this . _contentLength = 0 ;
@@ -1063,21 +1113,22 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback){
10631113process . nextTick ( finish ) ;
10641114}
10651115
1066- if ( this . socket ) {
1116+ if ( this [ kSocket ] ) {
10671117// Fully uncork connection on end().
1068- this . socket . _writableState . corked = 1 ;
1069- this . socket . uncork ( ) ;
1118+ this [ kSocket ] . _writableState . corked = 1 ;
1119+ this [ kSocket ] . uncork ( ) ;
10701120}
1071- this [ kCorked ] = 0 ;
1121+ this [ kCorked ] = 1 ;
1122+ this . uncork ( ) ;
10721123
10731124this . finished = true ;
10741125
10751126// There is the first message on the outgoing queue, and we've sent
10761127// everything to the socket.
10771128debug ( 'outgoing message end.' ) ;
10781129if ( this . outputData . length === 0 &&
1079- this . socket &&
1080- this . socket . _httpMessage === this ) {
1130+ this [ kSocket ] &&
1131+ this [ kSocket ] . _httpMessage === this ) {
10811132this . _finish ( ) ;
10821133}
10831134
@@ -1088,7 +1139,7 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback){
10881139// This function is called once all user data are flushed to the socket.
10891140// Note that it has a chance that the socket is not drained.
10901141OutgoingMessage . prototype . _finish = function _finish ( ) {
1091- assert ( this . socket ) ;
1142+ assert ( this [ kSocket ] ) ;
10921143this . emit ( 'prefinish' ) ;
10931144} ;
10941145
@@ -1113,7 +1164,7 @@ OutgoingMessage.prototype._finish = function _finish(){
11131164// This function, _flush(), is called by both the Server and Client
11141165// to attempt to flush any pending messages out to the socket.
11151166OutgoingMessage . prototype . _flush = function _flush ( ) {
1116- const socket = this . socket ;
1167+ const socket = this [ kSocket ] ;
11171168
11181169if ( socket && socket . writable ) {
11191170// There might be remaining data in this.output; write it out
@@ -1130,11 +1181,6 @@ OutgoingMessage.prototype._flush = function _flush(){
11301181} ;
11311182
11321183OutgoingMessage . prototype . _flushOutput = function _flushOutput ( socket ) {
1133- while ( this [ kCorked ] ) {
1134- this [ kCorked ] -- ;
1135- socket . cork ( ) ;
1136- }
1137-
11381184const outputLength = this . outputData . length ;
11391185if ( outputLength <= 0 )
11401186return undefined ;
0 commit comments