@@ -25,8 +25,12 @@ import type {
25
25
FragmentSpreadNode ,
26
26
InlineFragmentNode ,
27
27
FragmentDefinitionNode ,
28
+ ArgumentNode ,
29
+ ValueNode ,
30
+ DirectiveNode ,
28
31
} from '../language/ast' ;
29
32
import { Kind } from '../language/kinds' ;
33
+ import { print } from '../language/printer' ;
30
34
31
35
import type { GraphQLSchema } from '../type/schema' ;
32
36
import type {
@@ -66,6 +70,7 @@ import {
66
70
getArgumentValues ,
67
71
getDirectiveValues ,
68
72
} from './values' ;
73
+ import { visit } from '../language' ;
69
74
70
75
/**
71
76
* Terminology
@@ -511,10 +516,14 @@ export function collectFields(
511
516
) {
512
517
continue ;
513
518
}
519
+ const selectionSet = selectionSetWithFragmentArgumentsApplied (
520
+ fragment ,
521
+ selection . arguments ,
522
+ ) ;
514
523
collectFields (
515
524
exeContext ,
516
525
runtimeType ,
517
- fragment . selectionSet ,
526
+ selectionSet ,
518
527
fields ,
519
528
visitedFragmentNames ,
520
529
) ;
@@ -525,6 +534,38 @@ export function collectFields(
525
534
return fields ;
526
535
}
527
536
537
+ function selectionSetWithFragmentArgumentsApplied ( fragment : FragmentDefinitionNode , fragmentArguments ?: ReadonlyArray < ArgumentNode > ) : SelectionSetNode {
538
+ if ( fragment . variableDefinitions == null ) {
539
+ return fragment . selectionSet ;
540
+ }
541
+
542
+ const providedArguments : Map < string , ArgumentNode > = new Map ( ) ;
543
+ for ( const arg of fragmentArguments ?? [ ] ) {
544
+ providedArguments . set ( arg . name . value , arg ) ;
545
+ }
546
+ const fragmentArgumentValues : Map < string , ValueNode > = new Map ( ) ;
547
+ for ( const argDef of fragment . variableDefinitions ?? [ ] ) {
548
+ const argName = argDef . variable . name . value ;
549
+ const providedArg = providedArguments . get ( argName ) ;
550
+ const argDefaultValue = argDef . defaultValue ;
551
+ if ( providedArg != null ) {
552
+ fragmentArgumentValues . set ( argName , providedArg . value ) ;
553
+ } else if ( argDefaultValue != null ) {
554
+ fragmentArgumentValues . set ( argName , argDefaultValue ) ;
555
+ }
556
+ }
557
+
558
+ return visit ( fragment . selectionSet , {
559
+ Variable ( variable ) {
560
+ const replacementValue = fragmentArgumentValues . get ( variable . name . value ) ;
561
+ if ( replacementValue != null ) {
562
+ return replacementValue ;
563
+ }
564
+ return variable ;
565
+ }
566
+ } ) ;
567
+ }
568
+
528
569
/**
529
570
* Determines if a field should be included based on the @include and @skip
530
571
* directives, where @skip has higher precedence than @include.
0 commit comments