@@ -15,7 +15,11 @@ import type {
1515 StreamItem ,
1616 SubsequentResultRecord ,
1717} from './types.js' ;
18- import { isStream } from './types.js' ;
18+ import {
19+ isDeferredFragment ,
20+ isPendingExecutionGroup ,
21+ isStream ,
22+ } from './types.js' ;
1923
2024/**
2125 * @internal
@@ -46,9 +50,11 @@ export class IncrementalGraph {
4650 }
4751
4852 getNewRootNodes (
53+ deferredFragments : ReadonlyArray < DeferredFragment > ,
4954 incrementalDataRecords : ReadonlyArray < IncrementalDataRecord > ,
5055 ) : ReadonlyArray < SubsequentResultRecord > {
5156 const initialResultChildren = new Set < SubsequentResultRecord > ( ) ;
57+ this . _addDeferredFragments ( deferredFragments , initialResultChildren ) ;
5258 this . _addIncrementalDataRecords (
5359 incrementalDataRecords ,
5460 undefined ,
@@ -89,13 +95,16 @@ export class IncrementalGraph {
8995 }
9096 }
9197
98+ // TODO: add test case for async transformation
99+ /* c8 ignore start */
92100 nextCompletedBatch ( ) : Promise < Iterable < IncrementalGraphEvent > | undefined > {
93101 const { promise, resolve } = promiseWithResolvers <
94102 Iterable < IncrementalGraphEvent > | undefined
95103 > ( ) ;
96104 this . _nextQueue . push ( resolve ) ;
97105 return promise ;
98106 }
107+ /* c8 ignore stop */
99108
100109 hasPending ( ) : boolean {
101110 return this . _pending . size > 0 ;
@@ -184,13 +193,22 @@ export class IncrementalGraph {
184193 }
185194 }
186195
196+ private _addDeferredFragments (
197+ deferredFragments : ReadonlyArray < DeferredFragment > ,
198+ initialResultChildren ?: Set < SubsequentResultRecord > ,
199+ ) : void {
200+ for ( const deferredFragment of deferredFragments ) {
201+ this . _addDeferredFragment ( deferredFragment , initialResultChildren ) ;
202+ }
203+ }
204+
187205 private _addIncrementalDataRecords (
188206 incrementalDataRecords : ReadonlyArray < IncrementalDataRecord > ,
189207 parents : ReadonlyArray < DeferredFragment > | undefined ,
190208 initialResultChildren ?: Set < SubsequentResultRecord > ,
191209 ) : void {
192210 for ( const incrementalDataRecord of incrementalDataRecords ) {
193- if ( ! isStream ( incrementalDataRecord ) ) {
211+ if ( isPendingExecutionGroup ( incrementalDataRecord ) ) {
194212 let ready = false ;
195213 for ( const deferredFragment of incrementalDataRecord . deferredFragments ) {
196214 this . _addDeferredFragment ( deferredFragment , initialResultChildren ) ;
@@ -202,13 +220,15 @@ export class IncrementalGraph {
202220 if ( ready && this . _completesRootNode ( incrementalDataRecord ) ) {
203221 this . _onExecutionGroup ( incrementalDataRecord ) ;
204222 }
205- } else if ( parents === undefined ) {
206- invariant ( initialResultChildren !== undefined ) ;
207- initialResultChildren . add ( incrementalDataRecord ) ;
208- } else {
209- for ( const parent of parents ) {
210- this . _addDeferredFragment ( parent , initialResultChildren ) ;
211- parent . children . add ( incrementalDataRecord ) ;
223+ } else if ( isStream ( incrementalDataRecord ) ) {
224+ if ( parents === undefined ) {
225+ invariant ( initialResultChildren !== undefined ) ;
226+ initialResultChildren . add ( incrementalDataRecord ) ;
227+ } else {
228+ for ( const parent of parents ) {
229+ this . _addDeferredFragment ( parent , initialResultChildren ) ;
230+ parent . children . add ( incrementalDataRecord ) ;
231+ }
212232 }
213233 }
214234 }
@@ -219,7 +239,7 @@ export class IncrementalGraph {
219239 ) : ReadonlyArray < SubsequentResultRecord > {
220240 const newRootNodes : Array < SubsequentResultRecord > = [ ] ;
221241 for ( const node of maybeEmptyNewRootNodes ) {
222- if ( ! isStream ( node ) ) {
242+ if ( isDeferredFragment ( node ) ) {
223243 if ( node . pendingExecutionGroups . size > 0 ) {
224244 // TODO: add test cases for executor returning results early
225245 /* c8 ignore start */
@@ -282,7 +302,6 @@ export class IncrementalGraph {
282302 return ;
283303 }
284304 parent . children . add ( deferredFragment ) ;
285- this . _addDeferredFragment ( parent , initialResultChildren ) ;
286305 }
287306
288307 private _onExecutionGroup (
@@ -295,16 +314,21 @@ export class IncrementalGraph {
295314
296315 pendingExecutionGroup . result = result = result ( ) ;
297316 const value = result . value ;
317+
318+ // TODO: add test case for async transformation
319+ /* c8 ignore start */
298320 if ( isPromise ( value ) ) {
299321 this . _pending . add ( pendingExecutionGroup ) ;
300322 // eslint-disable-next-line @typescript-eslint/no-floating-promises
301323 value . then ( ( resolved ) => {
302324 this . _pending . delete ( pendingExecutionGroup ) ;
303325 this . _enqueue ( resolved ) ;
304326 } ) ;
305- } else {
306- this . _enqueue ( value ) ;
327+ return ;
307328 }
329+ /* c8 ignore stop */
330+
331+ this . _enqueue ( value ) ;
308332 }
309333
310334 private async _onStreamItems ( stream : Stream ) : Promise < void > {
@@ -315,6 +339,7 @@ export class IncrementalGraph {
315339
316340 let items : Array < unknown > = [ ] ;
317341 let errors : Array < GraphQLError > = [ ] ;
342+ const deferredFragments : Array < DeferredFragment > = [ ] ;
318343 let incrementalDataRecords : Array < IncrementalDataRecord > = [ ] ;
319344
320345 const streamItemQueue = stream . streamItemQueue ;
@@ -325,12 +350,20 @@ export class IncrementalGraph {
325350 ? streamItem . result ( )
326351 : streamItem . result ;
327352 if ( ! ( result instanceof BoxedPromiseOrValue ) ) {
353+ // TODO: add test case for async transformation
354+ /* c8 ignore start */
328355 if ( items . length > 0 ) {
329356 this . _enqueue ( {
330357 stream,
331- result : { items, errors, incrementalDataRecords } ,
358+ result : {
359+ items,
360+ errors,
361+ deferredFragments,
362+ incrementalDataRecords,
363+ } ,
332364 } ) ;
333365 }
366+ /* c8 ignore stop */
334367 this . _enqueue (
335368 result === null
336369 ? { stream }
@@ -343,6 +376,8 @@ export class IncrementalGraph {
343376 }
344377
345378 let value = result . value ;
379+ // TODO: add test case for async transformation
380+ /* c8 ignore start */
346381 if ( isPromise ( value ) ) {
347382 this . _pending . add ( stream ) ;
348383 if ( items . length > 0 ) {
@@ -351,6 +386,7 @@ export class IncrementalGraph {
351386 result : {
352387 items,
353388 errors,
389+ deferredFragments,
354390 incrementalDataRecords,
355391 } ,
356392 } ) ;
@@ -360,12 +396,13 @@ export class IncrementalGraph {
360396 }
361397 // eslint-disable-next-line no-await-in-loop
362398 value = await value ;
363- this . _pending . delete ( stream ) ;
364399 // wait an additional tick to coalesce resolving additional promises
365400 // within the queue
366401 // eslint-disable-next-line no-await-in-loop
367402 await Promise . resolve ( ) ;
403+ this . _pending . delete ( stream ) ;
368404 }
405+ /* c8 ignore stop */
369406 const item = value . item ;
370407 if ( item === undefined ) {
371408 // TODO: add test case for failure via transformation with existing items
@@ -376,6 +413,7 @@ export class IncrementalGraph {
376413 result : {
377414 items,
378415 errors,
416+ deferredFragments,
379417 incrementalDataRecords,
380418 } ,
381419 } ) ;
@@ -389,13 +427,14 @@ export class IncrementalGraph {
389427 }
390428 items . push ( item ) ;
391429 errors . push ( ...value . errors ) ;
430+ deferredFragments . push ( ...value . deferredFragments ) ;
392431 incrementalDataRecords . push ( ...value . incrementalDataRecords ) ;
393432 }
394433
395434 if ( items . length > 0 ) {
396435 this . _enqueue ( {
397436 stream,
398- result : { items, errors, incrementalDataRecords } ,
437+ result : { items, errors, deferredFragments , incrementalDataRecords } ,
399438 } ) ;
400439 }
401440
@@ -407,7 +446,8 @@ export class IncrementalGraph {
407446 const next = this . _nextQueue . shift ( ) ;
408447 if ( next === undefined ) {
409448 return ;
410- }
449+ } /* c8 ignore start */
450+ // TODO: add test case for async transformation
411451 next ( this . currentCompletedBatch ( ) ) ;
412- }
452+ } /* c8 ignore stop */
413453}
0 commit comments