@@ -108,6 +108,7 @@ const kWriteCb = 1 << 26;
108108const kExpectWriteCb = 1 << 27 ;
109109const kAfterWriteTickInfo = 1 << 28 ;
110110const kAfterWritePending = 1 << 29 ;
111+ const kEmptyBuffer = 1 << 30 ;
111112
112113// TODO(benjamingr) it is likely slower to do it this way than with free functions
113114function makeBitMapDescriptor ( bit ) {
@@ -339,7 +340,7 @@ function WritableState(options, stream, isDuplex) {
339340function resetBuffer ( state ) {
340341 state . buffered = [ ] ;
341342 state . bufferedIndex = 0 ;
342- state . state |= kAllBuffers | kAllNoop ;
343+ state . state |= kAllBuffers | kAllNoop | kEmptyBuffer ;
343344}
344345
345346WritableState . prototype . getBuffer = function getBuffer ( ) {
@@ -523,6 +524,7 @@ function writeOrBuffer(stream, state, chunk, encoding, callback) {
523524
524525 if ( ( state . state & ( kWriting | kErrored | kCorked | kConstructed ) ) !== kConstructed ) {
525526 state . buffered . push ( { chunk, encoding, callback } ) ;
527+ state . state &= ~ kEmptyBuffer ;
526528 if ( ( state . state & kAllBuffers ) !== 0 && encoding !== 'buffer' ) {
527529 state . state &= ~ kAllBuffers ;
528530 }
@@ -591,8 +593,9 @@ function onwrite(stream, er) {
591593 // Avoid V8 leak, https://github.com/nodejs/node/pull/34103#issuecomment-652002364
592594 er . stack ; // eslint-disable-line no-unused-expressions
593595
594- if ( ! state . errored ) {
595- state . errored = er ;
596+ if ( ( state . state & kErrored ) === 0 ) {
597+ state [ kErroredValue ] = er ;
598+ state . state |= kErrored ;
596599 }
597600
598601 // In case of duplex streams we need to notify the readable side of the
@@ -607,12 +610,12 @@ function onwrite(stream, er) {
607610 onwriteError ( stream , state , er , cb ) ;
608611 }
609612 } else {
610- if ( state . buffered . length > state . bufferedIndex ) {
613+ if ( ( state . state & kEmptyBuffer ) === 0 ) {
611614 clearBuffer ( stream , state ) ;
612615 }
613616
614617 if ( sync ) {
615- const needDrain = state . length === 0 && ( state . state & kNeedDrain ) ! == 0 ;
618+ const needDrain = ( state . state & kNeedDrain ) !== 0 && state . length = == 0 ;
616619 const needTick = needDrain || ( state . state & kDestroyed !== 0 ) || cb !== nop ;
617620
618621 // It is a common case that the callback passed to .write() is always
@@ -625,7 +628,9 @@ function onwrite(stream, er) {
625628 state . state |= kAfterWritePending ;
626629 } else {
627630 state . pendingcb -- ;
628- finishMaybe ( stream , state , true ) ;
631+ if ( ( state . state & kEnding ) !== 0 ) {
632+ finishMaybe ( stream , state , true ) ;
633+ }
629634 }
630635 } else if ( ( state . state & kAfterWriteTickInfo ) !== 0 &&
631636 state [ kAfterWriteTickInfoValue ] . cb === cb ) {
@@ -636,7 +641,9 @@ function onwrite(stream, er) {
636641 state . state |= ( kAfterWritePending | kAfterWriteTickInfo ) ;
637642 } else {
638643 state . pendingcb -- ;
639- finishMaybe ( stream , state , true ) ;
644+ if ( ( state . state & kEnding ) !== 0 ) {
645+ finishMaybe ( stream , state , true ) ;
646+ }
640647 }
641648 } else {
642649 afterWrite ( stream , state , 1 , cb ) ;
@@ -692,7 +699,7 @@ function errorBuffer(state) {
692699
693700// If there's something in the buffer waiting, then process it.
694701function clearBuffer ( stream , state ) {
695- if ( ( state . state & ( kDestroyed | kBufferProcessing | kCorked ) ) !== 0 ||
702+ if ( ( state . state & ( kDestroyed | kBufferProcessing | kCorked | kEmptyBuffer ) ) !== 0 ||
696703 ( state . state & kConstructed ) === 0 ) {
697704 return ;
698705 }
0 commit comments