@@ -2,16 +2,16 @@ import type { ISymbolMeta } from '../extensions';
22import { Symbol } from './symbol' ;
33import type { ISymbolIdentifier , ISymbolIn , ISymbolRegistry } from './types' ;
44
5- type IndexEntry = [ string , unknown ] ;
5+ type IndexEntry = readonly [ key : string , value : unknown , serialized : string ] ;
66type IndexKeySpace = ReadonlyArray < IndexEntry > ;
77type QueryCacheKey = string ;
88type SymbolId = number ;
99
1010export class SymbolRegistry implements ISymbolRegistry {
11- /** Forward index: cache key → serialized entries it depends on . */
12- private _cacheDependencies : Map < QueryCacheKey , ReadonlyArray < string > > = new Map ( ) ;
11+ /** Forward index: cache key → index key space it was registered with . */
12+ private _cacheDependencies : Map < QueryCacheKey , IndexKeySpace > = new Map ( ) ;
1313 /** Reverse index: serialized index entry → set of cache keys that depend on it. */
14- private _dependencyToCache : Map < QueryCacheKey , Set < QueryCacheKey > > = new Map ( ) ;
14+ private _dependencyToCache : Map < string , Set < QueryCacheKey > > = new Map ( ) ;
1515 private _id : SymbolId = 0 ;
1616 private _indices : Map < IndexEntry [ 0 ] , Map < IndexEntry [ 1 ] , Set < SymbolId > > > = new Map ( ) ;
1717 private _queryCache : Map < QueryCacheKey , ReadonlyArray < Symbol > > = new Map ( ) ;
@@ -87,7 +87,7 @@ export class SymbolRegistry implements ISymbolRegistry {
8787 if ( value && typeof value === 'object' && ! Array . isArray ( value ) ) {
8888 entries . push ( ...this . buildIndexKeySpace ( value as ISymbolMeta , path ) ) ;
8989 } else {
90- entries . push ( [ path , value ] ) ;
90+ entries . push ( [ path , value , ` ${ path } : ${ JSON . stringify ( value ) } ` ] ) ;
9191 }
9292 }
9393 return entries ;
@@ -99,7 +99,7 @@ export class SymbolRegistry implements ISymbolRegistry {
9999 */
100100 private cacheKeyFromKeySpace ( indexKeySpace : IndexKeySpace ) : QueryCacheKey {
101101 return indexKeySpace
102- . map ( ( indexEntry ) => this . serializeIndexEntry ( indexEntry ) )
102+ . map ( ( indexEntry ) => indexEntry [ 2 ] )
103103 . sort ( ) // ensure order-insensitivity
104104 . join ( '|' ) ;
105105 }
@@ -116,7 +116,7 @@ export class SymbolRegistry implements ISymbolRegistry {
116116
117117 private invalidateCache ( indexKeySpace : IndexKeySpace ) : void {
118118 for ( const indexEntry of indexKeySpace ) {
119- const serialized = this . serializeIndexEntry ( indexEntry ) ;
119+ const serialized = indexEntry [ 2 ] ;
120120 const cacheKeys = this . _dependencyToCache . get ( serialized ) ;
121121 if ( ! cacheKeys ) continue ;
122122 for ( const cacheKey of cacheKeys ) {
@@ -126,8 +126,8 @@ export class SymbolRegistry implements ISymbolRegistry {
126126 const deps = this . _cacheDependencies . get ( cacheKey ) ;
127127 if ( deps ) {
128128 for ( const dep of deps ) {
129- if ( dep !== serialized ) {
130- this . _dependencyToCache . get ( dep ) ?. delete ( cacheKey ) ;
129+ if ( dep [ 2 ] !== serialized ) {
130+ this . _dependencyToCache . get ( dep [ 2 ] ) ?. delete ( cacheKey ) ;
131131 }
132132 }
133133 this . _cacheDependencies . delete ( cacheKey ) ;
@@ -138,7 +138,7 @@ export class SymbolRegistry implements ISymbolRegistry {
138138 }
139139
140140 private isSubset ( sub : IndexKeySpace , sup : IndexKeySpace ) : boolean {
141- const supMap = new Map ( sup ) ;
141+ const supMap = new Map ( sup . map ( ( e ) => [ e [ 0 ] , e [ 1 ] ] as const ) ) ;
142142 for ( const [ key , value ] of sub ) {
143143 if ( ! supMap . has ( key ) || supMap . get ( key ) !== value ) {
144144 return false ;
@@ -157,22 +157,40 @@ export class SymbolRegistry implements ISymbolRegistry {
157157 }
158158 const sets : Array < Set < SymbolId > > = [ ] ;
159159 let missed = false ;
160+
161+ // Build index sets and register cache dependencies inline within a single pass.
160162 for ( const indexEntry of indexKeySpace ) {
161- const values = this . _indices . get ( indexEntry [ 0 ] ) ;
162- if ( ! values ) {
163- missed = true ;
164- break ;
163+ const serialized = indexEntry [ 2 ] ;
164+ let cacheKeys : Set < string > ;
165+
166+ if ( this . _dependencyToCache . has ( serialized ) ) {
167+ cacheKeys = this . _dependencyToCache . get ( serialized ) ! ;
168+ } else {
169+ cacheKeys = new Set ( ) ;
170+ this . _dependencyToCache . set ( serialized , cacheKeys ) ;
165171 }
166- const set = values . get ( indexEntry [ 1 ] ) ;
167- if ( ! set ) {
168- missed = true ;
169- break ;
172+
173+ cacheKeys . add ( cacheKey ) ;
174+
175+ if ( ! missed ) {
176+ const values = this . _indices . get ( indexEntry [ 0 ] ) ;
177+ if ( ! values ) {
178+ missed = true ;
179+ continue ;
180+ }
181+ const set = values . get ( indexEntry [ 1 ] ) ;
182+ if ( ! set ) {
183+ missed = true ;
184+ continue ;
185+ }
186+ sets . push ( set ) ;
170187 }
171- sets . push ( set ) ;
172188 }
189+
190+ this . _cacheDependencies . set ( cacheKey , indexKeySpace ) ;
191+
173192 if ( missed || ! sets . length ) {
174193 this . _queryCache . set ( cacheKey , [ ] ) ;
175- this . registerCacheDependencies ( cacheKey , indexKeySpace ) ;
176194 return [ ] ;
177195 }
178196
@@ -193,29 +211,9 @@ export class SymbolRegistry implements ISymbolRegistry {
193211
194212 const symbols = Array . from ( result , ( symbolId ) => this . _values . get ( symbolId ) ! ) ;
195213 this . _queryCache . set ( cacheKey , symbols ) ;
196- this . registerCacheDependencies ( cacheKey , indexKeySpace ) ;
197214 return symbols ;
198215 }
199216
200- /**
201- * Registers reverse-index entries so that when any of the given index entries
202- * are invalidated, the cache key is evicted in O(1) per entry.
203- */
204- private registerCacheDependencies ( cacheKey : QueryCacheKey , indexKeySpace : IndexKeySpace ) : void {
205- const serializedEntries : Array < string > = [ ] ;
206- for ( const indexEntry of indexKeySpace ) {
207- const serialized = this . serializeIndexEntry ( indexEntry ) ;
208- serializedEntries . push ( serialized ) ;
209- let cacheKeys = this . _dependencyToCache . get ( serialized ) ;
210- if ( ! cacheKeys ) {
211- cacheKeys = new Set ( ) ;
212- this . _dependencyToCache . set ( serialized , cacheKeys ) ;
213- }
214- cacheKeys . add ( cacheKey ) ;
215- }
216- this . _cacheDependencies . set ( cacheKey , serializedEntries ) ;
217- }
218-
219217 private replaceStubs ( symbol : Symbol , indexKeySpace : IndexKeySpace ) : void {
220218 for ( const stubId of this . _stubs . values ( ) ) {
221219 const stub = this . _values . get ( stubId ) ;
@@ -230,8 +228,4 @@ export class SymbolRegistry implements ISymbolRegistry {
230228 }
231229 }
232230 }
233-
234- private serializeIndexEntry ( indexEntry : IndexEntry ) : string {
235- return `${ indexEntry [ 0 ] } :${ JSON . stringify ( indexEntry [ 1 ] ) } ` ;
236- }
237231}
0 commit comments