Skip to content

Commit

Permalink
Use yauzl-clone module for cloning yauzl object
Browse files Browse the repository at this point in the history
  • Loading branch information
overlookmotel committed Apr 22, 2018
1 parent 4d86e89 commit 6b1be7a
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 95 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@

## Next

* Use `yauzl-clone` module for cloning yauzl object
* Fix: Add `fd-slicer` dev dependency
34 changes: 0 additions & 34 deletions lib/cloneYauzl.js

This file was deleted.

15 changes: 6 additions & 9 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@

// Modules
const yauzlOriginal = require('yauzl'),
eventsIntercept = require('events-intercept');
cloner = require('yauzl-clone');

// Imports
const NativePromise = require('./promise'),
cloneYauzl = require('./cloneYauzl'),
promisify = require('./promisify');

// Exports
Expand All @@ -23,13 +22,11 @@ function use(Promise, yauzl, options) {
if (!yauzl) yauzl = yauzlOriginal;

// Clone yauzl unless `options.clone` false
if (options.clone) yauzl = cloneYauzl(yauzl);

// Patch ZipFile prototype with events-intercept methods
const ZipFileProto = yauzl.ZipFile.prototype;
if (!ZipFileProto.intercept) {
eventsIntercept.patch(ZipFileProto);
['_events', '_eventsCount', '_interceptors'].forEach(key => delete ZipFileProto[key]);
if (options.clone) {
yauzl = cloner.clone(yauzl, {subclassZipFile: true, subclassEntry: true});
} else {
// Patch ZipFile prototype with events-intercept methods
cloner.clone(yauzl, {clone: false, eventsIntercept: true});
}

// Add promisfied methods
Expand Down
74 changes: 24 additions & 50 deletions lib/promisify.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

'use strict';

// Modules
const cloner = require('yauzl-clone');

// Constants
const STATE = Symbol(),
STORED_ERROR = Symbol();
Expand All @@ -14,10 +17,10 @@ module.exports = (yauzl, Promise) => {
const {ZipFile, Entry} = yauzl;

// Promisify open + from... methods
promisifyMethod(yauzl, Promise, 'open', 1);
promisifyMethod(yauzl, Promise, 'fromFd', 1);
promisifyMethod(yauzl, Promise, 'fromBuffer', 1);
promisifyMethod(yauzl, Promise, 'fromRandomAccessReader', 2);
promisifyMethod(yauzl, Promise, 'open');
promisifyMethod(yauzl, Promise, 'fromFd');
promisifyMethod(yauzl, Promise, 'fromBuffer');
promisifyMethod(yauzl, Promise, 'fromRandomAccessReader');

// Promisify `close` method
promisifyClose(ZipFile, Promise);
Expand All @@ -42,42 +45,24 @@ module.exports = (yauzl, Promise) => {
/*
* Promisify open/from... method
*/
function promisifyMethod(yauzl, Promise, fnName, optionsArg) {
const original = yauzl[fnName],
cbArg = optionsArg + 1;

yauzl[fnName] = function() {
return new Promise((resolve, reject) => {
const args = Array.prototype.slice.call(arguments);
args[optionsArg] = Object.assign({}, args[optionsArg], {lazyEntries: true, autoClose: false});

args[cbArg] = (err, zipFile) => {
if (err) return reject(err);
opened(zipFile, resolve, fnName == 'fromBuffer', yauzl);
};

original.apply(this, args);
});
};
function promisifyMethod(yauzl, Promise, fnName) {
const fromBuffer = fnName == 'fromBuffer';

cloner.patch(yauzl, fnName, original => {
return function(path, totalSize, options) {
return new Promise((resolve, reject) => {
options = Object.assign({}, options, {lazyEntries: true, autoClose: false});

original(path, totalSize, options, (err, zipFile) => {
if (err) return reject(err);
opened(zipFile, resolve, fromBuffer, yauzl);
});
});
};
});
}

function opened(zipFile, resolve, fromBuffer, yauzl) {
// Convert to instance of ZipFile subclass
const {ZipFile} = yauzl;
if (!(zipFile instanceof ZipFile)) {
const zipFileInternal = zipFile;
zipFile = setPrototype(zipFile, ZipFile.prototype);

// Forward events from internal ZipFile to exposed one
zipFileInternal.on('close', () => zipFile.emit('close'));
zipFileInternal.on('error', err => zipFile.emit('error', err));

// Remove event interceptors from internal ZipFile
// so `close` + `error` events fire on exposed zipFile instance
// NB `._interceptors` already copied to subclass instance above
if (zipFile._interceptors) zipFileInternal._interceptors = {};
}

// For `.fromBuffer()` calls, adapt `reader` to emit close event
if (fromBuffer) {
zipFile.reader.unref = yauzl.RandomAccessReader.prototype.unref;
Expand Down Expand Up @@ -177,15 +162,8 @@ function emittedEntry(entry) {

clearState(this);

// Modify entry object
if (entry) {
// Convert to instance of Entry subclass
const {Entry} = this.constructor;
if (!(entry instanceof Entry)) entry = setPrototype(entry, Entry.prototype);

// Set reference to zipFile on entry (used by `entry.openReadStream()`)
entry.zipFile = this;
}
// Set reference to zipFile on entry (used by `entry.openReadStream()`)
if (entry) entry.zipFile = this;

// Resolve promise with entry
state.resolve(entry);
Expand Down Expand Up @@ -298,10 +276,6 @@ function entryOpenReadStream(options) {
/*
* Utility functions
*/
function setPrototype(obj, proto) {
return Object.assign(Object.create(proto), obj);
}

function wrapFunctionToReturnPromise(fn, Promise) {
return function() {
try {
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"url": "https://github.com/overlookmotel/yauzl-promise/issues"
},
"dependencies": {
"events-intercept": "^2.0.0",
"yauzl": "^2.9.1"
"yauzl": "^2.9.1",
"yauzl-clone": "^1.0.0"
},
"devDependencies": {
"bluebird": "^3.5.1",
Expand Down

0 comments on commit 6b1be7a

Please sign in to comment.