@@ -206,21 +206,10 @@ function checkRangesOrGetDefault(number, name, lower, upper, def) {
206206 return number ;
207207}
208208
209- // the Zlib class they all inherit from
210- // This thing manages the queue of requests, and returns
211- // true or false if there is anything in the queue when
212- // you call the .write() method.
213- function Zlib ( opts , mode ) {
209+ // The base class for all Zlib-style streams.
210+ function ZlibBase ( opts , mode , handle , { flush, finishFlush, fullFlush } ) {
214211 var chunkSize = Z_DEFAULT_CHUNK ;
215- var flush = Z_NO_FLUSH ;
216- var finishFlush = Z_FINISH ;
217- var windowBits = Z_DEFAULT_WINDOWBITS ;
218- var level = Z_DEFAULT_COMPRESSION ;
219- var memLevel = Z_DEFAULT_MEMLEVEL ;
220- var strategy = Z_DEFAULT_STRATEGY ;
221- var dictionary ;
222-
223- // The Zlib class is not exported to user land, the mode should only be
212+ // The ZlibBase class is not exported to user land, the mode should only be
224213 // passed in by us.
225214 assert ( typeof mode === 'number' ) ;
226215 assert ( mode >= DEFLATE && mode <= UNZIP ) ;
@@ -236,50 +225,11 @@ function Zlib(opts, mode) {
236225
237226 flush = checkRangesOrGetDefault (
238227 opts . flush , 'options.flush' ,
239- Z_NO_FLUSH , Z_BLOCK , Z_NO_FLUSH ) ;
228+ Z_NO_FLUSH , Z_BLOCK , flush ) ;
240229
241230 finishFlush = checkRangesOrGetDefault (
242231 opts . finishFlush , 'options.finishFlush' ,
243- Z_NO_FLUSH , Z_BLOCK , Z_FINISH ) ;
244-
245- // windowBits is special. On the compression side, 0 is an invalid value.
246- // But on the decompression side, a value of 0 for windowBits tells zlib
247- // to use the window size in the zlib header of the compressed stream.
248- if ( ( opts . windowBits == null || opts . windowBits === 0 ) &&
249- ( mode === INFLATE ||
250- mode === GUNZIP ||
251- mode === UNZIP ) ) {
252- windowBits = 0 ;
253- } else {
254- windowBits = checkRangesOrGetDefault (
255- opts . windowBits , 'options.windowBits' ,
256- Z_MIN_WINDOWBITS , Z_MAX_WINDOWBITS , Z_DEFAULT_WINDOWBITS ) ;
257- }
258-
259- level = checkRangesOrGetDefault (
260- opts . level , 'options.level' ,
261- Z_MIN_LEVEL , Z_MAX_LEVEL , Z_DEFAULT_COMPRESSION ) ;
262-
263- memLevel = checkRangesOrGetDefault (
264- opts . memLevel , 'options.memLevel' ,
265- Z_MIN_MEMLEVEL , Z_MAX_MEMLEVEL , Z_DEFAULT_MEMLEVEL ) ;
266-
267- strategy = checkRangesOrGetDefault (
268- opts . strategy , 'options.strategy' ,
269- Z_DEFAULT_STRATEGY , Z_FIXED , Z_DEFAULT_STRATEGY ) ;
270-
271- dictionary = opts . dictionary ;
272- if ( dictionary !== undefined && ! isArrayBufferView ( dictionary ) ) {
273- if ( isAnyArrayBuffer ( dictionary ) ) {
274- dictionary = Buffer . from ( dictionary ) ;
275- } else {
276- throw new ERR_INVALID_ARG_TYPE (
277- 'options.dictionary' ,
278- [ 'Buffer' , 'TypedArray' , 'DataView' , 'ArrayBuffer' ] ,
279- dictionary
280- ) ;
281- }
282- }
232+ Z_NO_FLUSH , Z_BLOCK , finishFlush ) ;
283233
284234 if ( opts . encoding || opts . objectMode || opts . writableObjectMode ) {
285235 opts = _extend ( { } , opts ) ;
@@ -288,39 +238,29 @@ function Zlib(opts, mode) {
288238 opts . writableObjectMode = false ;
289239 }
290240 }
241+
291242 Transform . call ( this , opts ) ;
243+ this . _hadError = false ;
292244 this . bytesWritten = 0 ;
293- this . _handle = new binding . Zlib ( mode ) ;
245+ this . _handle = handle ;
246+ handle [ owner_symbol ] = this ;
294247 // Used by processCallback() and zlibOnError()
295- this . _handle [ owner_symbol ] = this ;
296- this . _handle . onerror = zlibOnError ;
297- this . _hadError = false ;
298- this . _writeState = new Uint32Array ( 2 ) ;
299-
300- if ( ! this . _handle . init ( windowBits ,
301- level ,
302- memLevel ,
303- strategy ,
304- this . _writeState ,
305- processCallback ,
306- dictionary ) ) {
307- throw new ERR_ZLIB_INITIALIZATION_FAILED ( ) ;
308- }
309-
248+ handle . onerror = zlibOnError ;
310249 this . _outBuffer = Buffer . allocUnsafe ( chunkSize ) ;
311250 this . _outOffset = 0 ;
312- this . _level = level ;
313- this . _strategy = strategy ;
251+
314252 this . _chunkSize = chunkSize ;
315253 this . _defaultFlushFlag = flush ;
316254 this . _finishFlushFlag = finishFlush ;
317255 this . _nextFlush = - 1 ;
318- this . _info = opts && opts . info ;
256+ this . _defaultFullFlushFlag = fullFlush ;
319257 this . once ( 'end' , this . close ) ;
258+ this . _info = opts && opts . info ;
320259}
321- inherits ( Zlib , Transform ) ;
322260
323- Object . defineProperty ( Zlib . prototype , '_closed' , {
261+ inherits ( ZlibBase , Transform ) ;
262+
263+ Object . defineProperty ( ZlibBase . prototype , '_closed' , {
324264 configurable : true ,
325265 enumerable : true ,
326266 get ( ) {
@@ -332,7 +272,7 @@ Object.defineProperty(Zlib.prototype, '_closed', {
332272// perspective, but it is inconsistent with all other streams exposed by Node.js
333273// that have this concept, where it stands for the number of bytes read
334274// *from* the stream (that is, net.Socket/tls.Socket & file system streams).
335- Object . defineProperty ( Zlib . prototype , 'bytesRead' , {
275+ Object . defineProperty ( ZlibBase . prototype , 'bytesRead' , {
336276 configurable : true ,
337277 enumerable : true ,
338278 get : deprecate ( function ( ) {
@@ -345,41 +285,15 @@ Object.defineProperty(Zlib.prototype, 'bytesRead', {
345285 'This feature will be removed in the future.' , 'DEP0108' )
346286} ) ;
347287
348- // This callback is used by `.params()` to wait until a full flush happened
349- // before adjusting the parameters. In particular, the call to the native
350- // `params()` function should not happen while a write is currently in progress
351- // on the threadpool.
352- function paramsAfterFlushCallback ( level , strategy , callback ) {
353- assert ( this . _handle , 'zlib binding closed' ) ;
354- this . _handle . params ( level , strategy ) ;
355- if ( ! this . _hadError ) {
356- this . _level = level ;
357- this . _strategy = strategy ;
358- if ( callback ) callback ( ) ;
359- }
360- }
361-
362- Zlib . prototype . params = function params ( level , strategy , callback ) {
363- checkRangesOrGetDefault ( level , 'level' , Z_MIN_LEVEL , Z_MAX_LEVEL ) ;
364- checkRangesOrGetDefault ( strategy , 'strategy' , Z_DEFAULT_STRATEGY , Z_FIXED ) ;
365-
366- if ( this . _level !== level || this . _strategy !== strategy ) {
367- this . flush ( Z_SYNC_FLUSH ,
368- paramsAfterFlushCallback . bind ( this , level , strategy , callback ) ) ;
369- } else {
370- process . nextTick ( callback ) ;
371- }
372- } ;
373-
374- Zlib . prototype . reset = function reset ( ) {
288+ ZlibBase . prototype . reset = function ( ) {
375289 if ( ! this . _handle )
376290 assert ( false , 'zlib binding closed' ) ;
377291 return this . _handle . reset ( ) ;
378292} ;
379293
380294// This is the _flush function called by the transform class,
381295// internally, when the last chunk has been written.
382- Zlib . prototype . _flush = function _flush ( callback ) {
296+ ZlibBase . prototype . _flush = function ( callback ) {
383297 this . _transform ( Buffer . alloc ( 0 ) , '' , callback ) ;
384298} ;
385299
@@ -400,12 +314,12 @@ function maxFlush(a, b) {
400314}
401315
402316const flushBuffer = Buffer . alloc ( 0 ) ;
403- Zlib . prototype . flush = function flush ( kind , callback ) {
317+ ZlibBase . prototype . flush = function ( kind , callback ) {
404318 var ws = this . _writableState ;
405319
406320 if ( typeof kind === 'function' || ( kind === undefined && ! callback ) ) {
407321 callback = kind ;
408- kind = Z_FULL_FLUSH ;
322+ kind = this . _defaultFullFlushFlag ;
409323 }
410324
411325 if ( ws . ended ) {
@@ -424,17 +338,17 @@ Zlib.prototype.flush = function flush(kind, callback) {
424338 }
425339} ;
426340
427- Zlib . prototype . close = function close ( callback ) {
341+ ZlibBase . prototype . close = function ( callback ) {
428342 _close ( this , callback ) ;
429343 this . destroy ( ) ;
430344} ;
431345
432- Zlib . prototype . _destroy = function _destroy ( err , callback ) {
346+ ZlibBase . prototype . _destroy = function ( err , callback ) {
433347 _close ( this ) ;
434348 callback ( err ) ;
435349} ;
436350
437- Zlib . prototype . _transform = function _transform ( chunk , encoding , cb ) {
351+ ZlibBase . prototype . _transform = function ( chunk , encoding , cb ) {
438352 var flushFlag = this . _defaultFlushFlag ;
439353 // We use a 'fake' zero-length chunk to carry information about flushes from
440354 // the public API to the actual stream implementation.
@@ -451,7 +365,7 @@ Zlib.prototype._transform = function _transform(chunk, encoding, cb) {
451365 processChunk ( this , chunk , flushFlag , cb ) ;
452366} ;
453367
454- Zlib . prototype . _processChunk = function _processChunk ( chunk , flushFlag , cb ) {
368+ ZlibBase . prototype . _processChunk = function ( chunk , flushFlag , cb ) {
455369 // _processChunk() is left for backwards compatibility
456370 if ( typeof cb === 'function' )
457371 processChunk ( this , chunk , flushFlag , cb ) ;
@@ -641,6 +555,109 @@ function _close(engine, callback) {
641555 engine . _handle = null ;
642556}
643557
558+ const zlibDefaultOpts = {
559+ flush : Z_NO_FLUSH ,
560+ finishFlush : Z_FINISH ,
561+ fullFlush : Z_FULL_FLUSH
562+ } ;
563+ // Base class for all streams actually backed by zlib and using zlib-specific
564+ // parameters.
565+ function Zlib ( opts , mode ) {
566+ var windowBits = Z_DEFAULT_WINDOWBITS ;
567+ var level = Z_DEFAULT_COMPRESSION ;
568+ var memLevel = Z_DEFAULT_MEMLEVEL ;
569+ var strategy = Z_DEFAULT_STRATEGY ;
570+ var dictionary ;
571+
572+ if ( opts ) {
573+ // windowBits is special. On the compression side, 0 is an invalid value.
574+ // But on the decompression side, a value of 0 for windowBits tells zlib
575+ // to use the window size in the zlib header of the compressed stream.
576+ if ( ( opts . windowBits == null || opts . windowBits === 0 ) &&
577+ ( mode === INFLATE ||
578+ mode === GUNZIP ||
579+ mode === UNZIP ) ) {
580+ windowBits = 0 ;
581+ } else {
582+ windowBits = checkRangesOrGetDefault (
583+ opts . windowBits , 'options.windowBits' ,
584+ Z_MIN_WINDOWBITS , Z_MAX_WINDOWBITS , Z_DEFAULT_WINDOWBITS ) ;
585+ }
586+
587+ level = checkRangesOrGetDefault (
588+ opts . level , 'options.level' ,
589+ Z_MIN_LEVEL , Z_MAX_LEVEL , Z_DEFAULT_COMPRESSION ) ;
590+
591+ memLevel = checkRangesOrGetDefault (
592+ opts . memLevel , 'options.memLevel' ,
593+ Z_MIN_MEMLEVEL , Z_MAX_MEMLEVEL , Z_DEFAULT_MEMLEVEL ) ;
594+
595+ strategy = checkRangesOrGetDefault (
596+ opts . strategy , 'options.strategy' ,
597+ Z_DEFAULT_STRATEGY , Z_FIXED , Z_DEFAULT_STRATEGY ) ;
598+
599+ dictionary = opts . dictionary ;
600+ if ( dictionary !== undefined && ! isArrayBufferView ( dictionary ) ) {
601+ if ( isAnyArrayBuffer ( dictionary ) ) {
602+ dictionary = Buffer . from ( dictionary ) ;
603+ } else {
604+ throw new ERR_INVALID_ARG_TYPE (
605+ 'options.dictionary' ,
606+ [ 'Buffer' , 'TypedArray' , 'DataView' , 'ArrayBuffer' ] ,
607+ dictionary
608+ ) ;
609+ }
610+ }
611+ }
612+
613+ const handle = new binding . Zlib ( mode ) ;
614+ // Ideally, we could let ZlibBase() set up _writeState. I haven't been able
615+ // to come up with a good solution that doesn't break our internal API,
616+ // and with it all supported npm versions at the time of writing.
617+ this . _writeState = new Uint32Array ( 2 ) ;
618+ if ( ! handle . init ( windowBits ,
619+ level ,
620+ memLevel ,
621+ strategy ,
622+ this . _writeState ,
623+ processCallback ,
624+ dictionary ) ) {
625+ throw new ERR_ZLIB_INITIALIZATION_FAILED ( ) ;
626+ }
627+
628+ ZlibBase . call ( this , opts , mode , handle , zlibDefaultOpts ) ;
629+
630+ this . _level = level ;
631+ this . _strategy = strategy ;
632+ }
633+ inherits ( Zlib , ZlibBase ) ;
634+
635+ // This callback is used by `.params()` to wait until a full flush happened
636+ // before adjusting the parameters. In particular, the call to the native
637+ // `params()` function should not happen while a write is currently in progress
638+ // on the threadpool.
639+ function paramsAfterFlushCallback ( level , strategy , callback ) {
640+ assert ( this . _handle , 'zlib binding closed' ) ;
641+ this . _handle . params ( level , strategy ) ;
642+ if ( ! this . _hadError ) {
643+ this . _level = level ;
644+ this . _strategy = strategy ;
645+ if ( callback ) callback ( ) ;
646+ }
647+ }
648+
649+ Zlib . prototype . params = function params ( level , strategy , callback ) {
650+ checkRangesOrGetDefault ( level , 'level' , Z_MIN_LEVEL , Z_MAX_LEVEL ) ;
651+ checkRangesOrGetDefault ( strategy , 'strategy' , Z_DEFAULT_STRATEGY , Z_FIXED ) ;
652+
653+ if ( this . _level !== level || this . _strategy !== strategy ) {
654+ this . flush ( Z_SYNC_FLUSH ,
655+ paramsAfterFlushCallback . bind ( this , level , strategy , callback ) ) ;
656+ } else {
657+ process . nextTick ( callback ) ;
658+ }
659+ } ;
660+
644661// generic zlib
645662// minimal 2-byte header
646663function Deflate ( opts ) {
0 commit comments