@@ -188,6 +188,7 @@ function Zlib(opts, mode) {
188
188
this . _flushFlag = opts . flush || constants . Z_NO_FLUSH ;
189
189
this . _finishFlushFlag = opts . finishFlush !== undefined ?
190
190
opts . finishFlush : constants . Z_FINISH ;
191
+ this . _scheduledFlushFlag = constants . Z_NO_FLUSH ;
191
192
192
193
if ( opts . chunkSize !== undefined ) {
193
194
if ( opts . chunkSize < constants . Z_MIN_CHUNK ) {
@@ -300,6 +301,23 @@ Zlib.prototype._flush = function _flush(callback) {
300
301
this . _transform ( Buffer . alloc ( 0 ) , '' , callback ) ;
301
302
} ;
302
303
304
+ // If a flush is scheduled while another flush is still pending, a way to figure
305
+ // out which one is the "stronger" flush is needed.
306
+ // Roughly, the following holds:
307
+ // Z_NO_FLUSH (< Z_TREES) < Z_BLOCK < Z_PARTIAL_FLUSH <
308
+ // Z_SYNC_FLUSH < Z_FULL_FLUSH < Z_FINISH
309
+ const flushiness = [ ] ;
310
+ let i = 0 ;
311
+ for ( const flushFlag of [ constants . Z_NO_FLUSH , constants . Z_BLOCK ,
312
+ constants . Z_PARTIAL_FLUSH , constants . Z_SYNC_FLUSH ,
313
+ constants . Z_FULL_FLUSH , constants . Z_FINISH ] ) {
314
+ flushiness [ flushFlag ] = i ++ ;
315
+ }
316
+
317
+ function maxFlush ( a , b ) {
318
+ return flushiness [ a ] > flushiness [ b ] ? a : b ;
319
+ }
320
+
303
321
Zlib . prototype . flush = function flush ( kind , callback ) {
304
322
var ws = this . _writableState ;
305
323
@@ -315,13 +333,21 @@ Zlib.prototype.flush = function flush(kind, callback) {
315
333
if ( callback )
316
334
this . once ( 'end' , callback ) ;
317
335
} else if ( ws . needDrain ) {
318
- if ( callback ) {
319
- const drainHandler = ( ) => this . flush ( kind , callback ) ;
336
+ const alreadyHadFlushScheduled =
337
+ this . _scheduledFlushFlag !== constants . Z_NO_FLUSH ;
338
+ this . _scheduledFlushFlag = maxFlush ( kind , this . _scheduledFlushFlag ) ;
339
+
340
+ // If a callback was passed, always register a new `drain` + flush handler,
341
+ // mostly because that’s simpler and flush callbacks piling up is a rare
342
+ // thing anyway.
343
+ if ( ! alreadyHadFlushScheduled || callback ) {
344
+ const drainHandler = ( ) => this . flush ( this . _scheduledFlushFlag , callback ) ;
320
345
this . once ( 'drain' , drainHandler ) ;
321
346
}
322
347
} else {
323
348
this . _flushFlag = kind ;
324
349
this . write ( Buffer . alloc ( 0 ) , '' , callback ) ;
350
+ this . _scheduledFlushFlag = constants . Z_NO_FLUSH ;
325
351
}
326
352
} ;
327
353
0 commit comments