@@ -506,9 +506,11 @@ function executeFields(
506
506
path: ResponsePath | void,
507
507
fields: ObjMap< Array < FieldNode > > ,
508
508
) : MaybePromise < ObjMap < mixed > > {
509
+ const results = Object . create ( null ) ;
509
510
let containsPromise = false ;
510
511
511
- const finalResults = Object . keys ( fields ) . reduce ( ( results , responseName ) => {
512
+ for ( let i = 0 , keys = Object . keys ( fields ) ; i < keys . length ; ++ i ) {
513
+ const responseName = keys [ i ] ;
512
514
const fieldNodes = fields [ responseName ] ;
513
515
const fieldPath = addPath ( path , responseName ) ;
514
516
const result = resolveField (
@@ -518,26 +520,24 @@ function executeFields(
518
520
fieldNodes ,
519
521
fieldPath ,
520
522
) ;
521
- if ( result === undefined ) {
522
- return results ;
523
- }
524
- results [ responseName ] = result ;
525
- if ( ! containsPromise && isPromise ( result ) ) {
526
- containsPromise = true ;
523
+
524
+ if ( result !== undefined ) {
525
+ results [ responseName ] = result ;
526
+ if ( ! containsPromise && isPromise ( result ) ) {
527
+ containsPromise = true ;
528
+ }
527
529
}
528
- return results ;
529
- } , Object . create ( null ) ) ;
530
+ }
530
531
531
532
// If there are no promises, we can just return the object
532
533
if (!containsPromise) {
533
- return finalResults ;
534
+ return results ;
534
535
}
535
536
536
- // Otherwise, results is a map from field name to the result
537
- // of resolving that field, which is possibly a promise. Return
538
- // a promise that will return this same map, but with any
539
- // promises replaced with the values they resolved to.
540
- return promiseForObject(finalResults);
537
+ // Otherwise, results is a map from field name to the result of resolving that
538
+ // field, which is possibly a promise. Return a promise that will return this
539
+ // same map, but with any promises replaced with the values they resolved to.
540
+ return promiseForObject(results);
541
541
}
542
542
543
543
/**
@@ -792,87 +792,53 @@ function completeValueCatchingError(
792
792
path: ResponsePath,
793
793
result: mixed,
794
794
): MaybePromise< mixed > {
795
- // If the field type is non-nullable, then it is resolved without any
796
- // protection from errors, however it still properly locates the error.
797
- if ( isNonNullType ( returnType ) ) {
798
- return completeValueWithLocatedError (
799
- exeContext ,
800
- returnType ,
801
- fieldNodes ,
802
- info ,
803
- path ,
804
- result ,
805
- ) ;
806
- }
807
-
808
- // Otherwise, error protection is applied, logging the error and resolving
809
- // a null value for this field if one is encountered.
810
795
try {
811
- const completed = completeValueWithLocatedError (
812
- exeContext ,
813
- returnType ,
814
- fieldNodes ,
815
- info ,
816
- path ,
817
- result ,
818
- ) ;
796
+ let completed ;
797
+ if ( isPromise ( result ) ) {
798
+ completed = result . then ( resolved =>
799
+ completeValue ( exeContext , returnType , fieldNodes , info , path , resolved ) ,
800
+ ) ;
801
+ } else {
802
+ completed = completeValue (
803
+ exeContext ,
804
+ returnType ,
805
+ fieldNodes ,
806
+ info ,
807
+ path ,
808
+ result ,
809
+ ) ;
810
+ }
811
+
819
812
if ( isPromise ( completed ) ) {
820
- // If `completeValueWithLocatedError` returned a rejected promise, log
821
- // the rejection error and resolve to null.
822
813
// Note: we don't rely on a `catch` method, but we do expect "thenable"
823
814
// to take a second callback for the error case.
824
- return completed . then ( undefined , error => {
825
- exeContext . errors . push ( error ) ;
826
- return Promise . resolve ( null ) ;
827
- } ) ;
815
+ return completed . then ( undefined , error =>
816
+ handleFieldError ( error , fieldNodes , path , returnType , exeContext ) ,
817
+ ) ;
828
818
}
829
819
return completed ;
830
820
} catch ( error ) {
831
- // If `completeValueWithLocatedError` returned abruptly (threw an error),
832
- // log the error and return null.
833
- exeContext . errors . push ( error ) ;
834
- return null ;
821
+ return handleFieldError ( error , fieldNodes , path , returnType , exeContext ) ;
835
822
}
836
823
}
837
824
838
- // This is a small wrapper around completeValue which annotates errors with
839
- // location information.
840
- function completeValueWithLocatedError(
841
- exeContext: ExecutionContext,
842
- returnType: GraphQLOutputType,
843
- fieldNodes: $ReadOnlyArray< FieldNode > ,
844
- info: GraphQLResolveInfo,
845
- path: ResponsePath,
846
- result: mixed,
847
- ): MaybePromise< mixed > {
848
- try {
849
- const completed = completeValue (
850
- exeContext ,
851
- returnType ,
852
- fieldNodes ,
853
- info ,
854
- path ,
855
- result ,
856
- ) ;
857
- if ( isPromise ( completed ) ) {
858
- return completed . then ( undefined , error =>
859
- Promise . reject (
860
- locatedError (
861
- asErrorInstance ( error ) ,
862
- fieldNodes ,
863
- responsePathAsArray ( path ) ,
864
- ) ,
865
- ) ,
866
- ) ;
867
- }
868
- return completed ;
869
- } catch (error) {
870
- throw locatedError (
871
- asErrorInstance ( error ) ,
872
- fieldNodes ,
873
- responsePathAsArray ( path ) ,
874
- ) ;
825
+ function handleFieldError ( rawError , fieldNodes , path , returnType , exeContext ) {
826
+ const error = locatedError (
827
+ asErrorInstance ( rawError ) ,
828
+ fieldNodes ,
829
+ responsePathAsArray ( path ) ,
830
+ ) ;
831
+
832
+ // If the field type is non-nullable, then it is resolved without any
833
+ // protection from errors, however it still properly locates the error.
834
+ if ( isNonNullType ( returnType ) ) {
835
+ throw error ;
875
836
}
837
+
838
+ // Otherwise, error protection is applied, logging the error and resolving
839
+ // a null value for this field if one is encountered.
840
+ exeContext.errors.push(error);
841
+ return null;
876
842
}
877
843
878
844
/**
@@ -904,13 +870,6 @@ function completeValue(
904
870
path: ResponsePath,
905
871
result: mixed,
906
872
): MaybePromise< mixed > {
907
- // If result is a Promise, apply-lift over completeValue.
908
- if ( isPromise ( result ) ) {
909
- return result . then ( resolved =>
910
- completeValue ( exeContext , returnType , fieldNodes , info , path , resolved ) ,
911
- ) ;
912
- }
913
-
914
873
// If result is an Error, throw a located error.
915
874
if ( result instanceof Error ) {
916
875
throw result ;
0 commit comments