diff --git a/lib/zlib.js b/lib/zlib.js index 7837f3f7bc..b0826a8f54 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -150,7 +150,10 @@ function zlibBuffer(engine, buffer, callback) { } function onEnd() { - callback(null, Buffer.concat(buffers, nread)); + var buf = Buffer.concat(buffers, nread); + buffers = []; + callback(null, buf); + engine._clear(); } engine.on('error', onError); @@ -353,6 +356,10 @@ Zlib.prototype.end = function end(chunk, cb) { return ret; }; +Zlib.prototype._clear = function() { + return this._binding.clear(); +}; + Zlib.prototype._process = function() { if (this._hadError) return; diff --git a/src/node_zlib.cc b/src/node_zlib.cc index deacb713d9..406c042b91 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -39,7 +39,8 @@ static Persistent callback_sym; static Persistent onerror_sym; enum node_zlib_mode { - DEFLATE = 1, + NONE, + DEFLATE, INFLATE, GZIP, GUNZIP, @@ -60,17 +61,40 @@ class ZCtx : public ObjectWrap { ZCtx(node_zlib_mode mode) : ObjectWrap(), dictionary_(NULL), mode_(mode) {} + ~ZCtx() { + Clear(); + } + + + void Clear() { + assert(!write_in_progress_ && "write in progress"); + assert(init_done_ && "clear before init"); + assert(mode_ <= UNZIP); + if (mode_ == DEFLATE || mode_ == GZIP || mode_ == DEFLATERAW) { (void)deflateEnd(&strm_); } else if (mode_ == INFLATE || mode_ == GUNZIP || mode_ == INFLATERAW || mode_ == UNZIP) { (void)inflateEnd(&strm_); } + mode_ = NONE; + + if (dictionary_ != NULL) { + delete[] dictionary_; + dictionary_ = NULL; + } + } + - if (dictionary_ != NULL) delete[] dictionary_; + static Handle Clear(const Arguments& args) { + HandleScope scope; + ZCtx *ctx = ObjectWrap::Unwrap(args.This()); + ctx->Clear(); + return scope.Close(Undefined()); } + // write(flush, in, in_off, in_len, out, out_off, out_len) static Handle Write(const Arguments& args) { HandleScope scope; @@ -78,6 +102,7 @@ class ZCtx : public ObjectWrap { ZCtx *ctx = ObjectWrap::Unwrap(args.This()); assert(ctx->init_done_ && "write before init"); + assert(ctx->mode_ != NONE && "already finalized"); assert(!ctx->write_in_progress_ && "write already in progress"); ctx->write_in_progress_ = true; @@ -450,6 +475,7 @@ void InitZlib(Handle target) { NODE_SET_PROTOTYPE_METHOD(z, "write", ZCtx::Write); NODE_SET_PROTOTYPE_METHOD(z, "init", ZCtx::Init); + NODE_SET_PROTOTYPE_METHOD(z, "clear", ZCtx::Clear); NODE_SET_PROTOTYPE_METHOD(z, "reset", ZCtx::Reset); z->SetClassName(String::NewSymbol("Zlib"));