@@ -24,26 +24,39 @@ import type { GraphQLSchema } from '../type/schema.js';
24
24
25
25
import { typeFromAST } from '../utilities/typeFromAST.js' ;
26
26
27
- import { getDirectiveValues } from './values.js' ;
27
+ import type { GraphQLVariableSignature } from './getVariableSignature.js' ;
28
+ import { experimentalGetArgumentValues , getDirectiveValues } from './values.js' ;
28
29
29
30
export interface DeferUsage {
30
31
label : string | undefined ;
31
32
parentDeferUsage : DeferUsage | undefined ;
32
33
}
33
34
35
+ export interface FragmentVariables {
36
+ signatures : ObjMap < GraphQLVariableSignature > ;
37
+ values : ObjMap < unknown > ;
38
+ }
39
+
34
40
export interface FieldDetails {
35
41
node : FieldNode ;
36
- deferUsage : DeferUsage | undefined ;
42
+ deferUsage ?: DeferUsage | undefined ;
43
+ fragmentVariables ?: FragmentVariables | undefined ;
37
44
}
38
45
39
46
export type FieldGroup = ReadonlyArray < FieldDetails > ;
40
47
41
48
export type GroupedFieldSet = ReadonlyMap < string , FieldGroup > ;
42
49
50
+ export interface FragmentDetails {
51
+ definition : FragmentDefinitionNode ;
52
+ variableSignatures ?: ObjMap < GraphQLVariableSignature > | undefined ;
53
+ }
54
+
43
55
interface CollectFieldsContext {
44
56
schema : GraphQLSchema ;
45
- fragments : ObjMap < FragmentDefinitionNode > ;
57
+ fragments : ObjMap < FragmentDetails > ;
46
58
variableValues : { [ variable : string ] : unknown } ;
59
+ fragmentVariableValues ?: FragmentVariables ;
47
60
operation : OperationDefinitionNode ;
48
61
runtimeType : GraphQLObjectType ;
49
62
visitedFragmentNames : Set < string > ;
@@ -60,7 +73,7 @@ interface CollectFieldsContext {
60
73
*/
61
74
export function collectFields (
62
75
schema : GraphQLSchema ,
63
- fragments : ObjMap < FragmentDefinitionNode > ,
76
+ fragments : ObjMap < FragmentDetails > ,
64
77
variableValues : { [ variable : string ] : unknown } ,
65
78
runtimeType : GraphQLObjectType ,
66
79
operation : OperationDefinitionNode ,
@@ -101,7 +114,7 @@ export function collectFields(
101
114
// eslint-disable-next-line max-params
102
115
export function collectSubfields (
103
116
schema : GraphQLSchema ,
104
- fragments : ObjMap < FragmentDefinitionNode > ,
117
+ fragments : ObjMap < FragmentDetails > ,
105
118
variableValues : { [ variable : string ] : unknown } ,
106
119
operation : OperationDefinitionNode ,
107
120
returnType : GraphQLObjectType ,
@@ -140,12 +153,14 @@ export function collectSubfields(
140
153
} ;
141
154
}
142
155
156
+ // eslint-disable-next-line max-params
143
157
function collectFieldsImpl (
144
158
context : CollectFieldsContext ,
145
159
selectionSet : SelectionSetNode ,
146
160
groupedFieldSet : AccumulatorMap < string , FieldDetails > ,
147
161
newDeferUsages : Array < DeferUsage > ,
148
162
deferUsage ?: DeferUsage ,
163
+ fragmentVariables ?: FragmentVariables ,
149
164
) : void {
150
165
const {
151
166
schema,
@@ -159,18 +174,19 @@ function collectFieldsImpl(
159
174
for ( const selection of selectionSet . selections ) {
160
175
switch ( selection . kind ) {
161
176
case Kind . FIELD : {
162
- if ( ! shouldIncludeNode ( variableValues , selection ) ) {
177
+ if ( ! shouldIncludeNode ( selection , variableValues , fragmentVariables ) ) {
163
178
continue ;
164
179
}
165
180
groupedFieldSet . add ( getFieldEntryKey ( selection ) , {
166
181
node : selection ,
167
182
deferUsage,
183
+ fragmentVariables,
168
184
} ) ;
169
185
break ;
170
186
}
171
187
case Kind . INLINE_FRAGMENT : {
172
188
if (
173
- ! shouldIncludeNode ( variableValues , selection ) ||
189
+ ! shouldIncludeNode ( selection , variableValues , fragmentVariables ) ||
174
190
! doesFragmentConditionMatch ( schema , selection , runtimeType )
175
191
) {
176
192
continue ;
@@ -179,6 +195,7 @@ function collectFieldsImpl(
179
195
const newDeferUsage = getDeferUsage (
180
196
operation ,
181
197
variableValues ,
198
+ fragmentVariables ,
182
199
selection ,
183
200
deferUsage ,
184
201
) ;
@@ -190,6 +207,7 @@ function collectFieldsImpl(
190
207
groupedFieldSet ,
191
208
newDeferUsages ,
192
209
deferUsage ,
210
+ fragmentVariables ,
193
211
) ;
194
212
} else {
195
213
newDeferUsages . push ( newDeferUsage ) ;
@@ -199,6 +217,7 @@ function collectFieldsImpl(
199
217
groupedFieldSet ,
200
218
newDeferUsages ,
201
219
newDeferUsage ,
220
+ fragmentVariables ,
202
221
) ;
203
222
}
204
223
@@ -210,42 +229,60 @@ function collectFieldsImpl(
210
229
const newDeferUsage = getDeferUsage (
211
230
operation ,
212
231
variableValues ,
232
+ fragmentVariables ,
213
233
selection ,
214
234
deferUsage ,
215
235
) ;
216
236
217
237
if (
218
238
! newDeferUsage &&
219
239
( visitedFragmentNames . has ( fragName ) ||
220
- ! shouldIncludeNode ( variableValues , selection ) )
240
+ ! shouldIncludeNode ( selection , variableValues , fragmentVariables ) )
221
241
) {
222
242
continue ;
223
243
}
224
244
225
245
const fragment = fragments [ fragName ] ;
226
246
if (
227
247
fragment == null ||
228
- ! doesFragmentConditionMatch ( schema , fragment , runtimeType )
248
+ ! doesFragmentConditionMatch ( schema , fragment . definition , runtimeType )
229
249
) {
230
250
continue ;
231
251
}
252
+
253
+ const fragmentVariableSignatures = fragment . variableSignatures ;
254
+ let newFragmentVariables : FragmentVariables | undefined ;
255
+ if ( fragmentVariableSignatures ) {
256
+ newFragmentVariables = {
257
+ signatures : fragmentVariableSignatures ,
258
+ values : experimentalGetArgumentValues (
259
+ selection ,
260
+ Object . values ( fragmentVariableSignatures ) ,
261
+ variableValues ,
262
+ fragmentVariables ,
263
+ ) ,
264
+ } ;
265
+ }
266
+
232
267
if ( ! newDeferUsage ) {
233
268
visitedFragmentNames . add ( fragName ) ;
234
269
collectFieldsImpl (
235
270
context ,
236
- fragment . selectionSet ,
271
+ fragment . definition . selectionSet ,
237
272
groupedFieldSet ,
238
273
newDeferUsages ,
239
274
deferUsage ,
275
+ newFragmentVariables ,
240
276
) ;
241
277
} else {
242
278
newDeferUsages . push ( newDeferUsage ) ;
243
279
collectFieldsImpl (
244
280
context ,
245
- fragment . selectionSet ,
281
+ fragment . definition . selectionSet ,
246
282
groupedFieldSet ,
247
283
newDeferUsages ,
248
284
newDeferUsage ,
285
+ newFragmentVariables ,
249
286
) ;
250
287
}
251
288
break ;
@@ -262,10 +299,16 @@ function collectFieldsImpl(
262
299
function getDeferUsage (
263
300
operation : OperationDefinitionNode ,
264
301
variableValues : { [ variable : string ] : unknown } ,
302
+ fragmentVariables : FragmentVariables | undefined ,
265
303
node : FragmentSpreadNode | InlineFragmentNode ,
266
304
parentDeferUsage : DeferUsage | undefined ,
267
305
) : DeferUsage | undefined {
268
- const defer = getDirectiveValues ( GraphQLDeferDirective , node , variableValues ) ;
306
+ const defer = getDirectiveValues (
307
+ GraphQLDeferDirective ,
308
+ node ,
309
+ variableValues ,
310
+ fragmentVariables ,
311
+ ) ;
269
312
270
313
if ( ! defer ) {
271
314
return ;
@@ -291,10 +334,16 @@ function getDeferUsage(
291
334
* directives, where `@skip` has higher precedence than `@include`.
292
335
*/
293
336
function shouldIncludeNode (
294
- variableValues : { [ variable : string ] : unknown } ,
295
337
node : FragmentSpreadNode | FieldNode | InlineFragmentNode ,
338
+ variableValues : { [ variable : string ] : unknown } ,
339
+ fragmentVariables : FragmentVariables | undefined ,
296
340
) : boolean {
297
- const skip = getDirectiveValues ( GraphQLSkipDirective , node , variableValues ) ;
341
+ const skip = getDirectiveValues (
342
+ GraphQLSkipDirective ,
343
+ node ,
344
+ variableValues ,
345
+ fragmentVariables ,
346
+ ) ;
298
347
if ( skip ?. if === true ) {
299
348
return false ;
300
349
}
@@ -303,6 +352,7 @@ function shouldIncludeNode(
303
352
GraphQLIncludeDirective ,
304
353
node ,
305
354
variableValues ,
355
+ fragmentVariables ,
306
356
) ;
307
357
if ( include ?. if === false ) {
308
358
return false ;
0 commit comments