@@ -58,7 +58,7 @@ const Agent = require('_http_agent');
58
58
const { Buffer } = require ( 'buffer' ) ;
59
59
const { defaultTriggerAsyncIdScope } = require ( 'internal/async_hooks' ) ;
60
60
const { URL , urlToHttpOptions, searchParamsSymbol } = require ( 'internal/url' ) ;
61
- const { kOutHeaders, kNeedDrain } = require ( 'internal/http' ) ;
61
+ const { kOutHeaders } = require ( 'internal/http' ) ;
62
62
const { connResetException, codes } = require ( 'internal/errors' ) ;
63
63
const {
64
64
ERR_HTTP_HEADERS_SENT ,
@@ -98,7 +98,7 @@ class HTTPClientAsyncResource {
98
98
}
99
99
100
100
function ClientRequest ( input , options , cb ) {
101
- FunctionPrototypeCall ( OutgoingMessage , this ) ;
101
+ FunctionPrototypeCall ( OutgoingMessage , this , { autoDestroy : false } ) ;
102
102
103
103
if ( typeof input === 'string' ) {
104
104
const urlStr = input ;
@@ -298,7 +298,7 @@ function ClientRequest(input, options, cb) {
298
298
if ( typeof options . createConnection === 'function' ) {
299
299
const oncreate = once ( ( err , socket ) => {
300
300
if ( err ) {
301
- process . nextTick ( ( ) => this . emit ( 'error' , err ) ) ;
301
+ process . nextTick ( ( ) => emitError ( this , err ) ) ;
302
302
} else {
303
303
this . onSocket ( socket ) ;
304
304
}
@@ -366,8 +366,8 @@ function emitAbortNT(req) {
366
366
367
367
function ondrain ( ) {
368
368
const msg = this . _httpMessage ;
369
- if ( msg && ! msg . finished && msg [ kNeedDrain ] ) {
370
- msg [ kNeedDrain ] = false ;
369
+ if ( msg && ! msg . finished && msg . _writableState . needDrain ) {
370
+ msg . _writableState . needDrain = false ;
371
371
msg . emit ( 'drain' ) ;
372
372
}
373
373
}
@@ -393,8 +393,7 @@ function socketCloseListener() {
393
393
if ( ! res . complete ) {
394
394
res . destroy ( connResetException ( 'aborted' ) ) ;
395
395
}
396
- req . _closed = true ;
397
- req . emit ( 'close' ) ;
396
+ emitClose ( req ) ;
398
397
if ( ! res . aborted && res . readable ) {
399
398
res . push ( null ) ;
400
399
}
@@ -404,10 +403,9 @@ function socketCloseListener() {
404
403
// receive a response. The error needs to
405
404
// fire on the request.
406
405
req . socket . _hadError = true ;
407
- req . emit ( 'error' , connResetException ( 'socket hang up' ) ) ;
406
+ emitError ( req , connResetException ( 'socket hang up' ) ) ;
408
407
}
409
- req . _closed = true ;
410
- req . emit ( 'close' ) ;
408
+ emitClose ( req ) ;
411
409
}
412
410
413
411
// Too bad. That output wasn't getting written.
@@ -431,7 +429,7 @@ function socketErrorListener(err) {
431
429
// For Safety. Some additional errors might fire later on
432
430
// and we need to make sure we don't double-fire the error event.
433
431
req . socket . _hadError = true ;
434
- req . emit ( 'error' , err ) ;
432
+ emitError ( req , err ) ;
435
433
}
436
434
437
435
const parser = socket . parser ;
@@ -455,7 +453,7 @@ function socketOnEnd() {
455
453
// If we don't have a response then we know that the socket
456
454
// ended prematurely and we need to emit an error on the request.
457
455
req . socket . _hadError = true ;
458
- req . emit ( 'error' , connResetException ( 'socket hang up' ) ) ;
456
+ emitError ( req , connResetException ( 'socket hang up' ) ) ;
459
457
}
460
458
if ( parser ) {
461
459
parser . finish ( ) ;
@@ -478,7 +476,7 @@ function socketOnData(d) {
478
476
freeParser ( parser , req , socket ) ;
479
477
socket . destroy ( ) ;
480
478
req . socket . _hadError = true ;
481
- req . emit ( 'error' , ret ) ;
479
+ emitError ( req , ret ) ;
482
480
} else if ( parser . incoming && parser . incoming . upgrade ) {
483
481
// Upgrade (if status code 101) or CONNECT
484
482
const bytesParsed = ret ;
@@ -510,9 +508,7 @@ function socketOnData(d) {
510
508
socket . readableFlowing = null ;
511
509
512
510
req . emit ( eventName , res , socket , bodyHead ) ;
513
- req . destroyed = true ;
514
- req . _closed = true ;
515
- req . emit ( 'close' ) ;
511
+ emitClose ( req ) ;
516
512
} else {
517
513
// Requested Upgrade or used CONNECT method, but have no handler.
518
514
socket . destroy ( ) ;
@@ -697,8 +693,7 @@ function requestOnPrefinish() {
697
693
}
698
694
699
695
function emitFreeNT ( req ) {
700
- req . _closed = true ;
701
- req . emit ( 'close' ) ;
696
+ emitClose ( req ) ;
702
697
if ( req . socket ) {
703
698
req . socket . emit ( 'free' ) ;
704
699
}
@@ -779,10 +774,10 @@ function onSocketNT(req, socket, err) {
779
774
err = connResetException ( 'socket hang up' ) ;
780
775
}
781
776
if ( err ) {
782
- req . emit ( 'error' , err ) ;
777
+ emitError ( req , err ) ;
783
778
}
784
779
req . _closed = true ;
785
- req . emit ( 'close' ) ;
780
+ emitClose ( req ) ;
786
781
}
787
782
788
783
if ( socket ) {
@@ -862,6 +857,23 @@ function setSocketTimeout(sock, msecs) {
862
857
}
863
858
}
864
859
860
+ function emitError ( req , err ) {
861
+ req . destroyed = true ;
862
+ req . _writableState . errored = err ;
863
+ // Avoid V8 leak, https://github.com/nodejs/node/pull/34103#issuecomment-652002364
864
+ err . stack ; // eslint-disable-line no-unused-expressions
865
+ req . _writableState . errorEmitted = true ;
866
+ req . emit ( 'error' , err ) ;
867
+ }
868
+
869
+ function emitClose ( req ) {
870
+ req . destroyed = true ;
871
+ req . _closed = true ;
872
+ req . _writableState . closed = true ;
873
+ req . _writableState . closeEmitted = true ;
874
+ req . emit ( 'close' ) ;
875
+ }
876
+
865
877
ClientRequest . prototype . setNoDelay = function setNoDelay ( noDelay ) {
866
878
this . _deferToConnect ( 'setNoDelay' , [ noDelay ] ) ;
867
879
} ;
0 commit comments