@@ -56,7 +56,9 @@ const {
56
56
ERR_METHOD_NOT_IMPLEMENTED ,
57
57
ERR_STREAM_CANNOT_PIPE ,
58
58
ERR_STREAM_ALREADY_FINISHED ,
59
- ERR_STREAM_WRITE_AFTER_END
59
+ ERR_STREAM_WRITE_AFTER_END ,
60
+ ERR_STREAM_NULL_VALUES ,
61
+ ERR_STREAM_DESTROYED
60
62
} ,
61
63
hideStackFrames
62
64
} = require ( 'internal/errors' ) ;
@@ -67,6 +69,8 @@ const { CRLF, debug } = common;
67
69
68
70
const kCorked = Symbol ( 'corked' ) ;
69
71
72
+ function nop ( ) { }
73
+
70
74
const RE_CONN_CLOSE = / (?: ^ | \W ) c l o s e (?: $ | \W ) / i;
71
75
const RE_TE_CHUNKED = common . chunkExpression ;
72
76
@@ -633,58 +637,81 @@ ObjectDefineProperty(OutgoingMessage.prototype, 'writableEnded', {
633
637
634
638
const crlf_buf = Buffer . from ( '\r\n' ) ;
635
639
OutgoingMessage . prototype . write = function write ( chunk , encoding , callback ) {
640
+ if ( typeof encoding === 'function' ) {
641
+ callback = encoding ;
642
+ encoding = null ;
643
+ }
644
+
636
645
const ret = write_ ( this , chunk , encoding , callback , false ) ;
637
646
if ( ! ret )
638
647
this [ kNeedDrain ] = true ;
639
648
return ret ;
640
649
} ;
641
650
642
- function writeAfterEnd ( msg , callback ) {
643
- const err = new ERR_STREAM_WRITE_AFTER_END ( ) ;
651
+ function onError ( msg , err , callback ) {
644
652
const triggerAsyncId = msg . socket ? msg . socket [ async_id_symbol ] : undefined ;
645
653
defaultTriggerAsyncIdScope ( triggerAsyncId ,
646
654
process . nextTick ,
647
- writeAfterEndNT ,
655
+ emitErrorNt ,
648
656
msg ,
649
657
err ,
650
658
callback ) ;
651
659
}
652
660
661
+ function emitErrorNt ( msg , err , callback ) {
662
+ callback ( err ) ;
663
+ if ( typeof msg . emit === 'function' ) msg . emit ( 'error' , err ) ;
664
+ }
665
+
653
666
function write_ ( msg , chunk , encoding , callback , fromEnd ) {
667
+ if ( typeof callback !== 'function' )
668
+ callback = nop ;
669
+
670
+ let len ;
671
+ if ( chunk === null ) {
672
+ throw new ERR_STREAM_NULL_VALUES ( ) ;
673
+ } else if ( typeof chunk === 'string' ) {
674
+ len = Buffer . byteLength ( chunk , encoding ) ;
675
+ } else if ( chunk instanceof Buffer ) {
676
+ len = chunk . length ;
677
+ } else {
678
+ throw new ERR_INVALID_ARG_TYPE (
679
+ 'chunk' , [ 'string' , 'Buffer' , 'Uint8Array' ] , chunk ) ;
680
+ }
681
+
682
+ let err ;
654
683
if ( msg . finished ) {
655
- writeAfterEnd ( msg , callback ) ;
656
- return true ;
684
+ err = new ERR_STREAM_WRITE_AFTER_END ( ) ;
685
+ } else if ( msg . destroyed ) {
686
+ err = new ERR_STREAM_DESTROYED ( 'write' ) ;
687
+ }
688
+
689
+ if ( err ) {
690
+ onError ( msg , err , callback ) ;
691
+ return false ;
657
692
}
658
693
659
694
if ( ! msg . _header ) {
695
+ if ( fromEnd ) {
696
+ msg . _contentLength = len ;
697
+ }
660
698
msg . _implicitHeader ( ) ;
661
699
}
662
700
663
701
if ( ! msg . _hasBody ) {
664
702
debug ( 'This type of response MUST NOT have a body. ' +
665
703
'Ignoring write() calls.' ) ;
666
- if ( callback ) process . nextTick ( callback ) ;
704
+ process . nextTick ( callback ) ;
667
705
return true ;
668
706
}
669
707
670
- if ( ! fromEnd && typeof chunk !== 'string' && ! ( chunk instanceof Buffer ) ) {
671
- throw new ERR_INVALID_ARG_TYPE ( 'first argument' ,
672
- [ 'string' , 'Buffer' ] , chunk ) ;
673
- }
674
-
675
708
if ( ! fromEnd && msg . socket && ! msg . socket . writableCorked ) {
676
709
msg . socket . cork ( ) ;
677
710
process . nextTick ( connectionCorkNT , msg . socket ) ;
678
711
}
679
712
680
713
let ret ;
681
714
if ( msg . chunkedEncoding && chunk . length !== 0 ) {
682
- let len ;
683
- if ( typeof chunk === 'string' )
684
- len = Buffer . byteLength ( chunk , encoding ) ;
685
- else
686
- len = chunk . length ;
687
-
688
715
msg . _send ( len . toString ( 16 ) , 'latin1' , null ) ;
689
716
msg . _send ( crlf_buf , null , null ) ;
690
717
msg . _send ( chunk , encoding , null ) ;
@@ -698,12 +725,6 @@ function write_(msg, chunk, encoding, callback, fromEnd) {
698
725
}
699
726
700
727
701
- function writeAfterEndNT ( msg , err , callback ) {
702
- msg . emit ( 'error' , err ) ;
703
- if ( callback ) callback ( err ) ;
704
- }
705
-
706
-
707
728
function connectionCorkNT ( conn ) {
708
729
conn . uncork ( ) ;
709
730
}
@@ -745,6 +766,7 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
745
766
if ( typeof chunk === 'function' ) {
746
767
callback = chunk ;
747
768
chunk = null ;
769
+ encoding = null ;
748
770
} else if ( typeof encoding === 'function' ) {
749
771
callback = encoding ;
750
772
encoding = null ;
@@ -755,21 +777,6 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
755
777
}
756
778
757
779
if ( chunk ) {
758
- if ( typeof chunk !== 'string' && ! ( chunk instanceof Buffer ) ) {
759
- throw new ERR_INVALID_ARG_TYPE ( 'chunk' , [ 'string' , 'Buffer' ] , chunk ) ;
760
- }
761
-
762
- if ( this . finished ) {
763
- writeAfterEnd ( this , callback ) ;
764
- return this ;
765
- }
766
-
767
- if ( ! this . _header ) {
768
- if ( typeof chunk === 'string' )
769
- this . _contentLength = Buffer . byteLength ( chunk , encoding ) ;
770
- else
771
- this . _contentLength = chunk . length ;
772
- }
773
780
write_ ( this , chunk , encoding , null , true ) ;
774
781
} else if ( this . finished ) {
775
782
if ( typeof callback === 'function' ) {
0 commit comments