Skip to content

Commit a25f500

Browse files
committed
add fix for new tests
if we allow nesting of defers at the same level then we have to handle the case where a defer is completely empty, not just empty because its fields are also contained within a parent. this means that collectFIelds must directly return the new defer usages rather than just set the stage for later iteration of the new fields
1 parent 88cc98b commit a25f500

File tree

4 files changed

+66
-43
lines changed

4 files changed

+66
-43
lines changed

src/execution/buildFieldPlan.ts

-15
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ export type DeferUsageSet = ReadonlySet<DeferUsage>;
88
export interface FieldGroup {
99
fields: ReadonlyArray<FieldDetails>;
1010
deferUsages?: DeferUsageSet | undefined;
11-
knownDeferUsages?: DeferUsageSet | undefined;
1211
}
1312

1413
export type GroupedFieldSet = Map<string, FieldGroup>;
@@ -21,21 +20,15 @@ export interface NewGroupedFieldSetDetails {
2120
export function buildFieldPlan(
2221
fields: Map<string, ReadonlyArray<FieldDetails>>,
2322
parentDeferUsages: DeferUsageSet = new Set<DeferUsage>(),
24-
knownDeferUsages: DeferUsageSet = new Set<DeferUsage>(),
2523
): {
2624
groupedFieldSet: GroupedFieldSet;
2725
newGroupedFieldSetDetailsMap: Map<DeferUsageSet, NewGroupedFieldSetDetails>;
28-
newDeferUsages: ReadonlyArray<DeferUsage>;
2926
} {
30-
const newDeferUsages: Set<DeferUsage> = new Set<DeferUsage>();
31-
const newKnownDeferUsages = new Set<DeferUsage>(knownDeferUsages);
32-
3327
const groupedFieldSet = new Map<
3428
string,
3529
{
3630
fields: Array<FieldDetails>;
3731
deferUsages: DeferUsageSet;
38-
knownDeferUsages: DeferUsageSet;
3932
}
4033
>();
4134

@@ -47,7 +40,6 @@ export function buildFieldPlan(
4740
{
4841
fields: Array<FieldDetails>;
4942
deferUsages: DeferUsageSet;
50-
knownDeferUsages: DeferUsageSet;
5143
}
5244
>;
5345
shouldInitiateDefer: boolean;
@@ -72,10 +64,6 @@ export function buildFieldPlan(
7264
continue;
7365
}
7466
deferUsageSet.add(deferUsage);
75-
if (!knownDeferUsages.has(deferUsage)) {
76-
newDeferUsages.add(deferUsage);
77-
newKnownDeferUsages.add(deferUsage);
78-
}
7967
}
8068
if (inOriginalResult) {
8169
deferUsageSet.clear();
@@ -99,7 +87,6 @@ export function buildFieldPlan(
9987
fieldGroup = {
10088
fields: [],
10189
deferUsages: deferUsageSet,
102-
knownDeferUsages: newKnownDeferUsages,
10390
};
10491
groupedFieldSet.set(responseKey, fieldGroup);
10592
}
@@ -140,7 +127,6 @@ export function buildFieldPlan(
140127
fieldGroup = {
141128
fields: [],
142129
deferUsages: deferUsageSet,
143-
knownDeferUsages: newKnownDeferUsages,
144130
};
145131
newGroupedFieldSet.set(responseKey, fieldGroup);
146132
}
@@ -150,7 +136,6 @@ export function buildFieldPlan(
150136
return {
151137
groupedFieldSet,
152138
newGroupedFieldSetDetailsMap,
153-
newDeferUsages: Array.from(newDeferUsages),
154139
};
155140
}
156141

src/execution/collectFields.ts

+57-18
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,12 @@ export function collectFields(
6060
variableValues: { [variable: string]: unknown },
6161
runtimeType: GraphQLObjectType,
6262
operation: OperationDefinitionNode,
63-
): Map<string, ReadonlyArray<FieldDetails>> {
63+
): {
64+
fields: Map<string, ReadonlyArray<FieldDetails>>;
65+
newDeferUsages: ReadonlyArray<DeferUsage>;
66+
} {
6467
const groupedFieldSet = new AccumulatorMap<string, FieldDetails>();
68+
const newDeferUsages: Array<DeferUsage> = [];
6569
const context: CollectFieldsContext = {
6670
schema,
6771
fragments,
@@ -71,8 +75,13 @@ export function collectFields(
7175
visitedFragmentNames: new Set(),
7276
};
7377

74-
collectFieldsImpl(context, operation.selectionSet, groupedFieldSet);
75-
return groupedFieldSet;
78+
collectFieldsImpl(
79+
context,
80+
operation.selectionSet,
81+
groupedFieldSet,
82+
newDeferUsages,
83+
);
84+
return { fields: groupedFieldSet, newDeferUsages };
7685
}
7786

7887
/**
@@ -93,7 +102,10 @@ export function collectSubfields(
93102
operation: OperationDefinitionNode,
94103
returnType: GraphQLObjectType,
95104
fieldDetails: ReadonlyArray<FieldDetails>,
96-
): Map<string, ReadonlyArray<FieldDetails>> {
105+
): {
106+
fields: Map<string, ReadonlyArray<FieldDetails>>;
107+
newDeferUsages: ReadonlyArray<DeferUsage>;
108+
} {
97109
const context: CollectFieldsContext = {
98110
schema,
99111
fragments,
@@ -103,6 +115,7 @@ export function collectSubfields(
103115
visitedFragmentNames: new Set(),
104116
};
105117
const subGroupedFieldSet = new AccumulatorMap<string, FieldDetails>();
118+
const newDeferUsages: Array<DeferUsage> = [];
106119

107120
for (const fieldDetail of fieldDetails) {
108121
const node = fieldDetail.node;
@@ -111,18 +124,23 @@ export function collectSubfields(
111124
context,
112125
node.selectionSet,
113126
subGroupedFieldSet,
127+
newDeferUsages,
114128
fieldDetail.deferUsage,
115129
);
116130
}
117131
}
118132

119-
return subGroupedFieldSet;
133+
return {
134+
fields: subGroupedFieldSet,
135+
newDeferUsages,
136+
};
120137
}
121138

122139
function collectFieldsImpl(
123140
context: CollectFieldsContext,
124141
selectionSet: SelectionSetNode,
125142
groupedFieldSet: AccumulatorMap<string, FieldDetails>,
143+
newDeferUsages: Array<DeferUsage>,
126144
deferUsage?: DeferUsage,
127145
): void {
128146
const {
@@ -161,12 +179,24 @@ function collectFieldsImpl(
161179
deferUsage,
162180
);
163181

164-
collectFieldsImpl(
165-
context,
166-
selection.selectionSet,
167-
groupedFieldSet,
168-
newDeferUsage ?? deferUsage,
169-
);
182+
if (!newDeferUsage) {
183+
collectFieldsImpl(
184+
context,
185+
selection.selectionSet,
186+
groupedFieldSet,
187+
newDeferUsages,
188+
deferUsage,
189+
);
190+
} else {
191+
newDeferUsages.push(newDeferUsage);
192+
collectFieldsImpl(
193+
context,
194+
selection.selectionSet,
195+
groupedFieldSet,
196+
newDeferUsages,
197+
newDeferUsage,
198+
);
199+
}
170200

171201
break;
172202
}
@@ -197,14 +227,23 @@ function collectFieldsImpl(
197227
}
198228
if (!newDeferUsage) {
199229
visitedFragmentNames.add(fragName);
230+
collectFieldsImpl(
231+
context,
232+
fragment.selectionSet,
233+
groupedFieldSet,
234+
newDeferUsages,
235+
deferUsage,
236+
);
237+
} else {
238+
newDeferUsages.push(newDeferUsage);
239+
collectFieldsImpl(
240+
context,
241+
fragment.selectionSet,
242+
groupedFieldSet,
243+
newDeferUsages,
244+
newDeferUsage,
245+
);
200246
}
201-
202-
collectFieldsImpl(
203-
context,
204-
fragment.selectionSet,
205-
groupedFieldSet,
206-
newDeferUsage ?? deferUsage,
207-
);
208247
break;
209248
}
210249
}

src/execution/execute.ts

+8-9
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,18 @@ const buildSubFieldPlan = memoize3(
9191
returnType: GraphQLObjectType,
9292
fieldGroup: FieldGroup,
9393
) => {
94-
const subFields = collectSubfields(
94+
const { fields: subFields, newDeferUsages } = collectSubfields(
9595
exeContext.schema,
9696
exeContext.fragments,
9797
exeContext.variableValues,
9898
exeContext.operation,
9999
returnType,
100100
fieldGroup.fields,
101101
);
102-
return buildFieldPlan(
103-
subFields,
104-
fieldGroup.deferUsages,
105-
fieldGroup.knownDeferUsages,
106-
);
102+
return {
103+
...buildFieldPlan(subFields, fieldGroup.deferUsages),
104+
newDeferUsages,
105+
};
107106
},
108107
);
109108

@@ -408,14 +407,14 @@ function executeOperation(
408407
);
409408
}
410409

411-
const fields = collectFields(
410+
const { fields, newDeferUsages } = collectFields(
412411
schema,
413412
fragments,
414413
variableValues,
415414
rootType,
416415
operation,
417416
);
418-
const { groupedFieldSet, newGroupedFieldSetDetailsMap, newDeferUsages } =
417+
const { groupedFieldSet, newGroupedFieldSetDetailsMap } =
419418
buildFieldPlan(fields);
420419

421420
const newDeferMap = addNewDeferredFragments(
@@ -1807,7 +1806,7 @@ function executeSubscription(
18071806
);
18081807
}
18091808

1810-
const fields = collectFields(
1809+
const { fields } = collectFields(
18111810
schema,
18121811
fragments,
18131812
variableValues,

src/validation/rules/SingleFieldSubscriptionsRule.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export function SingleFieldSubscriptionsRule(
4949
fragments[definition.name.value] = definition;
5050
}
5151
}
52-
const fields = collectFields(
52+
const { fields } = collectFields(
5353
schema,
5454
fragments,
5555
variableValues,

0 commit comments

Comments
 (0)