@@ -14,10 +14,31 @@ import {
14
14
KeyArgsFunction ,
15
15
} from "./policies" ;
16
16
17
+ // Mapping from JSON-encoded KeySpecifier strings to associated information.
18
+ const specifierInfoCache : Record < string , {
19
+ paths ?: string [ ] [ ] ;
20
+ keyFieldsFn ?: KeyFieldsFunction ;
21
+ keyArgsFn ?: KeyArgsFunction ;
22
+ } > = Object . create ( null ) ;
23
+
24
+ function lookupSpecifierInfo ( spec : KeySpecifier ) {
25
+ // It's safe to encode KeySpecifier arrays with JSON.stringify, since they're
26
+ // just arrays of strings or nested KeySpecifier arrays, and the order of the
27
+ // array elements is important (and suitably preserved by JSON.stringify).
28
+ const cacheKey = JSON . stringify ( spec ) ;
29
+ return specifierInfoCache [ cacheKey ] ||
30
+ ( specifierInfoCache [ cacheKey ] = Object . create ( null ) ) ;
31
+ }
32
+
17
33
export function keyFieldsFnFromSpecifier (
18
34
specifier : KeySpecifier ,
19
35
) : KeyFieldsFunction {
20
- return ( object , context ) => {
36
+ const info = lookupSpecifierInfo ( specifier ) ;
37
+
38
+ return info . keyFieldsFn || ( info . keyFieldsFn = (
39
+ object ,
40
+ context ,
41
+ ) => {
21
42
const extract : typeof extractKey =
22
43
( from , key ) => context . readField ( key , from ) ;
23
44
@@ -62,7 +83,7 @@ export function keyFieldsFnFromSpecifier(
62
83
) ;
63
84
64
85
return `${ context . typename } :${ JSON . stringify ( keyObject ) } ` ;
65
- } ;
86
+ } ) ;
66
87
}
67
88
68
89
// The keyArgs extraction process is roughly analogous to keyFields extraction,
@@ -73,7 +94,13 @@ export function keyFieldsFnFromSpecifier(
73
94
// function to collectSpecifierPaths, reusing the shared extractKeyPath helper
74
95
// wherever possible.
75
96
export function keyArgsFnFromSpecifier ( specifier : KeySpecifier ) : KeyArgsFunction {
76
- return ( args , { field, variables, fieldName } ) => {
97
+ const info = lookupSpecifierInfo ( specifier ) ;
98
+
99
+ return info . keyArgsFn || ( info . keyArgsFn = ( args , {
100
+ field,
101
+ variables,
102
+ fieldName,
103
+ } ) => {
77
104
const collected = collectSpecifierPaths ( specifier , keyPath => {
78
105
const firstKey = keyPath [ 0 ] ;
79
106
const firstChar = firstKey . charAt ( 0 ) ;
@@ -138,7 +165,7 @@ export function keyArgsFnFromSpecifier(specifier: KeySpecifier): KeyArgsFunction
138
165
}
139
166
140
167
return fieldName ;
141
- } ;
168
+ } ) ;
142
169
}
143
170
144
171
export function collectSpecifierPaths (
@@ -162,11 +189,11 @@ export function collectSpecifierPaths(
162
189
} , Object . create ( null ) ) ;
163
190
}
164
191
165
- export function getSpecifierPaths ( spec : KeySpecifier & {
166
- paths ?: string [ ] [ ] ;
167
- } ) : string [ ] [ ] {
168
- if ( ! spec . paths ) {
169
- const paths : string [ ] [ ] = spec . paths = [ ] ;
192
+ export function getSpecifierPaths ( spec : KeySpecifier ) : string [ ] [ ] {
193
+ const info = lookupSpecifierInfo ( spec ) ;
194
+
195
+ if ( ! info . paths ) {
196
+ const paths : string [ ] [ ] = info . paths = [ ] ;
170
197
const currentPath : string [ ] = [ ] ;
171
198
172
199
spec . forEach ( ( s , i ) => {
@@ -183,7 +210,7 @@ export function getSpecifierPaths(spec: KeySpecifier & {
183
210
} ) ;
184
211
}
185
212
186
- return spec . paths ! ;
213
+ return info . paths ! ;
187
214
}
188
215
189
216
function extractKey <
0 commit comments