diff options
author | isaacs <i@izs.me> | 2013-03-08 07:55:45 -0800 |
---|---|---|
committer | isaacs <i@izs.me> | 2013-03-08 18:56:31 -0800 |
commit | b3cbb16f41f3a7dfdbe9ad087ef9465b30529b09 (patch) | |
tree | c593b8687a21819d72eb5d0f1af86a1b348a569f /lib/zlib.js | |
parent | 29cd0f2a77faa3b2a746e64e4871cded32e8aa98 (diff) | |
download | nodejs-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.js | 47 |
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; |