@@ -915,6 +915,41 @@ function completeValue(
915
915
) ;
916
916
}
917
917
918
+ async function completePromiseCatchingErrors (
919
+ exeContext : ExecutionContext ,
920
+ returnType : GraphQLOutputType ,
921
+ fieldNodes : ReadonlyArray < FieldNode > ,
922
+ info : GraphQLResolveInfo ,
923
+ path : Path ,
924
+ result : Promise < unknown > ,
925
+ asyncPayloadRecord ?: AsyncPayloadRecord ,
926
+ ) : Promise < unknown > {
927
+ try {
928
+ const resolved = await result ;
929
+ let completed = completeValue (
930
+ exeContext ,
931
+ returnType ,
932
+ fieldNodes ,
933
+ info ,
934
+ path ,
935
+ resolved ,
936
+ asyncPayloadRecord ,
937
+ ) ;
938
+ if ( isPromise ( completed ) ) {
939
+ // see: https://github.com/tc39/proposal-faster-promise-adoption
940
+ // it is faster to await a promise prior to returning it from an async function
941
+ completed = await completed ;
942
+ }
943
+ return completed ;
944
+ } catch ( rawError ) {
945
+ const errors = asyncPayloadRecord ?. errors ?? exeContext . errors ;
946
+ const error = locatedError ( rawError , fieldNodes , pathToArray ( path ) ) ;
947
+ const handledError = handleFieldError ( error , returnType , errors ) ;
948
+ filterSubsequentPayloads ( exeContext , path , asyncPayloadRecord ) ;
949
+ return handledError ;
950
+ }
951
+ }
952
+
918
953
/**
919
954
* Returns an object containing the `@stream` arguments if a field should be
920
955
* streamed based on the experimental flag, stream directive present and
@@ -1878,21 +1913,19 @@ function executeStreamField(
1878
1913
exeContext,
1879
1914
} ) ;
1880
1915
let completedItem : PromiseOrValue < unknown > ;
1881
- try {
1916
+ if ( isPromise ( item ) ) {
1917
+ completedItem = completePromiseCatchingErrors (
1918
+ exeContext ,
1919
+ itemType ,
1920
+ fieldNodes ,
1921
+ info ,
1922
+ itemPath ,
1923
+ item ,
1924
+ asyncPayloadRecord ,
1925
+ ) ;
1926
+ } else {
1882
1927
try {
1883
- if ( isPromise ( item ) ) {
1884
- completedItem = item . then ( ( resolved ) =>
1885
- completeValue (
1886
- exeContext ,
1887
- itemType ,
1888
- fieldNodes ,
1889
- info ,
1890
- itemPath ,
1891
- resolved ,
1892
- asyncPayloadRecord ,
1893
- ) ,
1894
- ) ;
1895
- } else {
1928
+ try {
1896
1929
completedItem = completeValue (
1897
1930
exeContext ,
1898
1931
itemType ,
@@ -1902,40 +1935,40 @@ function executeStreamField(
1902
1935
item ,
1903
1936
asyncPayloadRecord ,
1904
1937
) ;
1905
- }
1906
1938
1907
- if ( isPromise ( completedItem ) ) {
1908
- // Note: we don't rely on a `catch` method, but we do expect "thenable"
1909
- // to take a second callback for the error case.
1910
- completedItem = completedItem . then ( undefined , ( rawError ) => {
1911
- const error = locatedError (
1912
- rawError ,
1913
- fieldNodes ,
1914
- pathToArray ( itemPath ) ,
1915
- ) ;
1916
- const handledError = handleFieldError (
1917
- error ,
1918
- itemType ,
1919
- asyncPayloadRecord . errors ,
1920
- ) ;
1921
- filterSubsequentPayloads ( exeContext , itemPath , asyncPayloadRecord ) ;
1922
- return handledError ;
1923
- } ) ;
1939
+ if ( isPromise ( completedItem ) ) {
1940
+ // Note: we don't rely on a `catch` method, but we do expect "thenable"
1941
+ // to take a second callback for the error case.
1942
+ completedItem = completedItem . then ( undefined , ( rawError ) => {
1943
+ const error = locatedError (
1944
+ rawError ,
1945
+ fieldNodes ,
1946
+ pathToArray ( itemPath ) ,
1947
+ ) ;
1948
+ const handledError = handleFieldError (
1949
+ error ,
1950
+ itemType ,
1951
+ asyncPayloadRecord . errors ,
1952
+ ) ;
1953
+ filterSubsequentPayloads ( exeContext , itemPath , asyncPayloadRecord ) ;
1954
+ return handledError ;
1955
+ } ) ;
1956
+ }
1957
+ } catch ( rawError ) {
1958
+ const error = locatedError ( rawError , fieldNodes , pathToArray ( itemPath ) ) ;
1959
+ completedItem = handleFieldError (
1960
+ error ,
1961
+ itemType ,
1962
+ asyncPayloadRecord . errors ,
1963
+ ) ;
1964
+ filterSubsequentPayloads ( exeContext , itemPath , asyncPayloadRecord ) ;
1924
1965
}
1925
- } catch ( rawError ) {
1926
- const error = locatedError ( rawError , fieldNodes , pathToArray ( itemPath ) ) ;
1927
- completedItem = handleFieldError (
1928
- error ,
1929
- itemType ,
1930
- asyncPayloadRecord . errors ,
1931
- ) ;
1932
- filterSubsequentPayloads ( exeContext , itemPath , asyncPayloadRecord ) ;
1966
+ } catch ( error ) {
1967
+ asyncPayloadRecord . errors . push ( error ) ;
1968
+ filterSubsequentPayloads ( exeContext , path , asyncPayloadRecord ) ;
1969
+ asyncPayloadRecord . addItems ( null ) ;
1970
+ return asyncPayloadRecord ;
1933
1971
}
1934
- } catch ( error ) {
1935
- asyncPayloadRecord . errors . push ( error ) ;
1936
- filterSubsequentPayloads ( exeContext , path , asyncPayloadRecord ) ;
1937
- asyncPayloadRecord . addItems ( null ) ;
1938
- return asyncPayloadRecord ;
1939
1972
}
1940
1973
1941
1974
let completedItems : PromiseOrValue < Array < unknown > | null > ;
0 commit comments