@@ -506,9 +506,11 @@ function executeFields(
506506 path: ResponsePath | void,
507507 fields: ObjMap< Array < FieldNode > > ,
508508) : MaybePromise < ObjMap < mixed > > {
509+ const results = Object . create ( null ) ;
509510 let containsPromise = false ;
510511
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 ] ;
512514 const fieldNodes = fields [ responseName ] ;
513515 const fieldPath = addPath ( path , responseName ) ;
514516 const result = resolveField (
@@ -518,26 +520,24 @@ function executeFields(
518520 fieldNodes ,
519521 fieldPath ,
520522 ) ;
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+ }
527529 }
528- return results ;
529- } , Object . create ( null ) ) ;
530+ }
530531
531532 // If there are no promises, we can just return the object
532533 if (!containsPromise) {
533- return finalResults ;
534+ return results ;
534535 }
535536
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);
541541}
542542
543543/**
@@ -792,87 +792,53 @@ function completeValueCatchingError(
792792 path: ResponsePath,
793793 result: mixed,
794794): 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.
810795 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+
819812 if ( isPromise ( completed ) ) {
820- // If `completeValueWithLocatedError` returned a rejected promise, log
821- // the rejection error and resolve to null.
822813 // Note: we don't rely on a `catch` method, but we do expect "thenable"
823814 // 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+ ) ;
828818 }
829819 return completed ;
830820 } 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 ) ;
835822 }
836823}
837824
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 ;
875836 }
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;
876842}
877843
878844/**
@@ -904,13 +870,6 @@ function completeValue(
904870 path: ResponsePath,
905871 result: mixed,
906872): 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-
914873 // If result is an Error, throw a located error.
915874 if ( result instanceof Error ) {
916875 throw result ;
0 commit comments