@@ -56,7 +56,9 @@ const {
5656 ERR_METHOD_NOT_IMPLEMENTED ,
5757 ERR_STREAM_CANNOT_PIPE ,
5858 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
6062 } ,
6163 hideStackFrames
6264} = require ( 'internal/errors' ) ;
@@ -67,6 +69,8 @@ const { CRLF, debug } = common;
6769
6870const kCorked = Symbol ( 'corked' ) ;
6971
72+ function nop ( ) { }
73+
7074const RE_CONN_CLOSE = / (?: ^ | \W ) c l o s e (?: $ | \W ) / i;
7175const RE_TE_CHUNKED = common . chunkExpression ;
7276
@@ -633,58 +637,81 @@ ObjectDefineProperty(OutgoingMessage.prototype, 'writableEnded', {
633637
634638const crlf_buf = Buffer . from ( '\r\n' ) ;
635639OutgoingMessage . prototype . write = function write ( chunk , encoding , callback ) {
640+ if ( typeof encoding === 'function' ) {
641+ callback = encoding ;
642+ encoding = null ;
643+ }
644+
636645 const ret = write_ ( this , chunk , encoding , callback , false ) ;
637646 if ( ! ret )
638647 this [ kNeedDrain ] = true ;
639648 return ret ;
640649} ;
641650
642- function writeAfterEnd ( msg , callback ) {
643- const err = new ERR_STREAM_WRITE_AFTER_END ( ) ;
651+ function onError ( msg , err , callback ) {
644652 const triggerAsyncId = msg . socket ? msg . socket [ async_id_symbol ] : undefined ;
645653 defaultTriggerAsyncIdScope ( triggerAsyncId ,
646654 process . nextTick ,
647- writeAfterEndNT ,
655+ emitErrorNt ,
648656 msg ,
649657 err ,
650658 callback ) ;
651659}
652660
661+ function emitErrorNt ( msg , err , callback ) {
662+ callback ( err ) ;
663+ if ( typeof msg . emit === 'function' ) msg . emit ( 'error' , err ) ;
664+ }
665+
653666function 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 ;
654683 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 ;
657692 }
658693
659694 if ( ! msg . _header ) {
695+ if ( fromEnd ) {
696+ msg . _contentLength = len ;
697+ }
660698 msg . _implicitHeader ( ) ;
661699 }
662700
663701 if ( ! msg . _hasBody ) {
664702 debug ( 'This type of response MUST NOT have a body. ' +
665703 'Ignoring write() calls.' ) ;
666- if ( callback ) process . nextTick ( callback ) ;
704+ process . nextTick ( callback ) ;
667705 return true ;
668706 }
669707
670- if ( ! fromEnd && typeof chunk !== 'string' && ! ( chunk instanceof Buffer ) ) {
671- throw new ERR_INVALID_ARG_TYPE ( 'first argument' ,
672- [ 'string' , 'Buffer' ] , chunk ) ;
673- }
674-
675708 if ( ! fromEnd && msg . socket && ! msg . socket . writableCorked ) {
676709 msg . socket . cork ( ) ;
677710 process . nextTick ( connectionCorkNT , msg . socket ) ;
678711 }
679712
680713 let ret ;
681714 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-
688715 msg . _send ( len . toString ( 16 ) , 'latin1' , null ) ;
689716 msg . _send ( crlf_buf , null , null ) ;
690717 msg . _send ( chunk , encoding , null ) ;
@@ -698,12 +725,6 @@ function write_(msg, chunk, encoding, callback, fromEnd) {
698725}
699726
700727
701- function writeAfterEndNT ( msg , err , callback ) {
702- msg . emit ( 'error' , err ) ;
703- if ( callback ) callback ( err ) ;
704- }
705-
706-
707728function connectionCorkNT ( conn ) {
708729 conn . uncork ( ) ;
709730}
@@ -745,6 +766,7 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
745766 if ( typeof chunk === 'function' ) {
746767 callback = chunk ;
747768 chunk = null ;
769+ encoding = null ;
748770 } else if ( typeof encoding === 'function' ) {
749771 callback = encoding ;
750772 encoding = null ;
@@ -755,21 +777,6 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
755777 }
756778
757779 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- }
773780 write_ ( this , chunk , encoding , null , true ) ;
774781 } else if ( this . finished ) {
775782 if ( typeof callback === 'function' ) {
0 commit comments