Skip to content

Commit

Permalink
fix(utils): export map cache is tainted by unreliable parse results
Browse files Browse the repository at this point in the history
  • Loading branch information
G-Rath committed Sep 24, 2024
1 parent 9913baa commit 8d4ed98
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
6 changes: 5 additions & 1 deletion src/exportMap/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ export default class ExportMapBuilder {

exportMap.mtime = stats.mtime;

exportCache.set(cacheKey, exportMap);
// If the visitor keys were not populated, then we shouldn't save anything to the cache,
// since the parse results may not be reliable.
if (exportMap.visitorKeys) {
exportCache.set(cacheKey, exportMap);
}
return exportMap;
}

Expand Down
21 changes: 19 additions & 2 deletions tests/src/core/getExports.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ import * as fs from 'fs';
import { getFilename } from '../utils';
import { test as testUnambiguous } from 'eslint-module-utils/unambiguous';

const doesBabelHaveVisitorKeys = () => {
const babelPath = require.resolve('babel-eslint');
const hypotheticalLocation = babelPath.replace('index.js', 'visitor-keys.js');
return fs.existsSync(hypotheticalLocation);
};

describe('ExportMap', function () {
const fakeContext = Object.assign(
semver.satisfies(eslintPkg.version, '>= 7.28') ? {
Expand All @@ -21,10 +27,12 @@ describe('ExportMap', function () {
},
{
settings: {},
parserPath: 'babel-eslint',
parserPath: require.resolve('babel-eslint'),
},
);

const isVisitorKeysSupported = doesBabelHaveVisitorKeys();

it('handles ExportAllDeclaration', function () {
let imports;
expect(function () {
Expand All @@ -36,11 +44,20 @@ describe('ExportMap', function () {

});

it('returns a cached copy on subsequent requests', function () {
isVisitorKeysSupported && it('returns a cached copy on subsequent requests', function () {
expect(ExportMapBuilder.get('./named-exports', fakeContext))
.to.exist.and.equal(ExportMapBuilder.get('./named-exports', fakeContext));
});

it('does not return a cached copy if the parse does not yield a visitor keys', function () {
const mockContext = {
...fakeContext,
parserPath: 'not-real',
};
expect(ExportMapBuilder.get('./named-exports', mockContext))
.to.exist.and.not.equal(ExportMapBuilder.get('./named-exports', mockContext));
});

it('does not return a cached copy after modification', (done) => {
const firstAccess = ExportMapBuilder.get('./mutator', fakeContext);
expect(firstAccess).to.exist;
Expand Down

0 comments on commit 8d4ed98

Please sign in to comment.