@@ -408,15 +408,26 @@ function doWrite(stream, state, writev, len, chunk, encoding, cb) {
408408
409409function onwriteError ( stream , state , sync , er , cb ) {
410410 -- state . pendingcb ;
411- if ( sync ) processNextTick ( afterError , stream , state , cb , er ) ; else afterError ( stream , state , cb , er ) ;
412411
413- stream . _writableState . errorEmitted = true ;
414- stream . emit ( 'error' , er ) ;
415- }
416-
417- function afterError ( stream , state , cb , err ) {
418- cb ( err ) ;
419- finishMaybe ( stream , state ) ;
412+ if ( sync ) {
413+ // defer the callback if we are being called synchronously
414+ // to avoid piling up things on the stack
415+ process . nextTick ( cb , er ) ;
416+ // this can emit finish, and it will always happen
417+ // after error
418+ process . nextTick ( finishMaybe , stream , state ) ;
419+ stream . _writableState . errorEmitted = true ;
420+ stream . emit ( 'error' , er ) ;
421+ } else {
422+ // the caller expect this to happen before if
423+ // it is async
424+ cb ( er ) ;
425+ stream . _writableState . errorEmitted = true ;
426+ stream . emit ( 'error' , er ) ;
427+ // this can emit finish, but finish must
428+ // always follow error
429+ finishMaybe ( stream , state ) ;
430+ }
420431}
421432
422433function onwriteStateUpdate ( state ) {
@@ -649,4 +660,4 @@ Writable.prototype._undestroy = destroyImpl.undestroy;
649660Writable . prototype . _destroy = function ( err , cb ) {
650661 this . end ( ) ;
651662 cb ( err ) ;
652- } ;
663+ } ;
0 commit comments