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 3 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 = (fileName, cb) => {
if (cache.has(fileName) === false) {
cache.set(fileName, fn(fileName).catch(err => {
cache.delete(fileName);
throw err;
}));
}
return cache.get(fileName).then(v => cb(null, v), cb);
};
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