Skip to content
This repository has been archived by the owner on Aug 4, 2021. It is now read-only.

perf: add cached version of isDir #218

Merged
merged 4 commits into from May 11, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
56 changes: 27 additions & 29 deletions src/index.js
Expand Up @@ -9,33 +9,29 @@ const ES6_BROWSER_EMPTY = resolve( __dirname, '../src/empty.js' );
// which deploy both ESM .mjs and CommonJS .js files as ESM.
const DEFAULT_EXTS = [ '.mjs', '.js', '.json', '.node' ];

let readFileCache = {};
const readFileAsync = file => new Promise((fulfil, reject) => fs.readFile(file, (err, contents) => err ? reject(err) : fulfil(contents)));
const statAsync = file => new Promise((fulfil, reject) => fs.stat(file, (err, contents) => err ? reject(err) : fulfil(contents)));
function cachedReadFile (file, cb) {
if (file in readFileCache === false) {
readFileCache[file] = readFileAsync(file).catch(err => {
delete readFileCache[file];
throw err;
});
}
readFileCache[file].then(contents => cb(null, contents), cb);
}

let isFileCache = {};
function cachedIsFile (file, cb) {
if (file in isFileCache === false) {
isFileCache[file] = statAsync(file)
.then(
stat => stat.isFile(),
err => {
if (err.code === 'ENOENT') return false;
delete isFileCache[file];
throw err;
});
}
isFileCache[file].then(contents => cb(null, contents), cb);
}
const cache = fn => {
const cache = new Map();
const wrapped = (param, done) => {
if (cache.has(param) === false) {
cache.set(param, fn(param).catch(err => {
cache.delete(param);
throw err;
}));
}
return cache.get(param).then(result => done(null, result), done);
};
wrapped.clear = () => cache.clear();
return wrapped;
};
const ignoreENOENT = err => {
if (err.code === 'ENOENT') return false;
throw err;
};
const readFileCached = cache(readFileAsync);
const isDirCached = cache(file => statAsync(file).then(stat => stat.isDirectory(), ignoreENOENT));
const isFileCached = cache(file => statAsync(file).then(stat => stat.isFile(), ignoreENOENT));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice now that I wrapped my head around it!


function getMainFields (options) {
let mainFields;
Expand Down Expand Up @@ -99,8 +95,9 @@ export default function nodeResolve ( options = {} ) {
},

generateBundle () {
isFileCache = {};
readFileCache = {};
readFileCached.clear();
isFileCached.clear();
isDirCached.clear();
},

resolveId ( importee, importer ) {
Expand Down Expand Up @@ -180,8 +177,9 @@ export default function nodeResolve ( options = {} ) {
}
return pkg;
},
readFile: cachedReadFile,
isFile: cachedIsFile,
readFile: readFileCached,
isFile: isFileCached,
isDirectory: isDirCached,
extensions: extensions
};

Expand Down