@@ -27,10 +27,9 @@ import type {
2727 FragmentDefinitionNode ,
2828 ArgumentNode ,
2929 ValueNode ,
30- DirectiveNode ,
3130} from '../language/ast' ;
3231import { Kind } from '../language/kinds' ;
33- import { print } from '../language/printer ' ;
32+ import { visit } from '../language/visitor ' ;
3433
3534import type { GraphQLSchema } from '../type/schema' ;
3635import type {
@@ -70,7 +69,6 @@ import {
7069 getArgumentValues ,
7170 getDirectiveValues ,
7271} from './values' ;
73- import { visit } from '../language' ;
7472
7573/**
7674 * Terminology
@@ -516,14 +514,15 @@ export function collectFields(
516514 ) {
517515 continue ;
518516 }
519- const selectionSet = selectionSetWithFragmentArgumentsApplied (
517+ const updatedSelectionSet = selectionSetWithFragmentArgumentsApplied (
518+ exeContext ,
520519 fragment ,
521- selection . arguments ,
520+ selection ,
522521 ) ;
523522 collectFields (
524523 exeContext ,
525524 runtimeType ,
526- selectionSet ,
525+ updatedSelectionSet ,
527526 fields ,
528527 visitedFragmentNames ,
529528 ) ;
@@ -534,35 +533,57 @@ export function collectFields(
534533 return fields ;
535534}
536535
537- function selectionSetWithFragmentArgumentsApplied ( fragment : FragmentDefinitionNode , fragmentArguments ?: ReadonlyArray < ArgumentNode > ) : SelectionSetNode {
536+ function selectionSetWithFragmentArgumentsApplied (
537+ exeContext : ExecutionContext ,
538+ fragment : FragmentDefinitionNode ,
539+ fragmentSpread : FragmentSpreadNode ,
540+ ) : SelectionSetNode {
538541 if ( fragment . variableDefinitions == null ) {
539542 return fragment . selectionSet ;
540543 }
541544
542545 const providedArguments : Map < string , ArgumentNode > = new Map ( ) ;
543- for ( const arg of fragmentArguments ?? [ ] ) {
546+ for ( const arg of fragmentSpread . arguments ?? [ ] ) {
544547 providedArguments . set ( arg . name . value , arg ) ;
545548 }
546- const fragmentArgumentValues : Map < string , ValueNode > = new Map ( ) ;
549+ const fragmentArgumentValues : Map < string , ValueNode | null > = new Map ( ) ;
547550 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+ const variableName = argDef . variable . name . value ;
552+ const providedArg = providedArguments . get ( variableName ) ;
551553 if ( providedArg != null ) {
552- fragmentArgumentValues . set ( argName , providedArg . value ) ;
553- } else if ( argDefaultValue != null ) {
554- fragmentArgumentValues . set ( argName , argDefaultValue ) ;
554+ fragmentArgumentValues . set ( variableName , providedArg . value ) ;
555+ } else if ( argDef . defaultValue != null ) {
556+ fragmentArgumentValues . set ( variableName , argDef . defaultValue ) ;
557+ } else {
558+ if ( isNonNullType ( argDef . type ) ) {
559+ exeContext . errors . push (
560+ new GraphQLError (
561+ `Fragment argument "$${ variableName } " on fragment "${ fragment . name . value } " is required but not provided.` ,
562+ [ fragmentSpread , argDef ] ,
563+ ) ,
564+ ) ;
565+ }
566+ fragmentArgumentValues . set ( variableName , null ) ;
555567 }
556568 }
557569
558570 return visit ( fragment . selectionSet , {
559- Variable ( variable ) {
560- const replacementValue = fragmentArgumentValues . get ( variable . name . value ) ;
561- if ( replacementValue != null ) {
562- return replacementValue ;
571+ Argument ( node ) {
572+ if ( node . value . kind === Kind . VARIABLE ) {
573+ const variable = node . value ;
574+ if ( fragmentArgumentValues . has ( variable . name . value ) ) {
575+ const replacementValue = fragmentArgumentValues . get (
576+ variable . name . value ,
577+ ) ;
578+ if ( replacementValue == null ) {
579+ // Remove the argument if the provided value is unset.
580+ return null ;
581+ }
582+
583+ return { ...node , value : replacementValue } ;
584+ }
563585 }
564- return variable ;
565- }
586+ } ,
566587 } ) ;
567588}
568589
0 commit comments