1
- import { AccumulatorMap } from '../jsutils/AccumulatorMap.js' ;
2
1
import { invariant } from '../jsutils/invariant.js' ;
3
2
import type { ObjMap } from '../jsutils/ObjMap.js' ;
4
3
@@ -26,28 +25,38 @@ import { typeFromAST } from '../utilities/typeFromAST.js';
26
25
27
26
import { getDirectiveValues } from './values.js' ;
28
27
29
- export type FieldGroup = ReadonlyArray < TaggedFieldNode > ;
30
-
31
- export type GroupedFieldSet = Map < string , FieldGroup > ;
32
-
33
28
/**
34
- * A tagged field node includes metadata necessary to determine whether a field should
35
- * be executed.
29
+ * A field group is a list of fields with the same response key.
36
30
*
37
- * A field 's depth is equivalent to the number of fields between the given field and
31
+ * The group 's depth is equivalent to the number of fields between the group and
38
32
* the operation root. For example, root fields have a depth of 0, their sub-fields
39
- * have a depth of 1, and so on. Tagging fields with their depth is necessary only to
40
- * compute a field's "defer depth".
33
+ * have a depth of 1, and so on.
41
34
*
42
- * A field's defer depth is the depth of the closest containing defer directive , or
43
- * undefined, if the field is not contained by a deferred fragment.
35
+ * The groups's depth is provided so that CollectField algorithm can compute the
36
+ * depth of an inline or named fragment with a defer directive.
37
+ */
38
+ export interface FieldGroup {
39
+ depth : number ;
40
+ fields : ReadonlyArray < TaggedFieldNode > ;
41
+ }
42
+
43
+ export type GroupedFieldSet = Map < string , FieldGroup > ;
44
+
45
+ interface MutableFieldSet {
46
+ depth : number ;
47
+ fields : Array < TaggedFieldNode > ;
48
+ }
49
+
50
+ /**
51
+ * A tagged field node includes the depth of any enclosing defer directive, or
52
+ * undefined, if the field is not contained within a deferred fragment.
44
53
*
45
- * Because deferred fragments at a given level are merged, the defer depth may be used
46
- * as a unique id to tag the fields for inclusion within a given deferred payload.
54
+ * Because deferred fragments at a given level are merged, the defer depth for a
55
+ * field node may be used as a unique id to tag the fields for inclusion within a
56
+ * given deferred payload.
47
57
*/
48
58
export interface TaggedFieldNode {
49
59
fieldNode : FieldNode ;
50
- depth : number ;
51
60
deferDepth : number | undefined ;
52
61
}
53
62
@@ -70,7 +79,7 @@ export function collectFields(
70
79
groupedFieldSet : GroupedFieldSet ;
71
80
newDeferDepth : number | undefined ;
72
81
} {
73
- const groupedFieldSet = new AccumulatorMap < string , TaggedFieldNode > ( ) ;
82
+ const groupedFieldSet = new Map < string , MutableFieldSet > ( ) ;
74
83
const newDeferDepth = collectFieldsImpl (
75
84
schema ,
76
85
fragments ,
@@ -111,11 +120,11 @@ export function collectSubfields(
111
120
groupedFieldSet : GroupedFieldSet ;
112
121
newDeferDepth : number | undefined ;
113
122
} {
114
- const groupedFieldSet = new AccumulatorMap < string , TaggedFieldNode > ( ) ;
123
+ const groupedFieldSet = new Map < string , MutableFieldSet > ( ) ;
115
124
let newDeferDepth : number | undefined ;
116
125
const visitedFragmentNames = new Set < string > ( ) ;
117
126
118
- for ( const field of fieldGroup ) {
127
+ for ( const field of fieldGroup . fields ) {
119
128
if ( field . fieldNode . selectionSet ) {
120
129
const nestedNewDeferDepth = collectFieldsImpl (
121
130
schema ,
@@ -126,7 +135,7 @@ export function collectSubfields(
126
135
field . fieldNode . selectionSet ,
127
136
groupedFieldSet ,
128
137
visitedFragmentNames ,
129
- fieldGroup [ 0 ] . depth + 1 ,
138
+ fieldGroup . depth + 1 ,
130
139
field . deferDepth ,
131
140
) ;
132
141
if ( nestedNewDeferDepth !== undefined ) {
@@ -149,7 +158,7 @@ function collectFieldsImpl(
149
158
operation : OperationDefinitionNode ,
150
159
runtimeType : GraphQLObjectType ,
151
160
selectionSet : SelectionSetNode ,
152
- groupedFieldSet : AccumulatorMap < string , TaggedFieldNode > ,
161
+ groupedFieldSet : Map < string , MutableFieldSet > ,
153
162
visitedFragmentNames : Set < string > ,
154
163
depth : number ,
155
164
deferDepth : number | undefined ,
@@ -161,11 +170,19 @@ function collectFieldsImpl(
161
170
if ( ! shouldIncludeNode ( variableValues , selection ) ) {
162
171
continue ;
163
172
}
164
- groupedFieldSet . add ( getFieldEntryKey ( selection ) , {
165
- fieldNode : selection ,
166
- depth,
167
- deferDepth,
168
- } ) ;
173
+ const key = getFieldEntryKey ( selection ) ;
174
+ const fieldSet = groupedFieldSet . get ( key ) ;
175
+ if ( fieldSet ) {
176
+ fieldSet . fields . push ( {
177
+ fieldNode : selection ,
178
+ deferDepth,
179
+ } ) ;
180
+ } else {
181
+ groupedFieldSet . set ( key , {
182
+ depth,
183
+ fields : [ { fieldNode : selection , deferDepth } ] ,
184
+ } ) ;
185
+ }
169
186
break ;
170
187
}
171
188
case Kind . INLINE_FRAGMENT : {
0 commit comments