@@ -293,14 +293,15 @@ function buildDataResponse(
293
293
futures : ReadonlyArray < Future > ,
294
294
cancellableStreams : Set < StreamRecord > ,
295
295
) : ExecutionResult | ExperimentalIncrementalExecutionResults {
296
- const filteredFutures = filterFutures ( errorPaths , futures ) ;
296
+ const filteredFutures = filterFutures ( undefined , errorPaths , futures ) ;
297
297
if ( filteredFutures . length > 0 ) {
298
298
return buildIncrementalResponse ( data , errors , futures , cancellableStreams ) ;
299
299
}
300
300
return errors . length > 0 ? { errors, data } : { data } ;
301
301
}
302
302
303
303
function filterFutures (
304
+ initialPath : Path | undefined ,
304
305
errorPaths : ReadonlySet < Path | undefined > ,
305
306
futures : ReadonlyArray < Future > ,
306
307
) : ReadonlyArray < Future > {
@@ -310,19 +311,33 @@ function filterFutures(
310
311
311
312
const filteredFutures : Array < Future > = [ ] ;
312
313
for ( const future of futures ) {
313
- let currentPath = isDeferredGroupedFieldSetRecord ( future )
314
+ let currentPath : Path | undefined = isDeferredGroupedFieldSetRecord ( future )
314
315
? future . path
315
316
: future . streamRecord . path ;
316
- while ( currentPath !== undefined ) {
317
+
318
+ if ( errorPaths . has ( currentPath ) ) {
319
+ continue ;
320
+ }
321
+
322
+ const paths : Array < Path | undefined > = [ currentPath ] ;
323
+ let filtered = false ;
324
+ while ( currentPath !== initialPath ) {
325
+ // Because currentPath leads to initialPath or is undefined, and the
326
+ // loop will exit if initialPath is undefined, currentPath must be
327
+ // defined.
328
+ // TODO: Consider, however, adding an invariant.
329
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
330
+ currentPath = currentPath ! . prev ;
317
331
if ( errorPaths . has ( currentPath ) ) {
332
+ filtered = true ;
318
333
break ;
319
334
}
320
- currentPath = currentPath . prev ;
335
+ paths . push ( currentPath ) ;
321
336
}
322
- if ( errorPaths . has ( currentPath ) ) {
323
- continue ;
337
+
338
+ if ( ! filtered ) {
339
+ filteredFutures . push ( future ) ;
324
340
}
325
- filteredFutures . push ( future ) ;
326
341
}
327
342
328
343
return filteredFutures ;
@@ -1966,7 +1981,7 @@ function executeDeferredGroupedFieldSet(
1966
1981
deferredFragmentRecords,
1967
1982
path : pathToArray ( path ) ,
1968
1983
data : resolved ,
1969
- futures : filterFutures ( errorPaths , futures ) ,
1984
+ futures : filterFutures ( path , errorPaths , futures ) ,
1970
1985
errors,
1971
1986
} ) ,
1972
1987
( error ) => {
@@ -1985,7 +2000,7 @@ function executeDeferredGroupedFieldSet(
1985
2000
deferredFragmentRecords,
1986
2001
path : pathToArray ( path ) ,
1987
2002
data,
1988
- futures : filterFutures ( errorPaths , futures ) ,
2003
+ futures : filterFutures ( path , errorPaths , futures ) ,
1989
2004
errors,
1990
2005
} ;
1991
2006
}
@@ -2015,6 +2030,7 @@ function firstSyncStreamItems(
2015
2030
2016
2031
const firstStreamItems = new StreamItemsRecord ( {
2017
2032
streamRecord,
2033
+ itemPath : initialPath ,
2018
2034
executor : ( incrementalContext ) =>
2019
2035
Promise . resolve ( ) . then ( ( ) => {
2020
2036
const firstResult = executor (
@@ -2033,6 +2049,7 @@ function firstSyncStreamItems(
2033
2049
2034
2050
const nextStreamItems = new StreamItemsRecord ( {
2035
2051
streamRecord,
2052
+ itemPath : currentPath ,
2036
2053
executor : ( nextIncrementalContext ) =>
2037
2054
executor ( currentPath , item , nextIncrementalContext ) ,
2038
2055
} ) ;
@@ -2065,8 +2082,10 @@ function firstAsyncStreamItems(
2065
2082
incrementalContext : IncrementalContext ,
2066
2083
) => PromiseOrValue < StreamItemsResult > ,
2067
2084
) : StreamItemsRecord {
2085
+ const initialPath = addPath ( path , initialIndex , undefined ) ;
2068
2086
const firstStreamItems : StreamItemsRecord = new StreamItemsRecord ( {
2069
2087
streamRecord,
2088
+ itemPath : initialPath ,
2070
2089
executor : ( incrementalContext ) =>
2071
2090
Promise . resolve ( ) . then ( ( ) =>
2072
2091
getNextAsyncStreamItemsResult (
@@ -2120,7 +2139,8 @@ async function getNextAsyncStreamItemsResult(
2120
2139
const nextStreamItems : StreamItemsRecord = nextAsyncStreamItems (
2121
2140
streamRecord ,
2122
2141
path ,
2123
- index + 1 ,
2142
+ itemPath ,
2143
+ index ,
2124
2144
nodes ,
2125
2145
asyncIterator ,
2126
2146
executor ,
@@ -2133,6 +2153,7 @@ async function getNextAsyncStreamItemsResult(
2133
2153
function nextAsyncStreamItems (
2134
2154
streamRecord : StreamRecord ,
2135
2155
path : Path ,
2156
+ initialPath : Path ,
2136
2157
initialIndex : number ,
2137
2158
nodes : ReadonlyArray < FieldNode > ,
2138
2159
asyncIterator : AsyncIterator < unknown > ,
@@ -2144,13 +2165,14 @@ function nextAsyncStreamItems(
2144
2165
) : StreamItemsRecord {
2145
2166
const nextStreamItems : StreamItemsRecord = new StreamItemsRecord ( {
2146
2167
streamRecord,
2168
+ itemPath : initialPath ,
2147
2169
executor : ( incrementalContext ) =>
2148
2170
Promise . resolve ( ) . then ( ( ) =>
2149
2171
getNextAsyncStreamItemsResult (
2150
2172
streamRecord ,
2151
2173
nextStreamItems ,
2152
2174
path ,
2153
- initialIndex ,
2175
+ initialIndex + 1 ,
2154
2176
incrementalContext ,
2155
2177
nodes ,
2156
2178
asyncIterator ,
@@ -2171,7 +2193,7 @@ function completeStreamItems(
2171
2193
info : GraphQLResolveInfo ,
2172
2194
itemType : GraphQLOutputType ,
2173
2195
) : PromiseOrValue < StreamItemsResult > {
2174
- const { errors, errorPaths, futures } = incrementalContext ;
2196
+ const { path , errors, errorPaths, futures } = incrementalContext ;
2175
2197
if ( isPromise ( item ) ) {
2176
2198
return completePromisedValue (
2177
2199
exeContext ,
@@ -2186,7 +2208,7 @@ function completeStreamItems(
2186
2208
( resolvedItem ) => ( {
2187
2209
streamRecord,
2188
2210
items : [ resolvedItem ] ,
2189
- futures : filterFutures ( errorPaths , futures ) ,
2211
+ futures : filterFutures ( path , errorPaths , futures ) ,
2190
2212
errors,
2191
2213
} ) ,
2192
2214
( error ) => {
@@ -2250,7 +2272,7 @@ function completeStreamItems(
2250
2272
( resolvedItem ) => ( {
2251
2273
streamRecord,
2252
2274
items : [ resolvedItem ] ,
2253
- futures : filterFutures ( errorPaths , futures ) ,
2275
+ futures : filterFutures ( path , errorPaths , futures ) ,
2254
2276
errors,
2255
2277
} ) ,
2256
2278
( error ) => {
@@ -2267,7 +2289,7 @@ function completeStreamItems(
2267
2289
return {
2268
2290
streamRecord,
2269
2291
items : [ completedItem ] ,
2270
- futures : filterFutures ( errorPaths , futures ) ,
2292
+ futures : filterFutures ( path , errorPaths , futures ) ,
2271
2293
errors,
2272
2294
} ;
2273
2295
}
0 commit comments