@@ -82,6 +82,9 @@ let debug = require('internal/util/debuglog').debuglog('http', (fn) => {
82
82
} ) ;
83
83
84
84
const kCorked = Symbol ( 'corked' ) ;
85
+ const kSocket = Symbol ( 'kSocket' ) ;
86
+ const kChunkedBuffer = Symbol ( 'kChunkedBuffer' ) ;
87
+ const kChunkedLength = Symbol ( 'kChunkedLength' ) ;
85
88
const kUniqueHeaders = Symbol ( 'kUniqueHeaders' ) ;
86
89
const kBytesWritten = Symbol ( 'kBytesWritten' ) ;
87
90
const kErrored = Symbol ( 'errored' ) ;
@@ -140,9 +143,11 @@ function OutgoingMessage(options) {
140
143
this . finished = false ;
141
144
this . _headerSent = false ;
142
145
this [ kCorked ] = 0 ;
146
+ this [ kChunkedBuffer ] = [ ] ;
147
+ this [ kChunkedLength ] = 0 ;
143
148
this . _closed = false ;
144
149
145
- this . socket = null ;
150
+ this [ kSocket ] = null ;
146
151
this . _header = null ;
147
152
this [ kOutHeaders ] = null ;
148
153
@@ -177,7 +182,7 @@ ObjectDefineProperty(OutgoingMessage.prototype, 'writableFinished', {
177
182
return (
178
183
this . finished &&
179
184
this . outputSize === 0 &&
180
- ( ! this . socket || this . socket . writableLength === 0 )
185
+ ( ! this [ kSocket ] || this [ kSocket ] . writableLength === 0 )
181
186
) ;
182
187
} ,
183
188
} ) ;
@@ -192,22 +197,21 @@ ObjectDefineProperty(OutgoingMessage.prototype, 'writableObjectMode', {
192
197
ObjectDefineProperty ( OutgoingMessage . prototype , 'writableLength' , {
193
198
__proto__ : null ,
194
199
get ( ) {
195
- return this . outputSize + ( this . socket ? this . socket . writableLength : 0 ) ;
200
+ return this . outputSize + this [ kChunkedLength ] + ( this [ kSocket ] ? this [ kSocket ] . writableLength : 0 ) ;
196
201
} ,
197
202
} ) ;
198
203
199
204
ObjectDefineProperty ( OutgoingMessage . prototype , 'writableHighWaterMark' , {
200
205
__proto__ : null ,
201
206
get ( ) {
202
- return this . socket ? this . socket . writableHighWaterMark : this [ kHighWaterMark ] ;
207
+ return this [ kSocket ] ? this [ kSocket ] . writableHighWaterMark : this [ kHighWaterMark ] ;
203
208
} ,
204
209
} ) ;
205
210
206
211
ObjectDefineProperty ( OutgoingMessage . prototype , 'writableCorked' , {
207
212
__proto__ : null ,
208
213
get ( ) {
209
- const corked = this . socket ? this . socket . writableCorked : 0 ;
210
- return corked + this [ kCorked ] ;
214
+ return this [ kCorked ] ;
211
215
} ,
212
216
} ) ;
213
217
@@ -235,13 +239,27 @@ ObjectDefineProperty(OutgoingMessage.prototype, '_headers', {
235
239
ObjectDefineProperty ( OutgoingMessage . prototype , 'connection' , {
236
240
__proto__ : null ,
237
241
get : function ( ) {
238
- return this . socket ;
242
+ return this [ kSocket ] ;
239
243
} ,
240
244
set : function ( val ) {
241
245
this . socket = val ;
242
246
} ,
243
247
} ) ;
244
248
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
+
245
263
ObjectDefineProperty ( OutgoingMessage . prototype , '_headerNames' , {
246
264
__proto__ : null ,
247
265
get : internalUtil . deprecate ( function ( ) {
@@ -299,19 +317,45 @@ OutgoingMessage.prototype._renderHeaders = function _renderHeaders() {
299
317
} ;
300
318
301
319
OutgoingMessage . 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 ( ) ;
306
323
}
307
324
} ;
308
325
309
326
OutgoingMessage . 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 ;
314
334
}
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 ;
315
359
} ;
316
360
317
361
OutgoingMessage . prototype . setTimeout = function setTimeout ( msecs , callback ) {
@@ -320,12 +364,12 @@ OutgoingMessage.prototype.setTimeout = function setTimeout(msecs, callback) {
320
364
this . on ( 'timeout' , callback ) ;
321
365
}
322
366
323
- if ( ! this . socket ) {
367
+ if ( ! this [ kSocket ] ) {
324
368
this . once ( 'socket' , function socketSetTimeoutOnConnect ( socket ) {
325
369
socket . setTimeout ( msecs ) ;
326
370
} ) ;
327
371
} else {
328
- this . socket . setTimeout ( msecs ) ;
372
+ this [ kSocket ] . setTimeout ( msecs ) ;
329
373
}
330
374
return this ;
331
375
} ;
@@ -342,8 +386,8 @@ OutgoingMessage.prototype.destroy = function destroy(error) {
342
386
343
387
this [ kErrored ] = error ;
344
388
345
- if ( this . socket ) {
346
- this . socket . destroy ( error ) ;
389
+ if ( this [ kSocket ] ) {
390
+ this [ kSocket ] . destroy ( error ) ;
347
391
} else {
348
392
this . once ( 'socket' , function socketDestroyOnConnect ( socket ) {
349
393
socket . destroy ( error ) ;
@@ -382,7 +426,7 @@ OutgoingMessage.prototype._send = function _send(data, encoding, callback, byteL
382
426
383
427
OutgoingMessage . prototype . _writeRaw = _writeRaw ;
384
428
function _writeRaw ( data , encoding , callback , size ) {
385
- const conn = this . socket ;
429
+ const conn = this [ kSocket ] ;
386
430
if ( conn && conn . destroyed ) {
387
431
// The socket was destroyed. If we're still trying to write to it,
388
432
// then we haven't gotten the 'close' event yet.
@@ -938,10 +982,16 @@ function write_(msg, chunk, encoding, callback, fromEnd) {
938
982
let ret ;
939
983
if ( msg . chunkedEncoding && chunk . length !== 0 ) {
940
984
len ??= 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
+ }
945
995
} else {
946
996
ret = msg . _send ( chunk , encoding , callback , len ) ;
947
997
}
@@ -1023,8 +1073,8 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
1023
1073
return this ;
1024
1074
}
1025
1075
1026
- if ( this . socket ) {
1027
- this . socket . cork ( ) ;
1076
+ if ( this [ kSocket ] ) {
1077
+ this [ kSocket ] . cork ( ) ;
1028
1078
}
1029
1079
1030
1080
write_ ( this , chunk , encoding , null , true ) ;
@@ -1038,8 +1088,8 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
1038
1088
}
1039
1089
return this ;
1040
1090
} else if ( ! this . _header ) {
1041
- if ( this . socket ) {
1042
- this . socket . cork ( ) ;
1091
+ if ( this [ kSocket ] ) {
1092
+ this [ kSocket ] . cork ( ) ;
1043
1093
}
1044
1094
1045
1095
this . _contentLength = 0 ;
@@ -1063,21 +1113,22 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
1063
1113
process . nextTick ( finish ) ;
1064
1114
}
1065
1115
1066
- if ( this . socket ) {
1116
+ if ( this [ kSocket ] ) {
1067
1117
// 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 ( ) ;
1070
1120
}
1071
- this [ kCorked ] = 0 ;
1121
+ this [ kCorked ] = 1 ;
1122
+ this . uncork ( ) ;
1072
1123
1073
1124
this . finished = true ;
1074
1125
1075
1126
// There is the first message on the outgoing queue, and we've sent
1076
1127
// everything to the socket.
1077
1128
debug ( 'outgoing message end.' ) ;
1078
1129
if ( this . outputData . length === 0 &&
1079
- this . socket &&
1080
- this . socket . _httpMessage === this ) {
1130
+ this [ kSocket ] &&
1131
+ this [ kSocket ] . _httpMessage === this ) {
1081
1132
this . _finish ( ) ;
1082
1133
}
1083
1134
@@ -1088,7 +1139,7 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
1088
1139
// This function is called once all user data are flushed to the socket.
1089
1140
// Note that it has a chance that the socket is not drained.
1090
1141
OutgoingMessage . prototype . _finish = function _finish ( ) {
1091
- assert ( this . socket ) ;
1142
+ assert ( this [ kSocket ] ) ;
1092
1143
this . emit ( 'prefinish' ) ;
1093
1144
} ;
1094
1145
@@ -1113,7 +1164,7 @@ OutgoingMessage.prototype._finish = function _finish() {
1113
1164
// This function, _flush(), is called by both the Server and Client
1114
1165
// to attempt to flush any pending messages out to the socket.
1115
1166
OutgoingMessage . prototype . _flush = function _flush ( ) {
1116
- const socket = this . socket ;
1167
+ const socket = this [ kSocket ] ;
1117
1168
1118
1169
if ( socket && socket . writable ) {
1119
1170
// There might be remaining data in this.output; write it out
@@ -1130,11 +1181,6 @@ OutgoingMessage.prototype._flush = function _flush() {
1130
1181
} ;
1131
1182
1132
1183
OutgoingMessage . prototype . _flushOutput = function _flushOutput ( socket ) {
1133
- while ( this [ kCorked ] ) {
1134
- this [ kCorked ] -- ;
1135
- socket . cork ( ) ;
1136
- }
1137
-
1138
1184
const outputLength = this . outputData . length ;
1139
1185
if ( outputLength <= 0 )
1140
1186
return undefined ;
0 commit comments