@@ -1418,41 +1418,70 @@ function invalidReturnTypeError(
14181418 ) ;
14191419}
14201420
1421+ /**
1422+ * Instantiates new DeferredFragmentRecords for the given path within an
1423+ * incremental data record, returning an updated map of DeferUsage
1424+ * objects to DeferredFragmentRecords.
1425+ *
1426+ * Note: As defer directives may be used with operations returning lists,
1427+ * a DeferUsage object may correspond to many DeferredFragmentRecords.
1428+ *
1429+ * DeferredFragmentRecord creation includes the following steps:
1430+ * 1. The new DeferredFragmentRecord is instantiated at the given path.
1431+ * 2. The parent result record is calculated from the given incremental data
1432+ * record.
1433+ * 3. The IncrementalPublisher is notified that a new DeferredFragmentRecord
1434+ * with the calculated parent has been added; the record will be released only
1435+ * after the parent has completed.
1436+ *
1437+ */
14211438function addNewDeferredFragments (
14221439 incrementalPublisher : IncrementalPublisher ,
14231440 newDeferUsages : ReadonlyArray < DeferUsage > ,
14241441 incrementalDataRecord : IncrementalDataRecord ,
14251442 deferMap ?: ReadonlyMap < DeferUsage , DeferredFragmentRecord > ,
14261443 path ?: Path | undefined ,
14271444) : ReadonlyMap < DeferUsage , DeferredFragmentRecord > {
1428- let newDeferMap ;
14291445 if ( newDeferUsages . length === 0 ) {
1430- newDeferMap = deferMap ?? new Map < DeferUsage , DeferredFragmentRecord > ( ) ;
1431- } else {
1432- newDeferMap =
1433- deferMap === undefined
1434- ? new Map < DeferUsage , DeferredFragmentRecord > ( )
1435- : new Map < DeferUsage , DeferredFragmentRecord > ( deferMap ) ;
1436- for ( const deferUsage of newDeferUsages ) {
1437- const parentDeferUsage = deferUsage . ancestors [ 0 ] ;
1438-
1439- const parent =
1440- parentDeferUsage === undefined
1441- ? ( incrementalDataRecord as InitialResultRecord | StreamItemsRecord )
1442- : deferredFragmentRecordFromDeferUsage ( parentDeferUsage , newDeferMap ) ;
1443-
1444- const deferredFragmentRecord = new DeferredFragmentRecord ( {
1445- path,
1446- label : deferUsage . label ,
1447- } ) ;
1446+ // Given no DeferUsages, return the existing map, creating one if necessary.
1447+ return deferMap ?? new Map < DeferUsage , DeferredFragmentRecord > ( ) ;
1448+ }
14481449
1449- incrementalPublisher . reportNewDeferFragmentRecord (
1450- deferredFragmentRecord ,
1451- parent ,
1452- ) ;
1450+ // Create a copy of the old map.
1451+ const newDeferMap =
1452+ deferMap === undefined
1453+ ? new Map < DeferUsage , DeferredFragmentRecord > ( )
1454+ : new Map < DeferUsage , DeferredFragmentRecord > ( deferMap ) ;
1455+
1456+ // For each new deferUsage object:
1457+ for ( const newDeferUsage of newDeferUsages ) {
1458+ // DeferUsage objects track their parent targets; the immediate parent is always the first member of this list.
1459+ const parentTarget = newDeferUsage . ancestors [ 0 ] ;
1460+
1461+ // If the parent target is defined, the parent target is a DeferUsage object and
1462+ // the parent result record is the DeferredFragmentRecord corresponding to that DeferUsage.
1463+ // If the parent target is not defined, the parent result record is either:
1464+ // - the InitialResultRecord, or
1465+ // - a StreamItemsRecord, as `@defer` may be nested under `@stream`.
1466+ const parent =
1467+ parentTarget === undefined
1468+ ? ( incrementalDataRecord as InitialResultRecord | StreamItemsRecord )
1469+ : deferredFragmentRecordFromDeferUsage ( parentTarget , newDeferMap ) ;
1470+
1471+ // Instantiate the new record.
1472+ const deferredFragmentRecord = new DeferredFragmentRecord ( {
1473+ path,
1474+ label : newDeferUsage . label ,
1475+ } ) ;
14531476
1454- newDeferMap . set ( deferUsage , deferredFragmentRecord ) ;
1455- }
1477+ // Report the new record to the Incremental Publisher.
1478+ incrementalPublisher . reportNewDeferFragmentRecord (
1479+ deferredFragmentRecord ,
1480+ parent ,
1481+ ) ;
1482+
1483+ // Update the map.
1484+ newDeferMap . set ( newDeferUsage , deferredFragmentRecord ) ;
14561485 }
14571486
14581487 return newDeferMap ;
0 commit comments