@@ -207,21 +207,10 @@ function checkRangesOrGetDefault(number, name, lower, upper, def) {
207207 return number ;
208208}
209209
210- // the Zlib class they all inherit from
211- // This thing manages the queue of requests, and returns
212- // true or false if there is anything in the queue when
213- // you call the .write() method.
214- function Zlib ( opts , mode ) {
210+ // The base class for all Zlib-style streams.
211+ function ZlibBase ( opts , mode , handle , { flush, finishFlush, fullFlush } ) {
215212 var chunkSize = Z_DEFAULT_CHUNK ;
216- var flush = Z_NO_FLUSH ;
217- var finishFlush = Z_FINISH ;
218- var windowBits = Z_DEFAULT_WINDOWBITS ;
219- var level = Z_DEFAULT_COMPRESSION ;
220- var memLevel = Z_DEFAULT_MEMLEVEL ;
221- var strategy = Z_DEFAULT_STRATEGY ;
222- var dictionary ;
223-
224- // The Zlib class is not exported to user land, the mode should only be
213+ // The ZlibBase class is not exported to user land, the mode should only be
225214 // passed in by us.
226215 assert ( typeof mode === 'number' ) ;
227216 assert ( mode >= DEFLATE && mode <= UNZIP ) ;
@@ -237,50 +226,11 @@ function Zlib(opts, mode) {
237226
238227 flush = checkRangesOrGetDefault (
239228 opts . flush , 'options.flush' ,
240- Z_NO_FLUSH , Z_BLOCK , Z_NO_FLUSH ) ;
229+ Z_NO_FLUSH , Z_BLOCK , flush ) ;
241230
242231 finishFlush = checkRangesOrGetDefault (
243232 opts . finishFlush , 'options.finishFlush' ,
244- Z_NO_FLUSH , Z_BLOCK , Z_FINISH ) ;
245-
246- // windowBits is special. On the compression side, 0 is an invalid value.
247- // But on the decompression side, a value of 0 for windowBits tells zlib
248- // to use the window size in the zlib header of the compressed stream.
249- if ( ( opts . windowBits == null || opts . windowBits === 0 ) &&
250- ( mode === INFLATE ||
251- mode === GUNZIP ||
252- mode === UNZIP ) ) {
253- windowBits = 0 ;
254- } else {
255- windowBits = checkRangesOrGetDefault (
256- opts . windowBits , 'options.windowBits' ,
257- Z_MIN_WINDOWBITS , Z_MAX_WINDOWBITS , Z_DEFAULT_WINDOWBITS ) ;
258- }
259-
260- level = checkRangesOrGetDefault (
261- opts . level , 'options.level' ,
262- Z_MIN_LEVEL , Z_MAX_LEVEL , Z_DEFAULT_COMPRESSION ) ;
263-
264- memLevel = checkRangesOrGetDefault (
265- opts . memLevel , 'options.memLevel' ,
266- Z_MIN_MEMLEVEL , Z_MAX_MEMLEVEL , Z_DEFAULT_MEMLEVEL ) ;
267-
268- strategy = checkRangesOrGetDefault (
269- opts . strategy , 'options.strategy' ,
270- Z_DEFAULT_STRATEGY , Z_FIXED , Z_DEFAULT_STRATEGY ) ;
271-
272- dictionary = opts . dictionary ;
273- if ( dictionary !== undefined && ! isArrayBufferView ( dictionary ) ) {
274- if ( isAnyArrayBuffer ( dictionary ) ) {
275- dictionary = Buffer . from ( dictionary ) ;
276- } else {
277- throw new ERR_INVALID_ARG_TYPE (
278- 'options.dictionary' ,
279- [ 'Buffer' , 'TypedArray' , 'DataView' , 'ArrayBuffer' ] ,
280- dictionary
281- ) ;
282- }
283- }
233+ Z_NO_FLUSH , Z_BLOCK , finishFlush ) ;
284234
285235 if ( opts . encoding || opts . objectMode || opts . writableObjectMode ) {
286236 opts = _extend ( { } , opts ) ;
@@ -289,40 +239,29 @@ function Zlib(opts, mode) {
289239 opts . writableObjectMode = false ;
290240 }
291241 }
242+
292243 Transform . call ( this , opts ) ;
244+ this . _hadError = false ;
293245 this . bytesWritten = 0 ;
294- this . _handle = new binding . Zlib ( mode ) ;
246+ this . _handle = handle ;
247+ handle [ owner_symbol ] = this ;
295248 // Used by processCallback() and zlibOnError()
296- this . _handle [ owner_symbol ] = this ;
297- this . _handle . onerror = zlibOnError ;
298- this . _hadError = false ;
299- this . _writeState = new Uint32Array ( 2 ) ;
300-
301- if ( ! this . _handle . init ( windowBits ,
302- level ,
303- memLevel ,
304- strategy ,
305- this . _writeState ,
306- processCallback ,
307- dictionary ) ) {
308- throw new ERR_ZLIB_INITIALIZATION_FAILED ( ) ;
309- }
310-
249+ handle . onerror = zlibOnError ;
311250 this . _outBuffer = Buffer . allocUnsafe ( chunkSize ) ;
312251 this . _outOffset = 0 ;
313- this . _level = level ;
314- this . _strategy = strategy ;
252+
315253 this . _chunkSize = chunkSize ;
316254 this . _defaultFlushFlag = flush ;
317255 this . _finishFlushFlag = finishFlush ;
318256 this . _nextFlush = - 1 ;
319- this . _info = opts && opts . info ;
257+ this . _defaultFullFlushFlag = fullFlush ;
320258 this . once ( 'end' , this . close ) ;
259+ this . _info = opts && opts . info ;
321260}
322- Object . setPrototypeOf ( Zlib . prototype , Transform . prototype ) ;
323- Object . setPrototypeOf ( Zlib , Transform ) ;
261+ Object . setPrototypeOf ( ZlibBase . prototype , Transform . prototype ) ;
262+ Object . setPrototypeOf ( ZlibBase , Transform ) ;
324263
325- Object . defineProperty ( Zlib . prototype , '_closed' , {
264+ Object . defineProperty ( ZlibBase . prototype , '_closed' , {
326265 configurable : true ,
327266 enumerable : true ,
328267 get ( ) {
@@ -334,7 +273,7 @@ Object.defineProperty(Zlib.prototype, '_closed', {
334273// perspective, but it is inconsistent with all other streams exposed by Node.js
335274// that have this concept, where it stands for the number of bytes read
336275// *from* the stream (that is, net.Socket/tls.Socket & file system streams).
337- Object . defineProperty ( Zlib . prototype , 'bytesRead' , {
276+ Object . defineProperty ( ZlibBase . prototype , 'bytesRead' , {
338277 configurable : true ,
339278 enumerable : true ,
340279 get : deprecate ( function ( ) {
@@ -347,41 +286,15 @@ Object.defineProperty(Zlib.prototype, 'bytesRead', {
347286 'This feature will be removed in the future.' , 'DEP0108' )
348287} ) ;
349288
350- // This callback is used by `.params()` to wait until a full flush happened
351- // before adjusting the parameters. In particular, the call to the native
352- // `params()` function should not happen while a write is currently in progress
353- // on the threadpool.
354- function paramsAfterFlushCallback ( level , strategy , callback ) {
355- assert ( this . _handle , 'zlib binding closed' ) ;
356- this . _handle . params ( level , strategy ) ;
357- if ( ! this . _hadError ) {
358- this . _level = level ;
359- this . _strategy = strategy ;
360- if ( callback ) callback ( ) ;
361- }
362- }
363-
364- Zlib . prototype . params = function params ( level , strategy , callback ) {
365- checkRangesOrGetDefault ( level , 'level' , Z_MIN_LEVEL , Z_MAX_LEVEL ) ;
366- checkRangesOrGetDefault ( strategy , 'strategy' , Z_DEFAULT_STRATEGY , Z_FIXED ) ;
367-
368- if ( this . _level !== level || this . _strategy !== strategy ) {
369- this . flush ( Z_SYNC_FLUSH ,
370- paramsAfterFlushCallback . bind ( this , level , strategy , callback ) ) ;
371- } else {
372- process . nextTick ( callback ) ;
373- }
374- } ;
375-
376- Zlib . prototype . reset = function reset ( ) {
289+ ZlibBase . prototype . reset = function ( ) {
377290 if ( ! this . _handle )
378291 assert ( false , 'zlib binding closed' ) ;
379292 return this . _handle . reset ( ) ;
380293} ;
381294
382295// This is the _flush function called by the transform class,
383296// internally, when the last chunk has been written.
384- Zlib . prototype . _flush = function _flush ( callback ) {
297+ ZlibBase . prototype . _flush = function ( callback ) {
385298 this . _transform ( Buffer . alloc ( 0 ) , '' , callback ) ;
386299} ;
387300
@@ -402,12 +315,12 @@ function maxFlush(a, b) {
402315}
403316
404317const flushBuffer = Buffer . alloc ( 0 ) ;
405- Zlib . prototype . flush = function flush ( kind , callback ) {
318+ ZlibBase . prototype . flush = function ( kind , callback ) {
406319 var ws = this . _writableState ;
407320
408321 if ( typeof kind === 'function' || ( kind === undefined && ! callback ) ) {
409322 callback = kind ;
410- kind = Z_FULL_FLUSH ;
323+ kind = this . _defaultFullFlushFlag ;
411324 }
412325
413326 if ( ws . ended ) {
@@ -426,17 +339,17 @@ Zlib.prototype.flush = function flush(kind, callback) {
426339 }
427340} ;
428341
429- Zlib . prototype . close = function close ( callback ) {
342+ ZlibBase . prototype . close = function ( callback ) {
430343 _close ( this , callback ) ;
431344 this . destroy ( ) ;
432345} ;
433346
434- Zlib . prototype . _destroy = function _destroy ( err , callback ) {
347+ ZlibBase . prototype . _destroy = function ( err , callback ) {
435348 _close ( this ) ;
436349 callback ( err ) ;
437350} ;
438351
439- Zlib . prototype . _transform = function _transform ( chunk , encoding , cb ) {
352+ ZlibBase . prototype . _transform = function ( chunk , encoding , cb ) {
440353 var flushFlag = this . _defaultFlushFlag ;
441354 // We use a 'fake' zero-length chunk to carry information about flushes from
442355 // the public API to the actual stream implementation.
@@ -453,7 +366,7 @@ Zlib.prototype._transform = function _transform(chunk, encoding, cb) {
453366 processChunk ( this , chunk , flushFlag , cb ) ;
454367} ;
455368
456- Zlib . prototype . _processChunk = function _processChunk ( chunk , flushFlag , cb ) {
369+ ZlibBase . prototype . _processChunk = function ( chunk , flushFlag , cb ) {
457370 // _processChunk() is left for backwards compatibility
458371 if ( typeof cb === 'function' )
459372 processChunk ( this , chunk , flushFlag , cb ) ;
@@ -643,6 +556,110 @@ function _close(engine, callback) {
643556 engine . _handle = null ;
644557}
645558
559+ const zlibDefaultOpts = {
560+ flush : Z_NO_FLUSH ,
561+ finishFlush : Z_FINISH ,
562+ fullFlush : Z_FULL_FLUSH
563+ } ;
564+ // Base class for all streams actually backed by zlib and using zlib-specific
565+ // parameters.
566+ function Zlib ( opts , mode ) {
567+ var windowBits = Z_DEFAULT_WINDOWBITS ;
568+ var level = Z_DEFAULT_COMPRESSION ;
569+ var memLevel = Z_DEFAULT_MEMLEVEL ;
570+ var strategy = Z_DEFAULT_STRATEGY ;
571+ var dictionary ;
572+
573+ if ( opts ) {
574+ // windowBits is special. On the compression side, 0 is an invalid value.
575+ // But on the decompression side, a value of 0 for windowBits tells zlib
576+ // to use the window size in the zlib header of the compressed stream.
577+ if ( ( opts . windowBits == null || opts . windowBits === 0 ) &&
578+ ( mode === INFLATE ||
579+ mode === GUNZIP ||
580+ mode === UNZIP ) ) {
581+ windowBits = 0 ;
582+ } else {
583+ windowBits = checkRangesOrGetDefault (
584+ opts . windowBits , 'options.windowBits' ,
585+ Z_MIN_WINDOWBITS , Z_MAX_WINDOWBITS , Z_DEFAULT_WINDOWBITS ) ;
586+ }
587+
588+ level = checkRangesOrGetDefault (
589+ opts . level , 'options.level' ,
590+ Z_MIN_LEVEL , Z_MAX_LEVEL , Z_DEFAULT_COMPRESSION ) ;
591+
592+ memLevel = checkRangesOrGetDefault (
593+ opts . memLevel , 'options.memLevel' ,
594+ Z_MIN_MEMLEVEL , Z_MAX_MEMLEVEL , Z_DEFAULT_MEMLEVEL ) ;
595+
596+ strategy = checkRangesOrGetDefault (
597+ opts . strategy , 'options.strategy' ,
598+ Z_DEFAULT_STRATEGY , Z_FIXED , Z_DEFAULT_STRATEGY ) ;
599+
600+ dictionary = opts . dictionary ;
601+ if ( dictionary !== undefined && ! isArrayBufferView ( dictionary ) ) {
602+ if ( isAnyArrayBuffer ( dictionary ) ) {
603+ dictionary = Buffer . from ( dictionary ) ;
604+ } else {
605+ throw new ERR_INVALID_ARG_TYPE (
606+ 'options.dictionary' ,
607+ [ 'Buffer' , 'TypedArray' , 'DataView' , 'ArrayBuffer' ] ,
608+ dictionary
609+ ) ;
610+ }
611+ }
612+ }
613+
614+ const handle = new binding . Zlib ( mode ) ;
615+ // Ideally, we could let ZlibBase() set up _writeState. I haven't been able
616+ // to come up with a good solution that doesn't break our internal API,
617+ // and with it all supported npm versions at the time of writing.
618+ this . _writeState = new Uint32Array ( 2 ) ;
619+ if ( ! handle . init ( windowBits ,
620+ level ,
621+ memLevel ,
622+ strategy ,
623+ this . _writeState ,
624+ processCallback ,
625+ dictionary ) ) {
626+ throw new ERR_ZLIB_INITIALIZATION_FAILED ( ) ;
627+ }
628+
629+ ZlibBase . call ( this , opts , mode , handle , zlibDefaultOpts ) ;
630+
631+ this . _level = level ;
632+ this . _strategy = strategy ;
633+ }
634+ Object . setPrototypeOf ( Zlib . prototype , ZlibBase . prototype ) ;
635+ Object . setPrototypeOf ( Zlib , ZlibBase ) ;
636+
637+ // This callback is used by `.params()` to wait until a full flush happened
638+ // before adjusting the parameters. In particular, the call to the native
639+ // `params()` function should not happen while a write is currently in progress
640+ // on the threadpool.
641+ function paramsAfterFlushCallback ( level , strategy , callback ) {
642+ assert ( this . _handle , 'zlib binding closed' ) ;
643+ this . _handle . params ( level , strategy ) ;
644+ if ( ! this . _hadError ) {
645+ this . _level = level ;
646+ this . _strategy = strategy ;
647+ if ( callback ) callback ( ) ;
648+ }
649+ }
650+
651+ Zlib . prototype . params = function params ( level , strategy , callback ) {
652+ checkRangesOrGetDefault ( level , 'level' , Z_MIN_LEVEL , Z_MAX_LEVEL ) ;
653+ checkRangesOrGetDefault ( strategy , 'strategy' , Z_DEFAULT_STRATEGY , Z_FIXED ) ;
654+
655+ if ( this . _level !== level || this . _strategy !== strategy ) {
656+ this . flush ( Z_SYNC_FLUSH ,
657+ paramsAfterFlushCallback . bind ( this , level , strategy , callback ) ) ;
658+ } else {
659+ process . nextTick ( callback ) ;
660+ }
661+ } ;
662+
646663// generic zlib
647664// minimal 2-byte header
648665function Deflate ( opts ) {
0 commit comments