@@ -205,21 +205,10 @@ function checkRangesOrGetDefault(number, name, lower, upper, def) {
205205 return number ;
206206}
207207
208- // the Zlib class they all inherit from
209- // This thing manages the queue of requests, and returns
210- // true or false if there is anything in the queue when
211- // you call the .write() method.
212- function Zlib ( opts , mode ) {
208+ // The base class for all Zlib-style streams.
209+ function ZlibBase ( opts , mode , handle , { flush, finishFlush, fullFlush } ) {
213210 var chunkSize = Z_DEFAULT_CHUNK ;
214- var flush = Z_NO_FLUSH ;
215- var finishFlush = Z_FINISH ;
216- var windowBits = Z_DEFAULT_WINDOWBITS ;
217- var level = Z_DEFAULT_COMPRESSION ;
218- var memLevel = Z_DEFAULT_MEMLEVEL ;
219- var strategy = Z_DEFAULT_STRATEGY ;
220- var dictionary ;
221-
222- // The Zlib class is not exported to user land, the mode should only be
211+ // The ZlibBase class is not exported to user land, the mode should only be
223212 // passed in by us.
224213 assert ( typeof mode === 'number' ) ;
225214 assert ( mode >= DEFLATE && mode <= UNZIP ) ;
@@ -235,50 +224,11 @@ function Zlib(opts, mode) {
235224
236225 flush = checkRangesOrGetDefault (
237226 opts . flush , 'options.flush' ,
238- Z_NO_FLUSH , Z_BLOCK , Z_NO_FLUSH ) ;
227+ Z_NO_FLUSH , Z_BLOCK , flush ) ;
239228
240229 finishFlush = checkRangesOrGetDefault (
241230 opts . finishFlush , 'options.finishFlush' ,
242- Z_NO_FLUSH , Z_BLOCK , Z_FINISH ) ;
243-
244- // windowBits is special. On the compression side, 0 is an invalid value.
245- // But on the decompression side, a value of 0 for windowBits tells zlib
246- // to use the window size in the zlib header of the compressed stream.
247- if ( ( opts . windowBits == null || opts . windowBits === 0 ) &&
248- ( mode === INFLATE ||
249- mode === GUNZIP ||
250- mode === UNZIP ) ) {
251- windowBits = 0 ;
252- } else {
253- windowBits = checkRangesOrGetDefault (
254- opts . windowBits , 'options.windowBits' ,
255- Z_MIN_WINDOWBITS , Z_MAX_WINDOWBITS , Z_DEFAULT_WINDOWBITS ) ;
256- }
257-
258- level = checkRangesOrGetDefault (
259- opts . level , 'options.level' ,
260- Z_MIN_LEVEL , Z_MAX_LEVEL , Z_DEFAULT_COMPRESSION ) ;
261-
262- memLevel = checkRangesOrGetDefault (
263- opts . memLevel , 'options.memLevel' ,
264- Z_MIN_MEMLEVEL , Z_MAX_MEMLEVEL , Z_DEFAULT_MEMLEVEL ) ;
265-
266- strategy = checkRangesOrGetDefault (
267- opts . strategy , 'options.strategy' ,
268- Z_DEFAULT_STRATEGY , Z_FIXED , Z_DEFAULT_STRATEGY ) ;
269-
270- dictionary = opts . dictionary ;
271- if ( dictionary !== undefined && ! isArrayBufferView ( dictionary ) ) {
272- if ( isAnyArrayBuffer ( dictionary ) ) {
273- dictionary = Buffer . from ( dictionary ) ;
274- } else {
275- throw new ERR_INVALID_ARG_TYPE (
276- 'options.dictionary' ,
277- [ 'Buffer' , 'TypedArray' , 'DataView' , 'ArrayBuffer' ] ,
278- dictionary
279- ) ;
280- }
281- }
231+ Z_NO_FLUSH , Z_BLOCK , finishFlush ) ;
282232
283233 if ( opts . encoding || opts . objectMode || opts . writableObjectMode ) {
284234 opts = _extend ( { } , opts ) ;
@@ -287,39 +237,29 @@ function Zlib(opts, mode) {
287237 opts . writableObjectMode = false ;
288238 }
289239 }
240+
290241 Transform . call ( this , opts ) ;
242+ this . _hadError = false ;
291243 this . bytesWritten = 0 ;
292- this . _handle = new binding . Zlib ( mode ) ;
244+ this . _handle = handle ;
245+ handle [ owner_symbol ] = this ;
293246 // Used by processCallback() and zlibOnError()
294- this . _handle [ owner_symbol ] = this ;
295- this . _handle . onerror = zlibOnError ;
296- this . _hadError = false ;
297- this . _writeState = new Uint32Array ( 2 ) ;
298-
299- if ( ! this . _handle . init ( windowBits ,
300- level ,
301- memLevel ,
302- strategy ,
303- this . _writeState ,
304- processCallback ,
305- dictionary ) ) {
306- throw new ERR_ZLIB_INITIALIZATION_FAILED ( ) ;
307- }
308-
247+ handle . onerror = zlibOnError ;
309248 this . _outBuffer = Buffer . allocUnsafe ( chunkSize ) ;
310249 this . _outOffset = 0 ;
311- this . _level = level ;
312- this . _strategy = strategy ;
250+
313251 this . _chunkSize = chunkSize ;
314252 this . _defaultFlushFlag = flush ;
315253 this . _finishFlushFlag = finishFlush ;
316254 this . _nextFlush = - 1 ;
317- this . _info = opts && opts . info ;
255+ this . _defaultFullFlushFlag = fullFlush ;
318256 this . once ( 'end' , this . close ) ;
257+ this . _info = opts && opts . info ;
319258}
320- inherits ( Zlib , Transform ) ;
321259
322- Object . defineProperty ( Zlib . prototype , '_closed' , {
260+ inherits ( ZlibBase , Transform ) ;
261+
262+ Object . defineProperty ( ZlibBase . prototype , '_closed' , {
323263 configurable : true ,
324264 enumerable : true ,
325265 get ( ) {
@@ -331,7 +271,7 @@ Object.defineProperty(Zlib.prototype, '_closed', {
331271// perspective, but it is inconsistent with all other streams exposed by Node.js
332272// that have this concept, where it stands for the number of bytes read
333273// *from* the stream (that is, net.Socket/tls.Socket & file system streams).
334- Object . defineProperty ( Zlib . prototype , 'bytesRead' , {
274+ Object . defineProperty ( ZlibBase . prototype , 'bytesRead' , {
335275 configurable : true ,
336276 enumerable : true ,
337277 get ( ) {
@@ -342,41 +282,15 @@ Object.defineProperty(Zlib.prototype, 'bytesRead', {
342282 }
343283} ) ;
344284
345- // This callback is used by `.params()` to wait until a full flush happened
346- // before adjusting the parameters. In particular, the call to the native
347- // `params()` function should not happen while a write is currently in progress
348- // on the threadpool.
349- function paramsAfterFlushCallback ( level , strategy , callback ) {
350- assert ( this . _handle , 'zlib binding closed' ) ;
351- this . _handle . params ( level , strategy ) ;
352- if ( ! this . _hadError ) {
353- this . _level = level ;
354- this . _strategy = strategy ;
355- if ( callback ) callback ( ) ;
356- }
357- }
358-
359- Zlib . prototype . params = function params ( level , strategy , callback ) {
360- checkRangesOrGetDefault ( level , 'level' , Z_MIN_LEVEL , Z_MAX_LEVEL ) ;
361- checkRangesOrGetDefault ( strategy , 'strategy' , Z_DEFAULT_STRATEGY , Z_FIXED ) ;
362-
363- if ( this . _level !== level || this . _strategy !== strategy ) {
364- this . flush ( Z_SYNC_FLUSH ,
365- paramsAfterFlushCallback . bind ( this , level , strategy , callback ) ) ;
366- } else {
367- process . nextTick ( callback ) ;
368- }
369- } ;
370-
371- Zlib . prototype . reset = function reset ( ) {
285+ ZlibBase . prototype . reset = function ( ) {
372286 if ( ! this . _handle )
373287 assert ( false , 'zlib binding closed' ) ;
374288 return this . _handle . reset ( ) ;
375289} ;
376290
377291// This is the _flush function called by the transform class,
378292// internally, when the last chunk has been written.
379- Zlib . prototype . _flush = function _flush ( callback ) {
293+ ZlibBase . prototype . _flush = function ( callback ) {
380294 this . _transform ( Buffer . alloc ( 0 ) , '' , callback ) ;
381295} ;
382296
@@ -397,12 +311,12 @@ function maxFlush(a, b) {
397311}
398312
399313const flushBuffer = Buffer . alloc ( 0 ) ;
400- Zlib . prototype . flush = function flush ( kind , callback ) {
314+ ZlibBase . prototype . flush = function ( kind , callback ) {
401315 var ws = this . _writableState ;
402316
403317 if ( typeof kind === 'function' || ( kind === undefined && ! callback ) ) {
404318 callback = kind ;
405- kind = Z_FULL_FLUSH ;
319+ kind = this . _defaultFullFlushFlag ;
406320 }
407321
408322 if ( ws . ended ) {
@@ -421,17 +335,17 @@ Zlib.prototype.flush = function flush(kind, callback) {
421335 }
422336} ;
423337
424- Zlib . prototype . close = function close ( callback ) {
338+ ZlibBase . prototype . close = function ( callback ) {
425339 _close ( this , callback ) ;
426340 this . destroy ( ) ;
427341} ;
428342
429- Zlib . prototype . _destroy = function _destroy ( err , callback ) {
343+ ZlibBase . prototype . _destroy = function ( err , callback ) {
430344 _close ( this ) ;
431345 callback ( err ) ;
432346} ;
433347
434- Zlib . prototype . _transform = function _transform ( chunk , encoding , cb ) {
348+ ZlibBase . prototype . _transform = function ( chunk , encoding , cb ) {
435349 var flushFlag = this . _defaultFlushFlag ;
436350 // We use a 'fake' zero-length chunk to carry information about flushes from
437351 // the public API to the actual stream implementation.
@@ -448,7 +362,7 @@ Zlib.prototype._transform = function _transform(chunk, encoding, cb) {
448362 processChunk ( this , chunk , flushFlag , cb ) ;
449363} ;
450364
451- Zlib . prototype . _processChunk = function _processChunk ( chunk , flushFlag , cb ) {
365+ ZlibBase . prototype . _processChunk = function ( chunk , flushFlag , cb ) {
452366 // _processChunk() is left for backwards compatibility
453367 if ( typeof cb === 'function' )
454368 processChunk ( this , chunk , flushFlag , cb ) ;
@@ -638,6 +552,109 @@ function _close(engine, callback) {
638552 engine . _handle = null ;
639553}
640554
555+ const zlibDefaultOpts = {
556+ flush : Z_NO_FLUSH ,
557+ finishFlush : Z_FINISH ,
558+ fullFlush : Z_FULL_FLUSH
559+ } ;
560+ // Base class for all streams actually backed by zlib and using zlib-specific
561+ // parameters.
562+ function Zlib ( opts , mode ) {
563+ var windowBits = Z_DEFAULT_WINDOWBITS ;
564+ var level = Z_DEFAULT_COMPRESSION ;
565+ var memLevel = Z_DEFAULT_MEMLEVEL ;
566+ var strategy = Z_DEFAULT_STRATEGY ;
567+ var dictionary ;
568+
569+ if ( opts ) {
570+ // windowBits is special. On the compression side, 0 is an invalid value.
571+ // But on the decompression side, a value of 0 for windowBits tells zlib
572+ // to use the window size in the zlib header of the compressed stream.
573+ if ( ( opts . windowBits == null || opts . windowBits === 0 ) &&
574+ ( mode === INFLATE ||
575+ mode === GUNZIP ||
576+ mode === UNZIP ) ) {
577+ windowBits = 0 ;
578+ } else {
579+ windowBits = checkRangesOrGetDefault (
580+ opts . windowBits , 'options.windowBits' ,
581+ Z_MIN_WINDOWBITS , Z_MAX_WINDOWBITS , Z_DEFAULT_WINDOWBITS ) ;
582+ }
583+
584+ level = checkRangesOrGetDefault (
585+ opts . level , 'options.level' ,
586+ Z_MIN_LEVEL , Z_MAX_LEVEL , Z_DEFAULT_COMPRESSION ) ;
587+
588+ memLevel = checkRangesOrGetDefault (
589+ opts . memLevel , 'options.memLevel' ,
590+ Z_MIN_MEMLEVEL , Z_MAX_MEMLEVEL , Z_DEFAULT_MEMLEVEL ) ;
591+
592+ strategy = checkRangesOrGetDefault (
593+ opts . strategy , 'options.strategy' ,
594+ Z_DEFAULT_STRATEGY , Z_FIXED , Z_DEFAULT_STRATEGY ) ;
595+
596+ dictionary = opts . dictionary ;
597+ if ( dictionary !== undefined && ! isArrayBufferView ( dictionary ) ) {
598+ if ( isAnyArrayBuffer ( dictionary ) ) {
599+ dictionary = Buffer . from ( dictionary ) ;
600+ } else {
601+ throw new ERR_INVALID_ARG_TYPE (
602+ 'options.dictionary' ,
603+ [ 'Buffer' , 'TypedArray' , 'DataView' , 'ArrayBuffer' ] ,
604+ dictionary
605+ ) ;
606+ }
607+ }
608+ }
609+
610+ const handle = new binding . Zlib ( mode ) ;
611+ // Ideally, we could let ZlibBase() set up _writeState. I haven't been able
612+ // to come up with a good solution that doesn't break our internal API,
613+ // and with it all supported npm versions at the time of writing.
614+ this . _writeState = new Uint32Array ( 2 ) ;
615+ if ( ! handle . init ( windowBits ,
616+ level ,
617+ memLevel ,
618+ strategy ,
619+ this . _writeState ,
620+ processCallback ,
621+ dictionary ) ) {
622+ throw new ERR_ZLIB_INITIALIZATION_FAILED ( ) ;
623+ }
624+
625+ ZlibBase . call ( this , opts , mode , handle , zlibDefaultOpts ) ;
626+
627+ this . _level = level ;
628+ this . _strategy = strategy ;
629+ }
630+ inherits ( Zlib , ZlibBase ) ;
631+
632+ // This callback is used by `.params()` to wait until a full flush happened
633+ // before adjusting the parameters. In particular, the call to the native
634+ // `params()` function should not happen while a write is currently in progress
635+ // on the threadpool.
636+ function paramsAfterFlushCallback ( level , strategy , callback ) {
637+ assert ( this . _handle , 'zlib binding closed' ) ;
638+ this . _handle . params ( level , strategy ) ;
639+ if ( ! this . _hadError ) {
640+ this . _level = level ;
641+ this . _strategy = strategy ;
642+ if ( callback ) callback ( ) ;
643+ }
644+ }
645+
646+ Zlib . prototype . params = function params ( level , strategy , callback ) {
647+ checkRangesOrGetDefault ( level , 'level' , Z_MIN_LEVEL , Z_MAX_LEVEL ) ;
648+ checkRangesOrGetDefault ( strategy , 'strategy' , Z_DEFAULT_STRATEGY , Z_FIXED ) ;
649+
650+ if ( this . _level !== level || this . _strategy !== strategy ) {
651+ this . flush ( Z_SYNC_FLUSH ,
652+ paramsAfterFlushCallback . bind ( this , level , strategy , callback ) ) ;
653+ } else {
654+ process . nextTick ( callback ) ;
655+ }
656+ } ;
657+
641658// generic zlib
642659// minimal 2-byte header
643660function Deflate ( opts ) {
0 commit comments