@@ -85,6 +85,8 @@ const collectSubfields = memoize3(
85
85
) ,
86
86
) ;
87
87
88
+ const SKIPPED_FIELD_SYMBOL : unique symbol = Symbol ( 'SkippedField' ) ;
89
+
88
90
/**
89
91
* Terminology
90
92
*
@@ -566,6 +568,10 @@ function executeOperation(
566
568
const path = undefined ;
567
569
let result ;
568
570
571
+ const willBranch =
572
+ newDeferDepth !== undefined &&
573
+ shouldBranch ( groupedFieldSet , exeContext , path ) ;
574
+
569
575
switch ( operation . operation ) {
570
576
case OperationTypeNode . QUERY :
571
577
result = executeFields (
@@ -574,6 +580,7 @@ function executeOperation(
574
580
rootValue ,
575
581
path ,
576
582
groupedFieldSet ,
583
+ willBranch ,
577
584
) ;
578
585
break ;
579
586
case OperationTypeNode . MUTATION :
@@ -594,13 +601,11 @@ function executeOperation(
594
601
rootValue ,
595
602
path ,
596
603
groupedFieldSet ,
604
+ willBranch ,
597
605
) ;
598
606
}
599
607
600
- if (
601
- newDeferDepth !== undefined &&
602
- shouldBranch ( groupedFieldSet , exeContext , path )
603
- ) {
608
+ if ( willBranch ) {
604
609
executeDeferredFragment (
605
610
exeContext ,
606
611
rootType ,
@@ -611,6 +616,11 @@ function executeOperation(
611
616
) ;
612
617
}
613
618
619
+ invariant (
620
+ result !== SKIPPED_FIELD_SYMBOL ,
621
+ 'fields in initial payload should not be skipped' ,
622
+ ) ;
623
+
614
624
return result ;
615
625
}
616
626
@@ -713,10 +723,12 @@ function executeFields(
713
723
sourceValue : unknown ,
714
724
path : Path | undefined ,
715
725
groupedFieldSet : GroupedFieldSet ,
726
+ willBranch : Boolean ,
716
727
asyncPayloadRecord ?: AsyncPayloadRecord ,
717
- ) : PromiseOrValue < ObjMap < unknown > > {
728
+ ) : PromiseOrValue < ObjMap < unknown > > | typeof SKIPPED_FIELD_SYMBOL {
718
729
const results = Object . create ( null ) ;
719
730
let containsPromise = false ;
731
+ let allFieldsSkipped = willBranch ? false : Boolean ( groupedFieldSet . size ) ;
720
732
721
733
try {
722
734
for ( const [ responseName , fieldGroup ] of groupedFieldSet ) {
@@ -732,6 +744,11 @@ function executeFields(
732
744
asyncPayloadRecord ,
733
745
) ;
734
746
747
+ if ( result === SKIPPED_FIELD_SYMBOL ) {
748
+ continue ;
749
+ }
750
+ allFieldsSkipped = false ;
751
+
735
752
if ( result !== undefined ) {
736
753
results [ responseName ] = result ;
737
754
if ( isPromise ( result ) ) {
@@ -750,6 +767,10 @@ function executeFields(
750
767
throw error ;
751
768
}
752
769
770
+ if ( allFieldsSkipped ) {
771
+ return SKIPPED_FIELD_SYMBOL ;
772
+ }
773
+
753
774
// If there are no promises, we can just return the object
754
775
if ( ! containsPromise ) {
755
776
return results ;
@@ -1395,7 +1416,7 @@ function completeAbstractValue(
1395
1416
path : Path ,
1396
1417
result : unknown ,
1397
1418
asyncPayloadRecord ?: AsyncPayloadRecord ,
1398
- ) : PromiseOrValue < ObjMap < unknown > > {
1419
+ ) : PromiseOrValue < ObjMap < unknown > | typeof SKIPPED_FIELD_SYMBOL > {
1399
1420
const resolveTypeFn = returnType . resolveType ?? exeContext . typeResolver ;
1400
1421
const contextValue = exeContext . contextValue ;
1401
1422
const runtimeType = resolveTypeFn ( result , contextValue , info , returnType ) ;
@@ -1505,7 +1526,7 @@ function completeObjectValue(
1505
1526
path : Path ,
1506
1527
result : unknown ,
1507
1528
asyncPayloadRecord ?: AsyncPayloadRecord ,
1508
- ) : PromiseOrValue < ObjMap < unknown > > {
1529
+ ) : PromiseOrValue < ObjMap < unknown > | typeof SKIPPED_FIELD_SYMBOL > {
1509
1530
// If there is an isTypeOf predicate function, call it with the
1510
1531
// current result. If isTypeOf returns false, then raise an error rather
1511
1532
// than continuing execution.
@@ -1561,27 +1582,29 @@ function collectAndExecuteSubfields(
1561
1582
path : Path ,
1562
1583
result : unknown ,
1563
1584
asyncPayloadRecord ?: AsyncPayloadRecord ,
1564
- ) : PromiseOrValue < ObjMap < unknown > > {
1585
+ ) : PromiseOrValue < ObjMap < unknown > > | typeof SKIPPED_FIELD_SYMBOL {
1565
1586
// Collect sub-fields to execute to complete this value.
1566
1587
const { groupedFieldSet, newDeferDepth } = collectSubfields (
1567
1588
exeContext ,
1568
1589
returnType ,
1569
1590
fieldGroup ,
1570
1591
) ;
1571
1592
1593
+ const willBranch =
1594
+ newDeferDepth !== undefined &&
1595
+ shouldBranch ( groupedFieldSet , exeContext , path ) ;
1596
+
1572
1597
const subFields = executeFields (
1573
1598
exeContext ,
1574
1599
returnType ,
1575
1600
result ,
1576
1601
path ,
1577
1602
groupedFieldSet ,
1603
+ willBranch ,
1578
1604
asyncPayloadRecord ,
1579
1605
) ;
1580
1606
1581
- if (
1582
- newDeferDepth !== undefined &&
1583
- shouldBranch ( groupedFieldSet , exeContext , path )
1584
- ) {
1607
+ if ( willBranch ) {
1585
1608
executeDeferredFragment (
1586
1609
exeContext ,
1587
1610
returnType ,
@@ -1913,9 +1936,15 @@ function executeDeferredFragment(
1913
1936
sourceValue ,
1914
1937
path ,
1915
1938
groupedFieldSet ,
1939
+ false ,
1916
1940
asyncPayloadRecord ,
1917
1941
) ;
1918
1942
1943
+ if ( promiseOrData === SKIPPED_FIELD_SYMBOL ) {
1944
+ exeContext . subsequentPayloads . delete ( asyncPayloadRecord ) ;
1945
+ return ;
1946
+ }
1947
+
1919
1948
if ( isPromise ( promiseOrData ) ) {
1920
1949
promiseOrData = promiseOrData . then ( null , ( e ) => {
1921
1950
asyncPayloadRecord . errors . push ( e ) ;
0 commit comments