Skip to content

Commit 01414be

Browse files
committed
Update collectFields: no longer throws errors that validation should catch
1 parent 4ebe8db commit 01414be

File tree

3 files changed

+49
-25
lines changed

3 files changed

+49
-25
lines changed

src/execution/__tests__/variables-test.ts

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,16 +1054,6 @@ describe('Execute: Handles inputs', () => {
10541054
data: {
10551055
fieldWithNullableStringInput: null,
10561056
},
1057-
errors: [
1058-
{
1059-
message:
1060-
'Fragment argument "$value" on fragment "a" is required but not provided.',
1061-
locations: [
1062-
{ line: 3, column: 11 },
1063-
{ line: 6, column: 20 },
1064-
],
1065-
},
1066-
],
10671057
});
10681058
});
10691059

@@ -1115,16 +1105,6 @@ describe('Execute: Handles inputs', () => {
11151105
data: {
11161106
fieldWithNullableStringInput: 'null',
11171107
},
1118-
errors: [
1119-
{
1120-
message:
1121-
'Fragment argument "$value" on fragment "a" is non-null, but null was provided.',
1122-
locations: [
1123-
{ line: 3, column: 16 },
1124-
{ line: 6, column: 20 },
1125-
],
1126-
},
1127-
],
11281108
});
11291109
});
11301110

src/execution/collectFields.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import type { ObjMap } from '../jsutils/ObjMap';
22

33
import type {
4-
SelectionSetNode,
4+
ArgumentNode,
55
FieldNode,
66
FragmentSpreadNode,
77
InlineFragmentNode,
88
FragmentDefinitionNode,
9+
SelectionSetNode,
10+
ValueNode,
911
} from '../language/ast';
1012
import { Kind } from '../language/kinds';
1113

@@ -19,6 +21,8 @@ import { isAbstractType } from '../type/definition';
1921

2022
import { typeFromAST } from '../utilities/typeFromAST';
2123

24+
import { visit } from '../language/visitor';
25+
2226
import { getDirectiveValues } from './values';
2327

2428
/**
@@ -89,12 +93,14 @@ export function collectFields(
8993
) {
9094
continue;
9195
}
96+
const selectionSetWithArgumentsApplied =
97+
selectionSetWithFragmentArgumentsApplied(fragment, selection);
9298
collectFields(
9399
schema,
94100
fragments,
95101
variableValues,
96102
runtimeType,
97-
fragment.selectionSet,
103+
selectionSetWithArgumentsApplied,
98104
fields,
99105
visitedFragmentNames,
100106
);
@@ -157,3 +163,44 @@ function doesFragmentConditionMatch(
157163
function getFieldEntryKey(node: FieldNode): string {
158164
return node.alias ? node.alias.value : node.name.value;
159165
}
166+
167+
/**
168+
*
169+
* When a fragment spread is provided with arguments,
170+
* visit that fragment's definition and replace those arguments'
171+
* variable usages with the provided argument value.
172+
*/
173+
function selectionSetWithFragmentArgumentsApplied(
174+
fragment: FragmentDefinitionNode,
175+
fragmentSpread: FragmentSpreadNode,
176+
): SelectionSetNode {
177+
const variableDefinitions = fragment.variableDefinitions;
178+
if (!variableDefinitions) {
179+
return fragment.selectionSet;
180+
}
181+
182+
const providedArguments: Map<string, ArgumentNode> = new Map();
183+
if (fragmentSpread.arguments) {
184+
for (const argument of fragmentSpread.arguments) {
185+
providedArguments.set(argument.name.value, argument);
186+
}
187+
}
188+
189+
const fragmentVariableValues: Map<string, ValueNode> = new Map();
190+
for (const variableDef of variableDefinitions) {
191+
const variableName = variableDef.variable.name.value;
192+
const providedArg = providedArguments.get(variableName);
193+
if (providedArg) {
194+
fragmentVariableValues.set(variableName, providedArg.value);
195+
} else if (variableDef.defaultValue) {
196+
fragmentVariableValues.set(variableName, variableDef.defaultValue);
197+
}
198+
// Otherwise just preserve the variable as-is: it will be treated as unset by the executor.
199+
}
200+
201+
return visit(fragment.selectionSet, {
202+
Variable(node) {
203+
return fragmentVariableValues.get(node.name.value);
204+
},
205+
});
206+
}

src/execution/execute.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,8 @@ import type {
2222
OperationDefinitionNode,
2323
FieldNode,
2424
FragmentDefinitionNode,
25-
ArgumentNode,
26-
ValueNode,
2725
} from '../language/ast';
2826
import { Kind } from '../language/kinds';
29-
import { visit } from '../language/visitor';
3027

3128
import type { GraphQLSchema } from '../type/schema';
3229
import type {

0 commit comments

Comments
 (0)