browserify-zlib
Advanced tools
Comparing version 0.1.4 to 0.2.0
{ | ||
"name": "browserify-zlib", | ||
"version": "0.1.4", | ||
"description": "Full zlib module for browserify", | ||
"keywords": ["zlib", "browserify"], | ||
"main": "index.js", | ||
"version": "0.2.0", | ||
"description": "Full zlib module for the browser", | ||
"keywords": [ | ||
"zlib", | ||
"browserify" | ||
], | ||
"main": "lib/index.js", | ||
"directories": { | ||
@@ -11,31 +14,52 @@ "test": "test" | ||
"dependencies": { | ||
"pako": "~0.2.0" | ||
"pako": "~1.0.5" | ||
}, | ||
"devDependencies": { | ||
"tape": "^2.12.3", | ||
"brfs": "^1.0.1" | ||
"assert": "^1.4.1", | ||
"babel-cli": "^6.24.1", | ||
"babel-plugin-transform-es2015-arrow-functions": "^6.22.0", | ||
"babel-plugin-transform-es2015-block-scoping": "^6.24.1", | ||
"babel-plugin-transform-es2015-template-literals": "^6.22.0", | ||
"babelify": "^7.3.0", | ||
"brfs": "^1.4.3", | ||
"browserify": "^14.4.0", | ||
"exec-glob": "^1.2.2", | ||
"glob": "^7.1.2", | ||
"karma": "^1.7.0", | ||
"karma-chrome-launcher": "^2.1.1", | ||
"karma-firefox-launcher": "^1.0.1", | ||
"karma-mocha": "^1.3.0", | ||
"karma-mocha-own-reporter": "^1.1.2", | ||
"karma-phantomjs-launcher": "^1.0.4", | ||
"mocha": "^3.4.2", | ||
"phantomjs-prebuilt": "^2.1.14", | ||
"standard": "^10.0.2", | ||
"watchify": "^3.9.0" | ||
}, | ||
"testling": { | ||
"files": "test/*.js", | ||
"browsers": [ | ||
"ie/6..latest", | ||
"chrome/22..latest", | ||
"firefox/16..latest", | ||
"safari/latest", | ||
"opera/11.0..latest", | ||
"iphone/6", | ||
"ipad/6", | ||
"android-browser/latest" | ||
"scripts": { | ||
"build": "babel src --out-dir lib", | ||
"lint": "standard \"*.js\" \"!(node_modules|lib)/!(*test-zlib*|index).js\"", | ||
"pretest": "npm run build", | ||
"test": "npm run test:node && npm run test:browser", | ||
"test:node": "node node_modules/exec-glob node \"test/test-*\"", | ||
"pretest:browser": "node test/build", | ||
"test:browser": "karma start --single-run=true karma.conf.js" | ||
}, | ||
"babel": { | ||
"plugins": [ | ||
"transform-es2015-arrow-functions", | ||
"transform-es2015-block-scoping", | ||
"transform-es2015-template-literals" | ||
] | ||
}, | ||
"scripts": { | ||
"test": "node_modules/tape/bin/tape test/*.js" | ||
}, | ||
"main": "src/index.js", | ||
"author": "Devon Govett <devongovett@gmail.com>", | ||
"homepage": "https://github.com/devongovett/browserify-zlib", | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/devongovett/browserify-zlib.git" | ||
"url": "git+https://github.com/devongovett/browserify-zlib.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/devongovett/browserify-zlib/issues" | ||
} | ||
} |
# browserify-zlib | ||
Emulates Node's [zlib](http://nodejs.org/api/zlib.html) module for [Browserify](http://browserify.org) | ||
using [pako](https://github.com/nodeca/pako). It uses the actual Node source code and passes the Node zlib tests | ||
by emulating the C++ binding that actually calls zlib. | ||
[![Travis CI](https://travis-ci.org/devongovett/browserify-zlib.svg?branch=master)](https://travis-ci.org/devongovett/browserify-zlib) | ||
[![Dependency Status](https://david-dm.org/devongovett/browserify-zlib.svg?style=flat-square)](https://david-dm.org/devongovett/browserify-zlib) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard) | ||
[![browser support](https://ci.testling.com/devongovett/browserify-zlib.png) | ||
](https://ci.testling.com/devongovett/browserify-zlib) | ||
## Description | ||
[![node tests](https://travis-ci.org/devongovett/browserify-zlib.svg) | ||
](https://travis-ci.org/devongovett/browserify-zlib) | ||
Emulates Node's [zlib](https://nodejs.org/api/zlib.html) module for the browser. Can be used as a drop in replacement with [Browserify](http://browserify.org) and [webpack](http://webpack.github.io/). | ||
The heavy lifting is done using [pako](https://github.com/nodeca/pako). The code in this module is modeled closely after the code in the source of Node core to get as much compatability as possible. | ||
## API | ||
https://nodejs.org/api/zlib.html | ||
## Not implemented | ||
@@ -18,3 +21,2 @@ | ||
* The `params` method | ||
* The `dictionary` option | ||
@@ -21,0 +23,0 @@ ## License |
@@ -1,57 +0,153 @@ | ||
var msg = require('pako/lib/zlib/messages'); | ||
var zstream = require('pako/lib/zlib/zstream'); | ||
var zlib_deflate = require('pako/lib/zlib/deflate.js'); | ||
var zlib_inflate = require('pako/lib/zlib/inflate.js'); | ||
var constants = require('pako/lib/zlib/constants'); | ||
'use strict' | ||
/* eslint camelcase: "off" */ | ||
var assert = require('assert') | ||
var Zstream = require('pako/lib/zlib/zstream') | ||
var zlib_deflate = require('pako/lib/zlib/deflate.js') | ||
var zlib_inflate = require('pako/lib/zlib/inflate.js') | ||
var constants = require('pako/lib/zlib/constants') | ||
for (var key in constants) { | ||
exports[key] = constants[key]; | ||
exports[key] = constants[key] | ||
} | ||
// zlib modes | ||
exports.NONE = 0; | ||
exports.DEFLATE = 1; | ||
exports.INFLATE = 2; | ||
exports.GZIP = 3; | ||
exports.GUNZIP = 4; | ||
exports.DEFLATERAW = 5; | ||
exports.INFLATERAW = 6; | ||
exports.UNZIP = 7; | ||
exports.NONE = 0 | ||
exports.DEFLATE = 1 | ||
exports.INFLATE = 2 | ||
exports.GZIP = 3 | ||
exports.GUNZIP = 4 | ||
exports.DEFLATERAW = 5 | ||
exports.INFLATERAW = 6 | ||
exports.UNZIP = 7 | ||
var GZIP_HEADER_ID1 = 0x1f | ||
var GZIP_HEADER_ID2 = 0x8b | ||
/** | ||
* Emulate Node's zlib C++ layer for use by the JS layer in index.js | ||
*/ | ||
function Zlib(mode) { | ||
if (mode < exports.DEFLATE || mode > exports.UNZIP) | ||
throw new TypeError("Bad argument"); | ||
this.mode = mode; | ||
this.init_done = false; | ||
this.write_in_progress = false; | ||
this.pending_close = false; | ||
this.windowBits = 0; | ||
this.level = 0; | ||
this.memLevel = 0; | ||
this.strategy = 0; | ||
this.dictionary = null; | ||
function Zlib (mode) { | ||
if (typeof mode !== 'number' || mode < exports.DEFLATE || mode > exports.UNZIP) { | ||
throw new TypeError('Bad argument') | ||
} | ||
this.dictionary = null | ||
this.err = 0 | ||
this.flush = 0 | ||
this.init_done = false | ||
this.level = 0 | ||
this.memLevel = 0 | ||
this.mode = mode | ||
this.strategy = 0 | ||
this.windowBits = 0 | ||
this.write_in_progress = false | ||
this.pending_close = false | ||
this.gzip_id_bytes_read = 0 | ||
} | ||
Zlib.prototype.init = function(windowBits, level, memLevel, strategy, dictionary) { | ||
this.windowBits = windowBits; | ||
this.level = level; | ||
this.memLevel = memLevel; | ||
this.strategy = strategy; | ||
// dictionary not supported. | ||
if (this.mode === exports.GZIP || this.mode === exports.GUNZIP) | ||
this.windowBits += 16; | ||
if (this.mode === exports.UNZIP) | ||
this.windowBits += 32; | ||
if (this.mode === exports.DEFLATERAW || this.mode === exports.INFLATERAW) | ||
this.windowBits = -this.windowBits; | ||
this.strm = new zstream(); | ||
Zlib.prototype.close = function () { | ||
if (this.write_in_progress) { | ||
this.pending_close = true | ||
return | ||
} | ||
this.pending_close = false | ||
assert(this.init_done, 'close before init') | ||
assert(this.mode <= exports.UNZIP) | ||
if (this.mode === exports.DEFLATE || this.mode === exports.GZIP || this.mode === exports.DEFLATERAW) { | ||
zlib_deflate.deflateEnd(this.strm) | ||
} else if (this.mode === exports.INFLATE || this.mode === exports.GUNZIP || | ||
this.mode === exports.INFLATERAW || this.mode === exports.UNZIP) { | ||
zlib_inflate.inflateEnd(this.strm) | ||
} | ||
this.mode = exports.NONE | ||
this.dictionary = null | ||
} | ||
Zlib.prototype.write = function (flush, input, in_off, in_len, out, out_off, out_len) { | ||
return this._write(true, flush, input, in_off, in_len, out, out_off, out_len) | ||
} | ||
Zlib.prototype.writeSync = function (flush, input, in_off, in_len, out, out_off, out_len) { | ||
return this._write(false, flush, input, in_off, in_len, out, out_off, out_len) | ||
} | ||
Zlib.prototype._write = function (async, flush, input, in_off, in_len, out, out_off, out_len) { | ||
assert.equal(arguments.length, 8) | ||
assert(this.init_done, 'write before init') | ||
assert(this.mode !== exports.NONE, 'already finalized') | ||
assert.equal(false, this.write_in_progress, 'write already in progress') | ||
assert.equal(false, this.pending_close, 'close is pending') | ||
this.write_in_progress = true | ||
assert.equal(false, flush === undefined, 'must provide flush value') | ||
this.write_in_progress = true | ||
if (flush !== exports.Z_NO_FLUSH && | ||
flush !== exports.Z_PARTIAL_FLUSH && | ||
flush !== exports.Z_SYNC_FLUSH && | ||
flush !== exports.Z_FULL_FLUSH && | ||
flush !== exports.Z_FINISH && | ||
flush !== exports.Z_BLOCK) { | ||
throw new Error('Invalid flush value') | ||
} | ||
if (input == null) { | ||
input = Buffer.alloc(0) | ||
in_len = 0 | ||
in_off = 0 | ||
} | ||
this.strm.avail_in = in_len | ||
this.strm.input = input | ||
this.strm.next_in = in_off | ||
this.strm.avail_out = out_len | ||
this.strm.output = out | ||
this.strm.next_out = out_off | ||
this.flush = flush | ||
if (!async) { | ||
// sync version | ||
this._process() | ||
if (this._checkError()) { | ||
return this._afterSync() | ||
} | ||
return | ||
} | ||
// async version | ||
var self = this | ||
process.nextTick(function () { | ||
self._process() | ||
self._after() | ||
}) | ||
return this | ||
} | ||
Zlib.prototype._afterSync = function () { | ||
var avail_out = this.strm.avail_out | ||
var avail_in = this.strm.avail_in | ||
this.write_in_progress = false | ||
return [avail_in, avail_out] | ||
} | ||
Zlib.prototype._process = function () { | ||
var next_expected_header_byte = null | ||
// If the avail_out is left at 0, then it means that it ran out | ||
// of room. If there was avail_out left over, then it means | ||
// that all of the input was consumed. | ||
switch (this.mode) { | ||
@@ -61,111 +157,197 @@ case exports.DEFLATE: | ||
case exports.DEFLATERAW: | ||
var status = zlib_deflate.deflateInit2( | ||
this.strm, | ||
this.level, | ||
exports.Z_DEFLATED, | ||
this.windowBits, | ||
this.memLevel, | ||
this.strategy | ||
); | ||
break; | ||
this.err = zlib_deflate.deflate(this.strm, this.flush) | ||
break | ||
case exports.UNZIP: | ||
if (this.strm.avail_in > 0) { | ||
next_expected_header_byte = this.strm.next_in | ||
} | ||
switch (this.gzip_id_bytes_read) { | ||
case 0: | ||
if (next_expected_header_byte === null) { | ||
break | ||
} | ||
if (this.strm.input[next_expected_header_byte] === GZIP_HEADER_ID1) { | ||
this.gzip_id_bytes_read = 1 | ||
next_expected_header_byte++ | ||
if (this.strm.avail_in === 1) { | ||
// The only available byte was already read. | ||
break | ||
} | ||
} else { | ||
this.mode = exports.INFLATE | ||
break | ||
} | ||
// fallthrough | ||
case 1: | ||
if (next_expected_header_byte === null) { | ||
break | ||
} | ||
if (this.strm.input[next_expected_header_byte] === GZIP_HEADER_ID2) { | ||
this.gzip_id_bytes_read = 2 | ||
this.mode = exports.GUNZIP | ||
} else { | ||
// There is no actual difference between INFLATE and INFLATERAW | ||
// (after initialization). | ||
this.mode = exports.INFLATE | ||
} | ||
break | ||
default: | ||
throw new Error('invalid number of gzip magic number bytes read') | ||
} | ||
// fallthrough | ||
case exports.INFLATE: | ||
case exports.GUNZIP: | ||
case exports.INFLATERAW: | ||
case exports.UNZIP: | ||
var status = zlib_inflate.inflateInit2( | ||
this.strm, | ||
this.windowBits | ||
); | ||
break; | ||
this.err = zlib_inflate.inflate(this.strm, this.flush) | ||
// If data was encoded with dictionary | ||
if (this.err === exports.Z_NEED_DICT && this.dictionary) { | ||
// Load it | ||
this.err = zlib_inflate.inflateSetDictionary(this.strm, this.dictionary) | ||
if (this.err === exports.Z_OK) { | ||
// And try to decode again | ||
this.err = zlib_inflate.inflate(this.strm, this.flush) | ||
} else if (this.err === exports.Z_DATA_ERROR) { | ||
// Both inflateSetDictionary() and inflate() return Z_DATA_ERROR. | ||
// Make it possible for After() to tell a bad dictionary from bad | ||
// input. | ||
this.err = exports.Z_NEED_DICT | ||
} | ||
} | ||
while (this.strm.avail_in > 0 && | ||
this.mode === exports.GUNZIP && | ||
this.err === exports.Z_STREAM_END && | ||
this.strm.next_in[0] !== 0x00) { | ||
// Bytes remain in input buffer. Perhaps this is another compressed | ||
// member in the same archive, or just trailing garbage. | ||
// Trailing zero bytes are okay, though, since they are frequently | ||
// used for padding. | ||
this.reset() | ||
this.err = zlib_inflate.inflate(this.strm, this.flush) | ||
} | ||
break | ||
default: | ||
throw new Error("Unknown mode " + this.mode); | ||
throw new Error('Unknown mode ' + this.mode) | ||
} | ||
if (status !== exports.Z_OK) { | ||
this._error(status); | ||
return; | ||
} | ||
Zlib.prototype._checkError = function () { | ||
// Acceptable error states depend on the type of zlib stream. | ||
switch (this.err) { | ||
case exports.Z_OK: | ||
case exports.Z_BUF_ERROR: | ||
if (this.strm.avail_out !== 0 && this.flush === exports.Z_FINISH) { | ||
this._error('unexpected end of file') | ||
return false | ||
} | ||
break | ||
case exports.Z_STREAM_END: | ||
// normal statuses, not fatal | ||
break | ||
case exports.Z_NEED_DICT: | ||
if (this.dictionary == null) { | ||
this._error('Missing dictionary') | ||
} else { | ||
this._error('Bad dictionary') | ||
} | ||
return false | ||
default: | ||
// something else. | ||
this._error('Zlib error') | ||
return false | ||
} | ||
this.write_in_progress = false; | ||
this.init_done = true; | ||
}; | ||
Zlib.prototype.params = function() { | ||
throw new Error("deflateParams Not supported"); | ||
}; | ||
return true | ||
} | ||
Zlib.prototype._writeCheck = function() { | ||
if (!this.init_done) | ||
throw new Error("write before init"); | ||
if (this.mode === exports.NONE) | ||
throw new Error("already finalized"); | ||
if (this.write_in_progress) | ||
throw new Error("write already in progress"); | ||
if (this.pending_close) | ||
throw new Error("close is pending"); | ||
}; | ||
Zlib.prototype._after = function () { | ||
if (!this._checkError()) { | ||
return | ||
} | ||
Zlib.prototype.write = function(flush, input, in_off, in_len, out, out_off, out_len) { | ||
this._writeCheck(); | ||
this.write_in_progress = true; | ||
var self = this; | ||
process.nextTick(function() { | ||
self.write_in_progress = false; | ||
var res = self._write(flush, input, in_off, in_len, out, out_off, out_len); | ||
self.callback(res[0], res[1]); | ||
if (self.pending_close) | ||
self.close(); | ||
}); | ||
return this; | ||
}; | ||
var avail_out = this.strm.avail_out | ||
var avail_in = this.strm.avail_in | ||
// set method for Node buffers, used by pako | ||
function bufferSet(data, offset) { | ||
for (var i = 0; i < data.length; i++) { | ||
this[offset + i] = data[i]; | ||
this.write_in_progress = false | ||
// call the write() cb | ||
this.callback(avail_in, avail_out) | ||
if (this.pending_close) { | ||
this.close() | ||
} | ||
} | ||
Zlib.prototype.writeSync = function(flush, input, in_off, in_len, out, out_off, out_len) { | ||
this._writeCheck(); | ||
return this._write(flush, input, in_off, in_len, out, out_off, out_len); | ||
}; | ||
Zlib.prototype._error = function (message) { | ||
if (this.strm.msg) { | ||
message = this.strm.msg | ||
} | ||
this.onerror(message, this.err) | ||
Zlib.prototype._write = function(flush, input, in_off, in_len, out, out_off, out_len) { | ||
this.write_in_progress = true; | ||
if (flush !== exports.Z_NO_FLUSH && | ||
flush !== exports.Z_PARTIAL_FLUSH && | ||
flush !== exports.Z_SYNC_FLUSH && | ||
flush !== exports.Z_FULL_FLUSH && | ||
flush !== exports.Z_FINISH && | ||
flush !== exports.Z_BLOCK) { | ||
throw new Error("Invalid flush value"); | ||
// no hope of rescue. | ||
this.write_in_progress = false | ||
if (this.pending_close) { | ||
this.close() | ||
} | ||
if (input == null) { | ||
input = new Buffer(0); | ||
in_len = 0; | ||
in_off = 0; | ||
} | ||
Zlib.prototype.init = function (windowBits, level, memLevel, strategy, dictionary) { | ||
assert(arguments.length === 4 || arguments.length === 5, 'init(windowBits, level, memLevel, strategy, [dictionary])') | ||
assert(windowBits >= 8 && windowBits <= 15, 'invalid windowBits') | ||
assert(level >= -1 && level <= 9, 'invalid compression level') | ||
assert(memLevel >= 1 && memLevel <= 9, 'invalid memlevel') | ||
assert(strategy === exports.Z_FILTERED || | ||
strategy === exports.Z_HUFFMAN_ONLY || | ||
strategy === exports.Z_RLE || | ||
strategy === exports.Z_FIXED || | ||
strategy === exports.Z_DEFAULT_STRATEGY, 'invalid strategy') | ||
this._init(level, windowBits, memLevel, strategy, dictionary) | ||
this._setDictionary() | ||
} | ||
Zlib.prototype.params = function () { | ||
throw new Error('deflateParams Not supported') | ||
} | ||
Zlib.prototype.reset = function () { | ||
this._reset() | ||
this._setDictionary() | ||
} | ||
Zlib.prototype._init = function (level, windowBits, memLevel, strategy, dictionary) { | ||
this.level = level | ||
this.windowBits = windowBits | ||
this.memLevel = memLevel | ||
this.strategy = strategy | ||
this.flush = exports.Z_NO_FLUSH | ||
this.err = exports.Z_OK | ||
if (this.mode === exports.GZIP || this.mode === exports.GUNZIP) { | ||
this.windowBits += 16 | ||
} | ||
if (out._set) | ||
out.set = out._set; | ||
else | ||
out.set = bufferSet; | ||
var strm = this.strm; | ||
strm.avail_in = in_len; | ||
strm.input = input; | ||
strm.next_in = in_off; | ||
strm.avail_out = out_len; | ||
strm.output = out; | ||
strm.next_out = out_off; | ||
if (this.mode === exports.UNZIP) { | ||
this.windowBits += 32 | ||
} | ||
if (this.mode === exports.DEFLATERAW || this.mode === exports.INFLATERAW) { | ||
this.windowBits = -1 * this.windowBits | ||
} | ||
this.strm = new Zstream() | ||
switch (this.mode) { | ||
@@ -175,64 +357,78 @@ case exports.DEFLATE: | ||
case exports.DEFLATERAW: | ||
var status = zlib_deflate.deflate(strm, flush); | ||
break; | ||
case exports.UNZIP: | ||
this.err = zlib_deflate.deflateInit2( | ||
this.strm, | ||
this.level, | ||
exports.Z_DEFLATED, | ||
this.windowBits, | ||
this.memLevel, | ||
this.strategy | ||
) | ||
break | ||
case exports.INFLATE: | ||
case exports.GUNZIP: | ||
case exports.INFLATERAW: | ||
var status = zlib_inflate.inflate(strm, flush); | ||
break; | ||
case exports.UNZIP: | ||
this.err = zlib_inflate.inflateInit2( | ||
this.strm, | ||
this.windowBits | ||
) | ||
break | ||
default: | ||
throw new Error("Unknown mode " + this.mode); | ||
throw new Error('Unknown mode ' + this.mode) | ||
} | ||
if (status !== exports.Z_STREAM_END && status !== exports.Z_OK) { | ||
this._error(status); | ||
if (this.err !== exports.Z_OK) { | ||
this._error('Init error') | ||
} | ||
this.write_in_progress = false; | ||
return [strm.avail_in, strm.avail_out]; | ||
}; | ||
Zlib.prototype.close = function() { | ||
if (this.write_in_progress) { | ||
this.pending_close = true; | ||
return; | ||
this.dictionary = dictionary | ||
this.write_in_progress = false | ||
this.init_done = true | ||
} | ||
Zlib.prototype._setDictionary = function () { | ||
if (this.dictionary == null) { | ||
return | ||
} | ||
this.pending_close = false; | ||
if (this.mode === exports.DEFLATE || this.mode === exports.GZIP || this.mode === exports.DEFLATERAW) { | ||
zlib_deflate.deflateEnd(this.strm); | ||
} else { | ||
zlib_inflate.inflateEnd(this.strm); | ||
this.err = exports.Z_OK | ||
switch (this.mode) { | ||
case exports.DEFLATE: | ||
case exports.DEFLATERAW: | ||
this.err = zlib_deflate.deflateSetDictionary(this.strm, this.dictionary) | ||
break | ||
default: | ||
break | ||
} | ||
this.mode = exports.NONE; | ||
}; | ||
Zlib.prototype.reset = function() { | ||
if (this.err !== exports.Z_OK) { | ||
this._error('Failed to set dictionary') | ||
} | ||
} | ||
Zlib.prototype._reset = function () { | ||
this.err = exports.Z_OK | ||
switch (this.mode) { | ||
case exports.DEFLATE: | ||
case exports.DEFLATERAW: | ||
var status = zlib_deflate.deflateReset(this.strm); | ||
break; | ||
case exports.GZIP: | ||
this.err = zlib_deflate.deflateReset(this.strm) | ||
break | ||
case exports.INFLATE: | ||
case exports.INFLATERAW: | ||
var status = zlib_inflate.inflateReset(this.strm); | ||
break; | ||
case exports.GUNZIP: | ||
this.err = zlib_inflate.inflateReset(this.strm) | ||
break | ||
default: | ||
break | ||
} | ||
if (status !== exports.Z_OK) { | ||
this._error(status); | ||
if (this.err !== exports.Z_OK) { | ||
this._error('Failed to reset stream') | ||
} | ||
}; | ||
} | ||
Zlib.prototype._error = function(status) { | ||
this.onerror(msg[status] + ': ' + this.strm.msg, status); | ||
this.write_in_progress = false; | ||
if (this.pending_close) | ||
this.close(); | ||
}; | ||
exports.Zlib = Zlib; | ||
exports.Zlib = Zlib |
242
src/index.js
@@ -1,28 +0,12 @@ | ||
// Copyright Joyent, Inc. and other Node contributors. | ||
// | ||
// Permission is hereby granted, free of charge, to any person obtaining a | ||
// copy of this software and associated documentation files (the | ||
// "Software"), to deal in the Software without restriction, including | ||
// without limitation the rights to use, copy, modify, merge, publish, | ||
// distribute, sublicense, and/or sell copies of the Software, and to permit | ||
// persons to whom the Software is furnished to do so, subject to the | ||
// following conditions: | ||
// | ||
// The above copyright notice and this permission notice shall be included | ||
// in all copies or substantial portions of the Software. | ||
// | ||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN | ||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | ||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
// USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
'use strict'; | ||
var Transform = require('_stream_transform'); | ||
const Buffer = require('buffer').Buffer; | ||
const Transform = require('stream').Transform; | ||
const binding = require('./binding'); | ||
const util = require('util'); | ||
const assert = require('assert').ok; | ||
const kMaxLength = require('buffer').kMaxLength; | ||
const kRangeErrorMessage = 'Cannot create final Buffer. It would be larger ' + | ||
'than 0x' + kMaxLength.toString(16) + ' bytes'; | ||
var binding = require('./binding'); | ||
var util = require('util'); | ||
var assert = require('assert').ok; | ||
// zlib doesn't provide these, so kludge them in following the same | ||
@@ -50,8 +34,14 @@ // const naming scheme zlib uses. | ||
// expose all the zlib constants | ||
Object.keys(binding).forEach(function(k) { | ||
if (k.match(/^Z/)) exports[k] = binding[k]; | ||
}); | ||
const bkeys = Object.keys(binding); | ||
for (var bk = 0; bk < bkeys.length; bk++) { | ||
var bkey = bkeys[bk]; | ||
if (bkey.match(/^Z/)) { | ||
Object.defineProperty(exports, bkey, { | ||
enumerable: true, value: binding[bkey], writable: false | ||
}); | ||
} | ||
} | ||
// translation table for return codes. | ||
exports.codes = { | ||
const codes = { | ||
Z_OK: binding.Z_OK, | ||
@@ -68,4 +58,10 @@ Z_STREAM_END: binding.Z_STREAM_END, | ||
Object.keys(exports.codes).forEach(function(k) { | ||
exports.codes[exports.codes[k]] = k; | ||
const ckeys = Object.keys(codes); | ||
for (var ck = 0; ck < ckeys.length; ck++) { | ||
var ckey = ckeys[ck]; | ||
codes[codes[ckey]] = ckey; | ||
} | ||
Object.defineProperty(exports, 'codes', { | ||
enumerable: true, value: Object.freeze(codes), writable: false | ||
}); | ||
@@ -222,6 +218,14 @@ | ||
function onEnd() { | ||
var buf = Buffer.concat(buffers, nread); | ||
var buf; | ||
var err = null; | ||
if (nread >= kMaxLength) { | ||
err = new RangeError(kRangeErrorMessage); | ||
} else { | ||
buf = Buffer.concat(buffers, nread); | ||
} | ||
buffers = []; | ||
callback(null, buf); | ||
engine.close(); | ||
callback(err, buf); | ||
} | ||
@@ -232,7 +236,8 @@ } | ||
if (typeof buffer === 'string') | ||
buffer = new Buffer(buffer); | ||
buffer = Buffer.from(buffer); | ||
if (!Buffer.isBuffer(buffer)) | ||
throw new TypeError('Not a string or buffer'); | ||
var flushFlag = binding.Z_FINISH; | ||
var flushFlag = engine._finishFlushFlag; | ||
@@ -255,3 +260,2 @@ return engine._processChunk(buffer, flushFlag); | ||
// gzip - bigger header, same deflate compression | ||
@@ -269,3 +273,2 @@ function Gzip(opts) { | ||
// raw - no header | ||
@@ -289,2 +292,10 @@ function DeflateRaw(opts) { | ||
function isValidFlushFlag(flag) { | ||
return flag === binding.Z_NO_FLUSH || | ||
flag === binding.Z_PARTIAL_FLUSH || | ||
flag === binding.Z_SYNC_FLUSH || | ||
flag === binding.Z_FULL_FLUSH || | ||
flag === binding.Z_FINISH || | ||
flag === binding.Z_BLOCK; | ||
} | ||
@@ -302,13 +313,12 @@ // the Zlib class they all inherit from | ||
if (opts.flush) { | ||
if (opts.flush !== binding.Z_NO_FLUSH && | ||
opts.flush !== binding.Z_PARTIAL_FLUSH && | ||
opts.flush !== binding.Z_SYNC_FLUSH && | ||
opts.flush !== binding.Z_FULL_FLUSH && | ||
opts.flush !== binding.Z_FINISH && | ||
opts.flush !== binding.Z_BLOCK) { | ||
throw new Error('Invalid flush flag: ' + opts.flush); | ||
} | ||
if (opts.flush && !isValidFlushFlag(opts.flush)) { | ||
throw new Error('Invalid flush flag: ' + opts.flush); | ||
} | ||
if (opts.finishFlush && !isValidFlushFlag(opts.finishFlush)) { | ||
throw new Error('Invalid flush flag: ' + opts.finishFlush); | ||
} | ||
this._flushFlag = opts.flush || binding.Z_NO_FLUSH; | ||
this._finishFlushFlag = typeof opts.finishFlush !== 'undefined' ? | ||
opts.finishFlush : binding.Z_FINISH; | ||
@@ -359,10 +369,10 @@ if (opts.chunkSize) { | ||
this._binding = new binding.Zlib(mode); | ||
this._handle = new binding.Zlib(mode); | ||
var self = this; | ||
this._hadError = false; | ||
this._binding.onerror = function(message, errno) { | ||
this._handle.onerror = function(message, errno) { | ||
// there is no way to cleanly recover. | ||
// continuing only obscures problems. | ||
self._binding = null; | ||
_close(self); | ||
self._hadError = true; | ||
@@ -382,11 +392,10 @@ | ||
this._binding.init(opts.windowBits || exports.Z_DEFAULT_WINDOWBITS, | ||
level, | ||
opts.memLevel || exports.Z_DEFAULT_MEMLEVEL, | ||
strategy, | ||
opts.dictionary); | ||
this._handle.init(opts.windowBits || exports.Z_DEFAULT_WINDOWBITS, | ||
level, | ||
opts.memLevel || exports.Z_DEFAULT_MEMLEVEL, | ||
strategy, | ||
opts.dictionary); | ||
this._buffer = new Buffer(this._chunkSize); | ||
this._buffer = Buffer.allocUnsafe(this._chunkSize); | ||
this._offset = 0; | ||
this._closed = false; | ||
this._level = level; | ||
@@ -396,2 +405,8 @@ this._strategy = strategy; | ||
this.once('end', this.close); | ||
Object.defineProperty(this, '_closed', { | ||
get: () => { return !this._handle; }, | ||
configurable: true, | ||
enumerable: true | ||
}); | ||
} | ||
@@ -417,3 +432,4 @@ | ||
this.flush(binding.Z_SYNC_FLUSH, function() { | ||
self._binding.params(level, strategy); | ||
assert(self._handle, 'zlib binding closed'); | ||
self._handle.params(level, strategy); | ||
if (!self._hadError) { | ||
@@ -431,3 +447,4 @@ self._level = level; | ||
Zlib.prototype.reset = function() { | ||
return this._binding.reset(); | ||
assert(this._handle, 'zlib binding closed'); | ||
return this._handle.reset(); | ||
}; | ||
@@ -438,3 +455,3 @@ | ||
Zlib.prototype._flush = function(callback) { | ||
this._transform(new Buffer(0), '', callback); | ||
this._transform(Buffer.alloc(0), '', callback); | ||
}; | ||
@@ -445,3 +462,3 @@ | ||
if (typeof kind === 'function' || (kind === void 0 && !callback)) { | ||
if (typeof kind === 'function' || (kind === undefined && !callback)) { | ||
callback = kind; | ||
@@ -458,9 +475,8 @@ kind = binding.Z_FULL_FLUSH; | ||
} else if (ws.needDrain) { | ||
var self = this; | ||
this.once('drain', function() { | ||
self.flush(callback); | ||
}); | ||
if (callback) { | ||
this.once('drain', () => this.flush(kind, callback)); | ||
} | ||
} else { | ||
this._flushFlag = kind; | ||
this.write(new Buffer(0), '', callback); | ||
this.write(Buffer.alloc(0), '', callback); | ||
} | ||
@@ -470,18 +486,22 @@ }; | ||
Zlib.prototype.close = function(callback) { | ||
_close(this, callback); | ||
process.nextTick(emitCloseNT, this); | ||
}; | ||
function _close(engine, callback) { | ||
if (callback) | ||
process.nextTick(callback); | ||
if (this._closed) | ||
// Caller may invoke .close after a zlib error (which will null _handle). | ||
if (!engine._handle) | ||
return; | ||
this._closed = true; | ||
engine._handle.close(); | ||
engine._handle = null; | ||
} | ||
this._binding.close(); | ||
function emitCloseNT(self) { | ||
self.emit('close'); | ||
} | ||
var self = this; | ||
process.nextTick(function() { | ||
self.emit('close'); | ||
}); | ||
}; | ||
Zlib.prototype._transform = function(chunk, encoding, cb) { | ||
@@ -493,6 +513,10 @@ var flushFlag; | ||
if (!chunk === null && !Buffer.isBuffer(chunk)) | ||
if (chunk !== null && !Buffer.isBuffer(chunk)) | ||
return cb(new Error('invalid input')); | ||
// If it's the last chunk, or a final flush, we use the Z_FINISH flush flag. | ||
if (!this._handle) | ||
return cb(new Error('zlib binding closed')); | ||
// If it's the last chunk, or a final flush, we use the Z_FINISH flush flag | ||
// (or whatever flag was provided using opts.finishFlush). | ||
// If it's explicitly flushing at some other time, then we use | ||
@@ -502,3 +526,3 @@ // Z_FULL_FLUSH. Otherwise, use Z_NO_FLUSH for maximum compression | ||
if (last) | ||
flushFlag = binding.Z_FINISH; | ||
flushFlag = this._finishFlushFlag; | ||
else { | ||
@@ -513,3 +537,2 @@ flushFlag = this._flushFlag; | ||
var self = this; | ||
this._processChunk(chunk, flushFlag, cb); | ||
@@ -536,10 +559,11 @@ }; | ||
assert(this._handle, 'zlib binding closed'); | ||
do { | ||
var res = this._binding.writeSync(flushFlag, | ||
chunk, // in | ||
inOff, // in_off | ||
availInBefore, // in_len | ||
this._buffer, // out | ||
this._offset, //out_off | ||
availOutBefore); // out_len | ||
var res = this._handle.writeSync(flushFlag, | ||
chunk, // in | ||
inOff, // in_off | ||
availInBefore, // in_len | ||
this._buffer, // out | ||
this._offset, //out_off | ||
availOutBefore); // out_len | ||
} while (!this._hadError && callback(res[0], res[1])); | ||
@@ -551,4 +575,9 @@ | ||
if (nread >= kMaxLength) { | ||
_close(this); | ||
throw new RangeError(kRangeErrorMessage); | ||
} | ||
var buf = Buffer.concat(buffers, nread); | ||
this.close(); | ||
_close(this); | ||
@@ -558,9 +587,10 @@ return buf; | ||
var req = this._binding.write(flushFlag, | ||
chunk, // in | ||
inOff, // in_off | ||
availInBefore, // in_len | ||
this._buffer, // out | ||
this._offset, //out_off | ||
availOutBefore); // out_len | ||
assert(this._handle, 'zlib binding closed'); | ||
var req = this._handle.write(flushFlag, | ||
chunk, // in | ||
inOff, // in_off | ||
availInBefore, // in_len | ||
this._buffer, // out | ||
this._offset, //out_off | ||
availOutBefore); // out_len | ||
@@ -571,2 +601,12 @@ req.buffer = chunk; | ||
function callback(availInAfter, availOutAfter) { | ||
// When the callback is used in an async write, the callback's | ||
// context is the `req` object that was created. The req object | ||
// is === this._handle, and that's why it's important to null | ||
// out the values after they are done being used. `this._handle` | ||
// can stay in memory longer than the callback and buffer are needed. | ||
if (this) { | ||
this.buffer = null; | ||
this.callback = null; | ||
} | ||
if (self._hadError) | ||
@@ -594,3 +634,3 @@ return; | ||
self._offset = 0; | ||
self._buffer = new Buffer(self._chunkSize); | ||
self._buffer = Buffer.allocUnsafe(self._chunkSize); | ||
} | ||
@@ -609,9 +649,9 @@ | ||
var newReq = self._binding.write(flushFlag, | ||
chunk, | ||
inOff, | ||
availInBefore, | ||
self._buffer, | ||
self._offset, | ||
self._chunkSize); | ||
var newReq = self._handle.write(flushFlag, | ||
chunk, | ||
inOff, | ||
availInBefore, | ||
self._buffer, | ||
self._offset, | ||
self._chunkSize); | ||
newReq.callback = callback; // this same function | ||
@@ -618,0 +658,0 @@ newReq.buffer = chunk; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
192108
1727
25
0
20
11
1
80
2
+ Addedpako@1.0.11(transitive)
- Removedpako@0.2.9(transitive)
Updatedpako@~1.0.5