@@ -3,6 +3,7 @@ import path from 'node:path'
33
44import type { TSESLint , TSESTree } from '@typescript-eslint/utils'
55import debug from 'debug'
6+ import { dequal } from 'dequal'
67import type { Annotation } from 'doctrine'
78import doctrine from 'doctrine'
89import type { AST } from 'eslint'
@@ -1078,11 +1079,6 @@ export function recursivePatternCapture(
10781079 }
10791080}
10801081
1081- let parserOptionsHash = ''
1082- let prevParserOptions = ''
1083- let settingsHash = ''
1084- let prevSettings = ''
1085-
10861082/**
10871083 * don't hold full context object in memory, just grab what we need.
10881084 * also calculate a cacheKey, where parts of the cacheKey hash are memoized
@@ -1091,24 +1087,14 @@ function childContext(
10911087 path : string ,
10921088 context : RuleContext | ChildContext ,
10931089) : ChildContext {
1094- const { settings, parserOptions, parserPath } = context
1095-
1096- if ( JSON . stringify ( settings ) !== prevSettings ) {
1097- settingsHash = hashObject ( { settings } ) . digest ( 'hex' )
1098- prevSettings = JSON . stringify ( settings )
1099- }
1100-
1101- if ( JSON . stringify ( parserOptions ) !== prevParserOptions ) {
1102- parserOptionsHash = hashObject ( { parserOptions } ) . digest ( 'hex' )
1103- prevParserOptions = JSON . stringify ( parserOptions )
1104- }
1090+ const { settings, parserOptions, parserPath, languageOptions } = context
11051091
11061092 return {
1107- cacheKey :
1108- String ( parserPath ) + parserOptionsHash + settingsHash + String ( path ) ,
1093+ cacheKey : makeContextCacheKey ( context ) + String ( path ) ,
11091094 settings,
11101095 parserOptions,
11111096 parserPath,
1097+ languageOptions,
11121098 path,
11131099 filename :
11141100 'physicalFilename' in context
@@ -1117,6 +1103,50 @@ function childContext(
11171103 }
11181104}
11191105
1106+ type OptionsVersionsCache = Record <
1107+ 'settings' | 'parserOptions' | 'parser' ,
1108+ { value : unknown ; version : number }
1109+ >
1110+
1111+ const optionsVersionsCache : OptionsVersionsCache = {
1112+ settings : { value : null , version : 0 } ,
1113+ parserOptions : { value : null , version : 0 } ,
1114+ parser : { value : null , version : 0 } ,
1115+ }
1116+
1117+ function getOptionsVersion ( key : keyof OptionsVersionsCache , value : unknown ) {
1118+ const entry = optionsVersionsCache [ key ]
1119+
1120+ if ( ! dequal ( value , entry . value ) ) {
1121+ entry . value = value
1122+ entry . version += 1
1123+ }
1124+
1125+ return String ( entry . version )
1126+ }
1127+
1128+ function makeContextCacheKey ( context : RuleContext | ChildContext ) {
1129+ const { settings, parserPath, parserOptions, languageOptions } = context
1130+
1131+ let hash = getOptionsVersion ( 'settings' , settings )
1132+
1133+ const usedParserOptions = languageOptions ?. parserOptions ?? parserOptions
1134+
1135+ hash += getOptionsVersion ( 'parserOptions' , usedParserOptions )
1136+
1137+ if ( languageOptions ) {
1138+ const { ecmaVersion, sourceType } = languageOptions
1139+ hash += String ( ecmaVersion ) + String ( sourceType )
1140+ }
1141+
1142+ hash += getOptionsVersion (
1143+ 'parser' ,
1144+ parserPath ?? languageOptions ?. parser ?. meta ?? languageOptions ?. parser ,
1145+ )
1146+
1147+ return hash
1148+ }
1149+
11201150/**
11211151 * sometimes legacy support isn't _that_ hard... right?
11221152 */
0 commit comments