@@ -520,17 +520,23 @@ function executeFieldsSerially(
520
520
fieldNodes ,
521
521
fieldPath ,
522
522
) ;
523
- if ( result === undefined ) {
523
+ if ( result === null ) {
524
524
return results ;
525
525
}
526
526
const promise = getPromise ( result ) ;
527
527
if ( promise ) {
528
528
return promise . then ( resolvedResult => {
529
- results [ responseName ] = resolvedResult ;
529
+ if ( resolvedResult . errors && resolvedResult . errors . length ) {
530
+ exeContext . errors . push . apply ( exeContext . errors , resolvedResult . errors ) ;
531
+ }
532
+ results [ responseName ] = resolvedResult . data ;
530
533
return results ;
531
534
} ) ;
532
535
}
533
- results [ responseName ] = result ;
536
+ if ( result . errors && result . errors . length ) {
537
+ exeContext . errors . push . apply ( exeContext . errors , result . errors ) ;
538
+ }
539
+ results [ responseName ] = result . data ;
534
540
return results ;
535
541
} ) ,
536
542
Promise . resolve ( { } ) ,
@@ -560,7 +566,7 @@ function executeFields(
560
566
fieldNodes ,
561
567
fieldPath ,
562
568
) ;
563
- if ( result === undefined ) {
569
+ if ( result === null ) {
564
570
return results ;
565
571
}
566
572
results [ responseName ] = result ;
@@ -572,14 +578,40 @@ function executeFields(
572
578
573
579
// If there are no promises, we can just return the object
574
580
if ( ! containsPromise ) {
575
- return finalResults ;
581
+ const merged = mergeEPRs ( finalResults ) ;
582
+ if ( merged . errors && merged . errors . length ) {
583
+ exeContext . errors . push . apply ( exeContext . errors , merged . errors ) ;
584
+ }
585
+ return merged.data;
576
586
}
577
587
578
588
// Otherwise, results is a map from field name to the result
579
589
// of resolving that field, which is possibly a promise. Return
580
590
// a promise that will return this same map, but with any
581
591
// promises replaced with the values they resolved to.
582
- return promiseForObject(finalResults);
592
+ return promiseForObject ( finalResults ) . then ( merged => {
593
+ if ( merged . errors && merged . errors . length ) {
594
+ exeContext . errors . push . apply ( exeContext . errors , merged . errors ) ;
595
+ }
596
+ return merged.data;
597
+ } ) ;
598
+ }
599
+
600
+ function mergeEPRs (
601
+ eprMap : ObjMap < ExecutionPartialResult < mixed > > ,
602
+ ) : ExecutionPartialResult < mixed > {
603
+ const keys = Object . keys ( eprMap ) ;
604
+ const values = keys . map ( name => eprMap [ name ] ) ;
605
+ return values . reduce (
606
+ ( merged , value , i ) => {
607
+ merged . data [ keys [ i ] ] = value . data ;
608
+ if ( value . errors && value . errors . length ) {
609
+ merged . errors . push . apply ( merged . errors , value . errors ) ;
610
+ }
611
+ return merged ;
612
+ } ,
613
+ { data : Object . create ( null ) , errors : [ ] } ,
614
+ ) ;
583
615
}
584
616
585
617
/**
@@ -705,21 +737,25 @@ function doesFragmentConditionMatch(
705
737
}
706
738
707
739
/**
708
- * This function transforms a JS object `ObjMap< Promise < T > > ` into
709
- * a `Promise < ObjMap < T > > `
740
+ * This function transforms a JS object `ObjMap< ExecutionPartialResult < T > > ` into
741
+ * a `ExecutionPartialResult < T > `
710
742
*
711
743
* This is akin to bluebird's `Promise.props`, but implemented only using
712
744
* `Promise.all` so it will work with any implementation of ES6 promises.
713
745
*/
714
- function promiseForObject < T > (object: ObjMap< Promise < T > > ) : Promise < ObjMap < T > > {
746
+ function promiseForObject< T > (
747
+ object: ObjMap< ExecutionPartialResult < T > > ,
748
+ ) : ExecutionPartialResult < T > {
715
749
const keys = Object . keys ( object ) ;
716
750
const valuesAndPromises = keys . map ( name => object [ name ] ) ;
717
- return Promise . all ( valuesAndPromises ) . then ( values =>
718
- values . reduce ( ( resolvedObject , value , i ) => {
719
- resolvedObject [ keys [ i ] ] = value ;
720
- return resolvedObject ;
721
- } , Object . create ( null ) ) ,
722
- ) ;
751
+ return Promise . all ( valuesAndPromises )
752
+ . then ( values =>
753
+ values . reduce ( ( resolvedObject , value , i ) => {
754
+ resolvedObject [ keys [ i ] ] = value ;
755
+ return resolvedObject ;
756
+ } , Object . create ( null ) ) ,
757
+ )
758
+ . then ( valueMap => mergeEPRs ( valueMap ) ) ;
723
759
}
724
760
725
761
/**
@@ -741,13 +777,13 @@ function resolveField(
741
777
source: mixed,
742
778
fieldNodes: $ReadOnlyArray< FieldNode > ,
743
779
path: ResponsePath,
744
- ): mixed {
780
+ ): ExecutionPartialResult < mixed > | null {
745
781
const fieldNode = fieldNodes [ 0 ] ;
746
782
const fieldName = fieldNode . name . value ;
747
783
748
784
const fieldDef = getFieldDef ( exeContext . schema , parentType , fieldName ) ;
749
785
if ( ! fieldDef ) {
750
- return;
786
+ return null ;
751
787
}
752
788
753
789
const resolveFn = fieldDef . resolve || exeContext . fieldResolver ;
@@ -771,27 +807,14 @@ function resolveField(
771
807
info ,
772
808
) ;
773
809
774
- const completed = completeValueCatchingError (
810
+ return completeValueCatchingError (
775
811
exeContext ,
776
812
fieldDef . type ,
777
813
fieldNodes ,
778
814
info ,
779
815
path ,
780
816
result ,
781
817
) ;
782
- const promise = getPromise ( completed ) ;
783
- if ( promise ) {
784
- return promise . then ( r => {
785
- if ( r . errors && r . errors . length ) {
786
- exeContext . errors . push . apply ( exeContext . errors , r . errors ) ;
787
- }
788
- return r . data ;
789
- } ) ;
790
- }
791
- if ( completed . errors && completed . errors . length ) {
792
- exeContext . errors . push . apply ( exeContext . errors , completed . errors ) ;
793
- }
794
- return completed . data ;
795
818
}
796
819
797
820
export function buildResolveInfo(
0 commit comments