@@ -108,6 +108,7 @@ const kWriteCb = 1 << 26;
108
108
const kExpectWriteCb = 1 << 27 ;
109
109
const kAfterWriteTickInfo = 1 << 28 ;
110
110
const kAfterWritePending = 1 << 29 ;
111
+ const kEmptyBuffer = 1 << 30 ;
111
112
112
113
// TODO(benjamingr) it is likely slower to do it this way than with free functions
113
114
function makeBitMapDescriptor ( bit ) {
@@ -339,7 +340,7 @@ function WritableState(options, stream, isDuplex) {
339
340
function resetBuffer ( state ) {
340
341
state . buffered = [ ] ;
341
342
state . bufferedIndex = 0 ;
342
- state . state |= kAllBuffers | kAllNoop ;
343
+ state . state |= kAllBuffers | kAllNoop | kEmptyBuffer ;
343
344
}
344
345
345
346
WritableState . prototype . getBuffer = function getBuffer ( ) {
@@ -523,6 +524,7 @@ function writeOrBuffer(stream, state, chunk, encoding, callback) {
523
524
524
525
if ( ( state . state & ( kWriting | kErrored | kCorked | kConstructed ) ) !== kConstructed ) {
525
526
state . buffered . push ( { chunk, encoding, callback } ) ;
527
+ state . state &= ~ kEmptyBuffer ;
526
528
if ( ( state . state & kAllBuffers ) !== 0 && encoding !== 'buffer' ) {
527
529
state . state &= ~ kAllBuffers ;
528
530
}
@@ -591,8 +593,9 @@ function onwrite(stream, er) {
591
593
// Avoid V8 leak, https://github.com/nodejs/node/pull/34103#issuecomment-652002364
592
594
er . stack ; // eslint-disable-line no-unused-expressions
593
595
594
- if ( ! state . errored ) {
595
- state . errored = er ;
596
+ if ( ( state . state & kErrored ) === 0 ) {
597
+ state [ kErroredValue ] = er ;
598
+ state . state |= kErrored ;
596
599
}
597
600
598
601
// In case of duplex streams we need to notify the readable side of the
@@ -607,12 +610,12 @@ function onwrite(stream, er) {
607
610
onwriteError ( stream , state , er , cb ) ;
608
611
}
609
612
} else {
610
- if ( state . buffered . length > state . bufferedIndex ) {
613
+ if ( ( state . state & kEmptyBuffer ) === 0 ) {
611
614
clearBuffer ( stream , state ) ;
612
615
}
613
616
614
617
if ( sync ) {
615
- const needDrain = state . length === 0 && ( state . state & kNeedDrain ) ! == 0 ;
618
+ const needDrain = ( state . state & kNeedDrain ) !== 0 && state . length = == 0 ;
616
619
const needTick = needDrain || ( state . state & kDestroyed !== 0 ) || cb !== nop ;
617
620
618
621
// It is a common case that the callback passed to .write() is always
@@ -625,7 +628,9 @@ function onwrite(stream, er) {
625
628
state . state |= kAfterWritePending ;
626
629
} else {
627
630
state . pendingcb -- ;
628
- finishMaybe ( stream , state , true ) ;
631
+ if ( ( state . state & kEnding ) !== 0 ) {
632
+ finishMaybe ( stream , state , true ) ;
633
+ }
629
634
}
630
635
} else if ( ( state . state & kAfterWriteTickInfo ) !== 0 &&
631
636
state [ kAfterWriteTickInfoValue ] . cb === cb ) {
@@ -636,7 +641,9 @@ function onwrite(stream, er) {
636
641
state . state |= ( kAfterWritePending | kAfterWriteTickInfo ) ;
637
642
} else {
638
643
state . pendingcb -- ;
639
- finishMaybe ( stream , state , true ) ;
644
+ if ( ( state . state & kEnding ) !== 0 ) {
645
+ finishMaybe ( stream , state , true ) ;
646
+ }
640
647
}
641
648
} else {
642
649
afterWrite ( stream , state , 1 , cb ) ;
@@ -668,7 +675,9 @@ function afterWrite(stream, state, count, cb) {
668
675
errorBuffer ( state ) ;
669
676
}
670
677
671
- finishMaybe ( stream , state ) ;
678
+ if ( ( state . state & kEnding ) !== 0 ) {
679
+ finishMaybe ( stream , state , true ) ;
680
+ }
672
681
}
673
682
674
683
// If there's something in the buffer waiting, then invoke callbacks.
@@ -692,7 +701,7 @@ function errorBuffer(state) {
692
701
693
702
// If there's something in the buffer waiting, then process it.
694
703
function clearBuffer ( stream , state ) {
695
- if ( ( state . state & ( kDestroyed | kBufferProcessing | kCorked ) ) !== 0 ||
704
+ if ( ( state . state & ( kDestroyed | kBufferProcessing | kCorked | kEmptyBuffer ) ) !== 0 ||
696
705
( state . state & kConstructed ) === 0 ) {
697
706
return ;
698
707
}
0 commit comments