Skip to content

Commit 8650f39

Browse files
committed
use completePromiseCatchingErrors within executeField
1 parent 5f05205 commit 8650f39

File tree

3 files changed

+67
-51
lines changed

3 files changed

+67
-51
lines changed

src/execution/__tests__/nonnull-test.ts

+15-15
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,16 @@ describe('Execute: handles non-nullable types', () => {
259259
path: ['syncNest', 'syncNest', 'sync'],
260260
locations: [{ line: 6, column: 22 }],
261261
},
262+
{
263+
message: promiseError.message,
264+
path: ['syncNest', 'promise'],
265+
locations: [{ line: 5, column: 11 }],
266+
},
267+
{
268+
message: promiseError.message,
269+
path: ['syncNest', 'syncNest', 'promise'],
270+
locations: [{ line: 6, column: 27 }],
271+
},
262272
{
263273
message: syncError.message,
264274
path: ['syncNest', 'promiseNest', 'sync'],
@@ -274,21 +284,6 @@ describe('Execute: handles non-nullable types', () => {
274284
path: ['promiseNest', 'syncNest', 'sync'],
275285
locations: [{ line: 12, column: 22 }],
276286
},
277-
{
278-
message: promiseError.message,
279-
path: ['syncNest', 'promise'],
280-
locations: [{ line: 5, column: 11 }],
281-
},
282-
{
283-
message: promiseError.message,
284-
path: ['syncNest', 'syncNest', 'promise'],
285-
locations: [{ line: 6, column: 27 }],
286-
},
287-
{
288-
message: syncError.message,
289-
path: ['promiseNest', 'promiseNest', 'sync'],
290-
locations: [{ line: 13, column: 25 }],
291-
},
292287
{
293288
message: promiseError.message,
294289
path: ['syncNest', 'promiseNest', 'promise'],
@@ -304,6 +299,11 @@ describe('Execute: handles non-nullable types', () => {
304299
path: ['promiseNest', 'syncNest', 'promise'],
305300
locations: [{ line: 12, column: 27 }],
306301
},
302+
{
303+
message: syncError.message,
304+
path: ['promiseNest', 'promiseNest', 'sync'],
305+
locations: [{ line: 13, column: 25 }],
306+
},
307307
{
308308
message: promiseError.message,
309309
path: ['promiseNest', 'promiseNest', 'promise'],

src/execution/__tests__/stream-test.ts

+23-11
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,9 @@ describe('Execute: stream directive', () => {
10371037
],
10381038
},
10391039
],
1040+
hasNext: true,
1041+
},
1042+
{
10401043
hasNext: false,
10411044
},
10421045
]);
@@ -1060,19 +1063,25 @@ describe('Execute: stream directive', () => {
10601063
} /* c8 ignore stop */,
10611064
},
10621065
});
1063-
expectJSON(result).toDeepEqual({
1064-
errors: [
1065-
{
1066-
message:
1067-
'Cannot return null for non-nullable field NestedObject.nonNullScalarField.',
1068-
locations: [{ line: 4, column: 11 }],
1069-
path: ['nestedObject', 'nonNullScalarField'],
1066+
expectJSON(result).toDeepEqual([
1067+
{
1068+
errors: [
1069+
{
1070+
message:
1071+
'Cannot return null for non-nullable field NestedObject.nonNullScalarField.',
1072+
locations: [{ line: 4, column: 11 }],
1073+
path: ['nestedObject', 'nonNullScalarField'],
1074+
},
1075+
],
1076+
data: {
1077+
nestedObject: null,
10701078
},
1071-
],
1072-
data: {
1073-
nestedObject: null,
1079+
hasNext: true,
10741080
},
1075-
});
1081+
{
1082+
hasNext: false,
1083+
},
1084+
]);
10761085
});
10771086
it('Filters payloads that are nulled by a later synchronous error', async () => {
10781087
const document = parse(`
@@ -1213,6 +1222,9 @@ describe('Execute: stream directive', () => {
12131222
],
12141223
},
12151224
],
1225+
hasNext: true,
1226+
},
1227+
{
12161228
hasNext: false,
12171229
},
12181230
]);

src/execution/execute.ts

+29-25
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,7 @@ function executeField(
697697
);
698698

699699
// Get the resolve function, regardless of if its result is normal or abrupt (error).
700+
let result: PromiseOrValue<unknown>;
700701
try {
701702
// Build a JS object of arguments from the field.arguments AST, using the
702703
// variables scope to fulfill any variable references.
@@ -712,32 +713,35 @@ function executeField(
712713
// used to represent an authenticated user, or request-specific caches.
713714
const contextValue = exeContext.contextValue;
714715

715-
const result = resolveFn(source, args, contextValue, info);
716+
result = resolveFn(source, args, contextValue, info);
717+
} catch (rawError) {
718+
const error = locatedError(rawError, fieldNodes, pathToArray(path));
719+
const handledError = handleFieldError(error, returnType, errors);
720+
filterSubsequentPayloads(exeContext, path, asyncPayloadRecord);
721+
return handledError;
722+
}
716723

717-
let completed;
718-
if (isPromise(result)) {
719-
completed = result.then((resolved) =>
720-
completeValue(
721-
exeContext,
722-
returnType,
723-
fieldNodes,
724-
info,
725-
path,
726-
resolved,
727-
asyncPayloadRecord,
728-
),
729-
);
730-
} else {
731-
completed = completeValue(
732-
exeContext,
733-
returnType,
734-
fieldNodes,
735-
info,
736-
path,
737-
result,
738-
asyncPayloadRecord,
739-
);
740-
}
724+
if (isPromise(result)) {
725+
return completePromiseCatchingErrors(
726+
exeContext,
727+
returnType,
728+
fieldNodes,
729+
info,
730+
path,
731+
result,
732+
asyncPayloadRecord,
733+
);
734+
}
735+
try {
736+
const completed = completeValue(
737+
exeContext,
738+
returnType,
739+
fieldNodes,
740+
info,
741+
path,
742+
result,
743+
asyncPayloadRecord,
744+
);
741745

742746
if (isPromise(completed)) {
743747
// Note: we don't rely on a `catch` method, but we do expect "thenable"

0 commit comments

Comments
 (0)