@@ -108,6 +108,7 @@ const kWriteCb = 1 << 26;
108108const kExpectWriteCb = 1 << 27 ;
109109const kAfterWriteTickInfo = 1 << 28 ;
110110const kAfterWritePending = 1 << 29 ;
111+ const kHasBuffer = 1 << 30 ;
111112
112113// TODO(benjamingr) it is likely slower to do it this way than with free functions
113114function makeBitMapDescriptor ( bit ) {
@@ -340,6 +341,7 @@ function resetBuffer(state) {
340341 state . buffered = [ ] ;
341342 state . bufferedIndex = 0 ;
342343 state . state |= kAllBuffers | kAllNoop ;
344+ state . state &= ~ kHasBuffer ;
343345}
344346
345347WritableState . prototype . getBuffer = function getBuffer ( ) {
@@ -396,11 +398,13 @@ function Writable(options) {
396398 destroyImpl . construct ( this , ( ) => {
397399 const state = this . _writableState ;
398400
399- if ( ! state . writing ) {
401+ if ( ( state . state & kWriting ) === 0 ) {
400402 clearBuffer ( this , state ) ;
401403 }
402404
403- finishMaybe ( this , state ) ;
405+ if ( ( state . state & kEnding ) !== 0 ) {
406+ finishMaybe ( this , state ) ;
407+ }
404408 } ) ;
405409}
406410
@@ -523,6 +527,7 @@ function writeOrBuffer(stream, state, chunk, encoding, callback) {
523527
524528 if ( ( state . state & ( kWriting | kErrored | kCorked | kConstructed ) ) !== kConstructed ) {
525529 state . buffered . push ( { chunk, encoding, callback } ) ;
530+ state . state |= kHasBuffer ;
526531 if ( ( state . state & kAllBuffers ) !== 0 && encoding !== 'buffer' ) {
527532 state . state &= ~ kAllBuffers ;
528533 }
@@ -591,8 +596,9 @@ function onwrite(stream, er) {
591596 // Avoid V8 leak, https://github.com/nodejs/node/pull/34103#issuecomment-652002364
592597 er . stack ; // eslint-disable-line no-unused-expressions
593598
594- if ( ! state . errored ) {
595- state . errored = er ;
599+ if ( ( state . state & kErrored ) === 0 ) {
600+ state [ kErroredValue ] = er ;
601+ state . state |= kErrored ;
596602 }
597603
598604 // In case of duplex streams we need to notify the readable side of the
@@ -607,12 +613,12 @@ function onwrite(stream, er) {
607613 onwriteError ( stream , state , er , cb ) ;
608614 }
609615 } else {
610- if ( state . buffered . length > state . bufferedIndex ) {
616+ if ( ( state . state & kHasBuffer ) !== 0 ) {
611617 clearBuffer ( stream , state ) ;
612618 }
613619
614620 if ( sync ) {
615- const needDrain = state . length === 0 && ( state . state & kNeedDrain ) ! == 0 ;
621+ const needDrain = ( state . state & kNeedDrain ) !== 0 && state . length = == 0 ;
616622 const needTick = needDrain || ( state . state & kDestroyed !== 0 ) || cb !== nop ;
617623
618624 // It is a common case that the callback passed to .write() is always
@@ -625,7 +631,9 @@ function onwrite(stream, er) {
625631 state . state |= kAfterWritePending ;
626632 } else {
627633 state . pendingcb -- ;
628- finishMaybe ( stream , state , true ) ;
634+ if ( ( state . state & kEnding ) !== 0 ) {
635+ finishMaybe ( stream , state , true ) ;
636+ }
629637 }
630638 } else if ( ( state . state & kAfterWriteTickInfo ) !== 0 &&
631639 state [ kAfterWriteTickInfoValue ] . cb === cb ) {
@@ -636,7 +644,9 @@ function onwrite(stream, er) {
636644 state . state |= ( kAfterWritePending | kAfterWriteTickInfo ) ;
637645 } else {
638646 state . pendingcb -- ;
639- finishMaybe ( stream , state , true ) ;
647+ if ( ( state . state & kEnding ) !== 0 ) {
648+ finishMaybe ( stream , state , true ) ;
649+ }
640650 }
641651 } else {
642652 afterWrite ( stream , state , 1 , cb ) ;
@@ -668,7 +678,9 @@ function afterWrite(stream, state, count, cb) {
668678 errorBuffer ( state ) ;
669679 }
670680
671- finishMaybe ( stream , state ) ;
681+ if ( ( state . state & kEnding ) !== 0 ) {
682+ finishMaybe ( stream , state , true ) ;
683+ }
672684}
673685
674686// If there's something in the buffer waiting, then invoke callbacks.
@@ -692,7 +704,7 @@ function errorBuffer(state) {
692704
693705// If there's something in the buffer waiting, then process it.
694706function clearBuffer ( stream , state ) {
695- if ( ( state . state & ( kDestroyed | kBufferProcessing | kCorked ) ) !== 0 ||
707+ if ( ( state . state & ( kDestroyed | kBufferProcessing | kCorked | kHasBuffer ) ) !== kHasBuffer ||
696708 ( state . state & kConstructed ) === 0 ) {
697709 return ;
698710 }
0 commit comments