Skip to content

Commit

Permalink
support actual stream.destroy api
Browse files Browse the repository at this point in the history
closes #110
  • Loading branch information
thejoshwolfe committed Feb 15, 2024
1 parent f02ca56 commit 784e5cd
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 12 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,8 @@ It is possible to destroy the `readStream` before it has piped all of its data.
To do this, call `readStream.destroy()`.
You must `unpipe()` the `readStream` from any destination before calling `readStream.destroy()`.
If this zipfile was created using `fromRandomAccessReader()`, the `RandomAccessReader` implementation
must provide readable streams that implement a `.destroy()` method (see `randomAccessReader._readStreamForRange()`)
must provide readable streams that implement a `._destroy()` method according to
https://nodejs.org/api/stream.html#writable_destroyerr-callback (see `randomAccessReader._readStreamForRange()`)
in order for calls to `readStream.destroy()` to work in this context.

#### close()
Expand Down Expand Up @@ -448,11 +449,11 @@ Any errors emitted on the readable stream will be handled and re-emitted on the
(returned from `zipfile.openReadStream()`) or provided as the `err` argument to the appropriate callback
(for example, for `fromRandomAccessReader()`).

The returned stream *must* implement a method `.destroy()`
if you call `readStream.destroy()` on streams you get from `openReadStream()`.
If you never call `readStream.destroy()`, then streams returned from this method do not need to implement a method `.destroy()`.
`.destroy()` should abort any streaming that is in progress and clean up any associated resources.
`.destroy()` will only be called after the stream has been `unpipe()`d from its destination.
If you call `readStream.destroy()` on streams you get from `openReadStream()`,
the returned stream *must* implement a method `._destroy()` according to https://nodejs.org/api/stream.html#writable_destroyerr-callback .
If you never call `readStream.destroy()`, then streams returned from this method do not need to implement a method `._destroy()`.
`._destroy()` should abort any streaming that is in progress and clean up any associated resources.
`._destroy()` will only be called after the stream has been `unpipe()`d from its destination.

Note that the stream returned from this method might not be the same object that is provided by `openReadStream()`.
The stream returned from this method might be `pipe()`d through one or more filter streams (for example, a zlib inflate stream).
Expand Down
27 changes: 21 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -564,13 +564,13 @@ ZipFile.prototype.openReadStream = function(entry, options, callback) {
endpointStream = inflateFilter;
}
// this is part of yauzl's API, so implement this function on the client-visible stream
endpointStream.destroy = function() {
installDestoryFn(endpointStream, function() {
destroyed = true;
if (inflateFilter !== endpointStream) inflateFilter.unpipe(endpointStream);
readStream.unpipe(inflateFilter);
// TODO: the inflateFilter may cause a memory leak. see Issue #27.
readStream.destroy();
};
});
}
callback(null, endpointStream);
} finally {
Expand Down Expand Up @@ -695,23 +695,23 @@ RandomAccessReader.prototype.createReadStream = function(options) {
if (!destroyed) refUnrefFilter.emit("error", err);
});
});
refUnrefFilter.destroy = function() {
installDestoryFn(refUnrefFilter, function() {
stream.unpipe(refUnrefFilter);
refUnrefFilter.unref();
stream.destroy();
};
});

var byteCounter = new AssertByteCountStream(end - start);
refUnrefFilter.on("error", function(err) {
setImmediate(function() {
if (!destroyed) byteCounter.emit("error", err);
});
});
byteCounter.destroy = function() {
installDestoryFn(byteCounter, function() {
destroyed = true;
refUnrefFilter.unpipe(byteCounter);
refUnrefFilter.destroy();
};
});

return stream.pipe(refUnrefFilter).pipe(byteCounter);
};
Expand Down Expand Up @@ -791,6 +791,21 @@ if (typeof Buffer.allocUnsafe === "function") {
};
}

// Node 8 introduced a proper destroy() implementation on writable streams.
function installDestoryFn(stream, fn) {
if (typeof stream.destory === "function") {
// New API.
stream._destroy = function(err, cb) {
console.log("\ndoing the new api\n");
fn();
if (cb != null) cb(err);
};
} else {
// Old API.
stream.destroy = fn;
}
}

function defaultCallback(err) {
if (err) throw err;
}

0 comments on commit 784e5cd

Please sign in to comment.