Skip to content

Commit 1089d9f

Browse files
authored
fix: take context.cwd into account for cache key (#388)
1 parent 3ea730f commit 1089d9f

File tree

7 files changed

+64
-37
lines changed

7 files changed

+64
-37
lines changed

.changeset/major-apples-invent.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"eslint-plugin-import-x": patch
3+
---
4+
5+
fix: take `context.cwd` into account for cache key

src/node-resolver.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import module from 'node:module'
1+
import { isBuiltin } from 'node:module'
22
import path from 'node:path'
33

44
import { ResolverFactory } from 'unrs-resolver'
@@ -25,11 +25,7 @@ export function createNodeResolver({
2525
interfaceVersion: 3,
2626
name: 'eslint-plugin-import-x:node',
2727
resolve(modulePath, sourceFile) {
28-
if (module.isBuiltin(modulePath)) {
29-
return { found: true, path: null }
30-
}
31-
32-
if (modulePath.startsWith('data:')) {
28+
if (isBuiltin(modulePath) || modulePath.startsWith('data:')) {
3329
return { found: true, path: null }
3430
}
3531

@@ -38,10 +34,10 @@ export function createNodeResolver({
3834
if (resolved.path) {
3935
return { found: true, path: resolved.path }
4036
}
41-
return { found: false }
4237
} catch {
43-
return { found: false }
38+
//
4439
}
40+
return { found: false }
4541
},
4642
}
4743
}

src/types.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import type { TSESLint, TSESTree } from '@typescript-eslint/utils'
2-
import type { PluginName, PluginSettings } from 'eslint-import-context'
2+
import type {
3+
ImportSettings,
4+
PluginName,
5+
PluginSettings,
6+
} from 'eslint-import-context'
37
import type { MinimatchOptions } from 'minimatch'
48

59
import type { ImportType as ImportType_ } from './utils/index.js'
@@ -159,3 +163,8 @@ export interface CjsRequire extends NodeJS.Require {
159163

160164
export type SetValue<T extends Set<unknown>> =
161165
T extends Set<infer U> ? U : never
166+
167+
export interface NormalizedCacheSettings
168+
extends NonNullable<ImportSettings['cache']> {
169+
lifetime: number
170+
}

src/utils/export-map.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,36 +1105,52 @@ function childContext(
11051105
path: string,
11061106
context: RuleContext | ChildContext,
11071107
): ChildContext {
1108-
const { settings, parserOptions, parserPath, languageOptions } = context
1108+
const {
1109+
settings,
1110+
parserOptions,
1111+
parserPath,
1112+
languageOptions,
1113+
cwd,
1114+
filename,
1115+
physicalFilename,
1116+
} = context
11091117

11101118
return {
1111-
cacheKey: makeContextCacheKey(context) + path,
1119+
cacheKey: makeContextCacheKey(context) + '\0' + path,
11121120
settings,
11131121
parserOptions,
11141122
parserPath,
11151123
languageOptions,
11161124
path,
1117-
cwd: context.cwd,
1118-
filename: context.filename,
1119-
physicalFilename: context.physicalFilename,
1125+
cwd,
1126+
filename,
1127+
physicalFilename,
11201128
}
11211129
}
11221130

11231131
export function makeContextCacheKey(context: RuleContext | ChildContext) {
1124-
const { settings, parserPath, parserOptions, languageOptions } = context
1132+
const { settings, parserPath, parserOptions, languageOptions, cwd } = context
11251133

11261134
let hash =
1135+
cwd +
1136+
'\0' +
11271137
stableHash(settings) +
1138+
'\0' +
11281139
stableHash(languageOptions?.parserOptions ?? parserOptions)
11291140

11301141
if (languageOptions) {
11311142
hash +=
1132-
String(languageOptions.ecmaVersion) + String(languageOptions.sourceType)
1143+
'\0' +
1144+
String(languageOptions.ecmaVersion) +
1145+
'\0' +
1146+
String(languageOptions.sourceType)
11331147
}
11341148

1135-
hash += stableHash(
1136-
parserPath ?? languageOptions?.parser?.meta ?? languageOptions?.parser,
1137-
)
1149+
hash +=
1150+
'\0' +
1151+
stableHash(
1152+
parserPath ?? languageOptions?.parser?.meta ?? languageOptions?.parser,
1153+
)
11381154

11391155
return hash
11401156
}

src/utils/module-cache.ts

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
import debug from 'debug'
22

3-
import type { ImportSettings, PluginSettings } from '../types.js'
3+
import type { NormalizedCacheSettings, PluginSettings } from '../types.js'
44

55
const log = debug('eslint-plugin-import-x:utils:ModuleCache')
66

7-
export type CacheKey = unknown
8-
97
export interface CacheObject {
108
result: unknown
119
lastSeen: ReturnType<typeof process.hrtime>
1210
}
1311

1412
export class ModuleCache {
15-
constructor(public map: Map<CacheKey, CacheObject> = new Map()) {}
13+
constructor(public map: Map<string, CacheObject> = new Map()) {}
1614

17-
set(cacheKey: CacheKey, result: unknown) {
15+
set(cacheKey: string, result: unknown) {
1816
this.map.set(cacheKey, {
1917
result,
2018
lastSeen: process.hrtime(),
@@ -23,13 +21,12 @@ export class ModuleCache {
2321
return result
2422
}
2523

26-
get<T>(cacheKey: CacheKey, settings: ImportSettings['cache']): T | undefined {
27-
if (this.map.has(cacheKey)) {
28-
const f = this.map.get(cacheKey)
24+
get<T>(cacheKey: string, settings: NormalizedCacheSettings): T | undefined {
25+
const cache = this.map.get(cacheKey)
26+
if (cache) {
2927
// check freshness
30-
// @ts-expect-error TS can't narrow properly from `has` and `get`
31-
if (process.hrtime(f.lastSeen)[0] < settings.lifetime) {
32-
return f!.result as T
28+
if (process.hrtime(cache.lastSeen)[0] < settings.lifetime) {
29+
return cache.result as T
3330
}
3431
} else {
3532
log('cache miss for', cacheKey)
@@ -51,8 +48,6 @@ export class ModuleCache {
5148
cacheSettings.lifetime = Number.POSITIVE_INFINITY
5249
}
5350

54-
return cacheSettings as ImportSettings['cache'] & {
55-
lifetime: number
56-
}
51+
return cacheSettings as NormalizedCacheSettings
5752
}
5853
}

src/utils/resolve.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import { createNodeResolver } from '../node-resolver.js'
99
import { cjsRequire } from '../require.js'
1010
import type {
1111
ChildContext,
12-
ImportSettings,
1312
LegacyResolver,
1413
NewResolver,
1514
NodeResolverOptions,
15+
NormalizedCacheSettings,
1616
PluginSettings,
1717
RuleContext,
1818
} from '../types.js'
@@ -47,7 +47,7 @@ export const fileExistsCache = new ModuleCache()
4747
// https://stackoverflow.com/a/27382838
4848
export function fileExistsWithCaseSync(
4949
filepath: string | null,
50-
cacheSettings?: ImportSettings['cache'],
50+
cacheSettings: NormalizedCacheSettings,
5151
strict?: boolean,
5252
): boolean {
5353
// don't care if the FS is case-sensitive

test/utils/resolve.spec.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ import type { TSESLint } from '@typescript-eslint/utils'
99
import { testContext, testFilePath } from '../utils.js'
1010

1111
import { importXResolverCompat } from 'eslint-plugin-import-x'
12-
import type { CjsRequire, NewResolver } from 'eslint-plugin-import-x'
12+
import type {
13+
CjsRequire,
14+
NewResolver,
15+
NormalizedCacheSettings,
16+
} from 'eslint-plugin-import-x'
1317
import {
1418
CASE_SENSITIVE_FS,
1519
fileExistsWithCaseSync,
@@ -450,7 +454,9 @@ describe('resolve', () => {
450454
'import-x/cache': { lifetime: 0 },
451455
})
452456

453-
const cacheSettings = context.settings['import-x/cache']
457+
const cacheSettings = context.settings[
458+
'import-x/cache'
459+
] as NormalizedCacheSettings
454460

455461
const file = resolve(
456462
// Note the case difference 'MyUncoolComponent' vs 'MyUnCoolComponent'

0 commit comments

Comments
 (0)