@@ -612,24 +612,31 @@ function onwrite(stream, er) { |
612 | 612 | } |
613 | 613 |
|
614 | 614 | if (sync) { |
| 615 | + const needDrain = state.length === 0 && (state.state & kNeedDrain) !== 0; |
| 616 | + const needTick = needDrain || (state.state & kDestroyed !== 0) || cb !== nop; |
| 617 | + |
615 | 618 | // It is a common case that the callback passed to .write() is always |
616 | 619 | // the same. In that case, we do not schedule a new nextTick(), but |
617 | 620 | // rather just increase a counter, to improve performance and avoid |
618 | 621 | // memory allocations. |
619 | 622 | if (cb === nop) { |
620 | | - if ((state.state & kAfterWritePending) === 0) { |
| 623 | + if ((state.state & kAfterWritePending) === 0 && needTick) { |
621 | 624 | process.nextTick(afterWrite, stream, state, 1, cb); |
622 | 625 | state.state |= kAfterWritePending; |
623 | 626 | } else { |
624 | | - state.pendingcb -= 1; |
| 627 | + state.pendingcb--; |
| 628 | + finishMaybe(stream, state, true); |
625 | 629 | } |
626 | | - } else if (state.afterWriteTickInfo !== null && |
627 | | - state.afterWriteTickInfo.cb === cb) { |
628 | | - state.afterWriteTickInfo.count++; |
| 630 | + } else if ((state.state & kAfterWriteTickInfo) !== 0 && |
| 631 | + state[kAfterWriteTickInfoValue].cb === cb) { |
| 632 | + state[kAfterWriteTickInfoValue].count++; |
| 633 | + } else if (needTick) { |
| 634 | + state[kAfterWriteTickInfoValue] = { count: 1, cb, stream, state }; |
| 635 | + process.nextTick(afterWriteTick, state[kAfterWriteTickInfoValue]); |
| 636 | + state.state |= (kAfterWritePending | kAfterWriteTickInfo); |
629 | 637 | } else { |
630 | | - state.afterWriteTickInfo = { count: 1, cb, stream, state }; |
631 | | - process.nextTick(afterWriteTick, state.afterWriteTickInfo); |
632 | | - state.state |= kAfterWritePending; |
| 638 | + state.pendingcb--; |
| 639 | + finishMaybe(stream, state, true); |
633 | 640 | } |
634 | 641 | } else { |
635 | 642 | afterWrite(stream, state, 1, cb); |
@@ -638,7 +645,8 @@ function onwrite(stream, er) { |
638 | 645 | } |
639 | 646 |
|
640 | 647 | function afterWriteTick({ stream, state, count, cb }) { |
641 | | - state.afterWriteTickInfo = null; |
| 648 | + state.state &= ~kAfterWriteTickInfo; |
| 649 | + state[kAfterWriteTickInfoValue] = null; |
642 | 650 | return afterWrite(stream, state, count, cb); |
643 | 651 | } |
644 | 652 |
|
@@ -795,6 +803,8 @@ Writable.prototype.end = function(chunk, encoding, cb) { |
795 | 803 | if (typeof cb === 'function') { |
796 | 804 | if (err) { |
797 | 805 | process.nextTick(cb, err); |
| 806 | + } else if ((state.state & kErrored) !== 0) { |
| 807 | + process.nextTick(cb, state[kErroredValue]); |
798 | 808 | } else if ((state.state & kFinished) !== 0) { |
799 | 809 | process.nextTick(cb, null); |
800 | 810 | } else { |
|