@@ -2,6 +2,7 @@ import { assert, expect } from 'chai';
22import { describe , it } from 'mocha' ;
33
44import { expectJSON } from '../../__testUtils__/expectJSON.js' ;
5+ import { resolveOnNextTick } from '../../__testUtils__/resolveOnNextTick.js' ;
56
67import { inspect } from '../../jsutils/inspect.js' ;
78
@@ -580,6 +581,56 @@ describe('Execute: Handles basic execution tasks', () => {
580581 } ) ;
581582 } ) ;
582583
584+ it ( 'handles sync errors combined with rejections' , async ( ) => {
585+ let isAsyncResolverFinished = false ;
586+
587+ const schema = new GraphQLSchema ( {
588+ query : new GraphQLObjectType ( {
589+ name : 'Query' ,
590+ fields : {
591+ syncNullError : {
592+ type : new GraphQLNonNull ( GraphQLString ) ,
593+ resolve : ( ) => null ,
594+ } ,
595+ asyncNullError : {
596+ type : new GraphQLNonNull ( GraphQLString ) ,
597+ async resolve ( ) {
598+ await resolveOnNextTick ( ) ;
599+ await resolveOnNextTick ( ) ;
600+ await resolveOnNextTick ( ) ;
601+ isAsyncResolverFinished = true ;
602+ return null ;
603+ } ,
604+ } ,
605+ } ,
606+ } ) ,
607+ } ) ;
608+
609+ // Order is important here, as the promise has to be created before the synchronous error is thrown
610+ const document = parse ( `
611+ {
612+ asyncNullError
613+ syncNullError
614+ }
615+ ` ) ;
616+
617+ const result = execute ( { schema, document } ) ;
618+
619+ expect ( isAsyncResolverFinished ) . to . equal ( false ) ;
620+ expectJSON ( await result ) . toDeepEqual ( {
621+ data : null ,
622+ errors : [
623+ {
624+ message :
625+ 'Cannot return null for non-nullable field Query.syncNullError.' ,
626+ locations : [ { line : 4 , column : 9 } ] ,
627+ path : [ 'syncNullError' ] ,
628+ } ,
629+ ] ,
630+ } ) ;
631+ expect ( isAsyncResolverFinished ) . to . equal ( true ) ;
632+ } ) ;
633+
583634 it ( 'Full response path is included for non-nullable fields' , ( ) => {
584635 const A : GraphQLObjectType = new GraphQLObjectType ( {
585636 name : 'A' ,
0 commit comments