summaryrefslogtreecommitdiff
path: root/lib/zlib.js
diff options
context:
space:
mode:
authorisaacs <i@izs.me>2013-03-08 07:55:45 -0800
committerisaacs <i@izs.me>2013-03-08 18:56:31 -0800
commitb3cbb16f41f3a7dfdbe9ad087ef9465b30529b09 (patch)
treec593b8687a21819d72eb5d0f1af86a1b348a569f /lib/zlib.js
parent29cd0f2a77faa3b2a746e64e4871cded32e8aa98 (diff)
downloadnodejs-b3cbb16f41f3a7dfdbe9ad087ef9465b30529b09.tar.gz
nodejs-b3cbb16f41f3a7dfdbe9ad087ef9465b30529b09.tar.bz2
nodejs-b3cbb16f41f3a7dfdbe9ad087ef9465b30529b09.zip
zlib: Manage flush flags appropriately
If you call z.flush();z.write('foo'); then it would try to write 'foo' before the flush was done, triggering an assertion in the zlib binding. Closes #4950
Diffstat (limited to 'lib/zlib.js')
-rw-r--r--lib/zlib.js47
1 files changed, 34 insertions, 13 deletions
diff --git a/lib/zlib.js b/lib/zlib.js
index dc0aeca30..c9263142d 100644
--- a/lib/zlib.js
+++ b/lib/zlib.js
@@ -226,8 +226,17 @@ function Zlib(opts, mode) {
Transform.call(this, opts);
- // means a different thing there.
- this._readableState.chunkSize = null;
+ 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);
+ }
+ }
+ this._flushFlag = opts.flush || binding.Z_NO_FLUSH;
if (opts.chunkSize) {
if (opts.chunkSize < exports.Z_MIN_CHUNK ||
@@ -308,22 +317,30 @@ Zlib.prototype.reset = function reset() {
return this._binding.reset();
};
+// This is the _flush function called by the transform class,
+// internally, when the last chunk has been written.
Zlib.prototype._flush = function(callback) {
- this._transform(null, '', callback);
+ this._transform(new Buffer(0), '', callback);
};
Zlib.prototype.flush = function(callback) {
var ws = this._writableState;
- var ts = this._transformState;
- if (ws.writing) {
- ws.needDrain = true;
+ if (ws.ended) {
+ if (callback)
+ process.nextTick(callback);
+ } else if (ws.ending) {
+ if (callback)
+ this.once('end', callback);
+ } else if (ws.needDrain) {
var self = this;
this.once('drain', function() {
- self._flush(callback);
+ self.flush(callback);
});
- } else
- this._flush(callback || function() {});
+ } else {
+ this._flushFlag = binding.Z_FULL_FLUSH;
+ this.write(new Buffer(0), '', callback);
+ }
};
Zlib.prototype.close = function(callback) {
@@ -358,10 +375,14 @@ Zlib.prototype._transform = function(chunk, encoding, cb) {
// goodness.
if (last)
flushFlag = binding.Z_FINISH;
- else if (chunk === null)
- flushFlag = binding.Z_FULL_FLUSH;
- else
- flushFlag = binding.Z_NO_FLUSH;
+ else {
+ flushFlag = this._flushFlag;
+ // once we've flushed the last of the queue, stop flushing and
+ // go back to the normal behavior.
+ if (chunk.length >= ws.length) {
+ this._flushFlag = this._opts.flush || binding.Z_NO_FLUSH;
+ }
+ }
var availInBefore = chunk && chunk.length;
var availOutBefore = this._chunkSize - this._offset;