Skip to content

Commit 88c48c9

Browse files
committed
do not use undefined for empty errors array
1 parent 02d302e commit 88c48c9

File tree

4 files changed

+52
-36
lines changed

4 files changed

+52
-36
lines changed

src/execution/IncrementalPublisher.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import {
3232
export function buildIncrementalResponse(
3333
context: IncrementalPublisherContext,
3434
result: ObjMap<unknown>,
35-
errors: ReadonlyArray<GraphQLError> | undefined,
35+
errors: ReadonlyArray<GraphQLError>,
3636
incrementalDataRecords: ReadonlyArray<IncrementalDataRecord>,
3737
): ExperimentalIncrementalExecutionResults {
3838
const incrementalPublisher = new IncrementalPublisher(context);
@@ -73,7 +73,7 @@ class IncrementalPublisher {
7373

7474
buildResponse(
7575
data: ObjMap<unknown>,
76-
errors: ReadonlyArray<GraphQLError> | undefined,
76+
errors: ReadonlyArray<GraphQLError>,
7777
incrementalDataRecords: ReadonlyArray<IncrementalDataRecord>,
7878
): ExperimentalIncrementalExecutionResults {
7979
const newRootNodes = this._incrementalGraph.getNewRootNodes(
@@ -82,10 +82,9 @@ class IncrementalPublisher {
8282

8383
const pending = this._toPendingResults(newRootNodes);
8484

85-
const initialResult: InitialIncrementalExecutionResult =
86-
errors === undefined
87-
? { data, pending, hasNext: true }
88-
: { errors, data, pending, hasNext: true };
85+
const initialResult: InitialIncrementalExecutionResult = errors.length
86+
? { errors, data, pending, hasNext: true }
87+
: { data, pending, hasNext: true };
8988

9089
return {
9190
initialResult,

src/execution/__tests__/nonnull-test.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,12 +544,22 @@ describe('Execute: handles non-nullable types', () => {
544544
expectJSON(result).toDeepEqual({
545545
data: null,
546546
errors: [
547-
// does not include syncNullError because result returns prior to it being added
548547
{
549548
message: 'promiseNonNull',
550549
path: ['promiseNonNull'],
551550
locations: [{ line: 3, column: 11 }],
552551
},
552+
{
553+
message: 'promise',
554+
path: [
555+
'promiseNest',
556+
'promiseNest',
557+
'promiseNest',
558+
'promiseNest',
559+
'promise',
560+
],
561+
locations: [{ line: 4, column: 67 }],
562+
},
553563
],
554564
});
555565
});
@@ -581,6 +591,17 @@ describe('Execute: handles non-nullable types', () => {
581591
path: ['promiseNonNull'],
582592
locations: [{ line: 3, column: 11 }],
583593
},
594+
{
595+
message: 'Completed, aborting.',
596+
path: [
597+
'promiseNest',
598+
'promiseNest',
599+
'promiseNest',
600+
'promiseNest',
601+
'promiseNest',
602+
],
603+
locations: [{ line: 4, column: 67 }],
604+
},
584605
],
585606
});
586607
const counterAtExecutionEnd = counter;

src/execution/execute.ts

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -168,15 +168,15 @@ export interface ValidatedExecutionArgs {
168168

169169
export interface ExecutionContext {
170170
validatedExecutionArgs: ValidatedExecutionArgs;
171-
errors: Array<GraphQLError> | undefined;
171+
errors: Array<GraphQLError>;
172172
abortSignalListener: AbortSignalListener | undefined;
173173
completed: boolean;
174174
cancellableStreams: Set<CancellableStreamRecord> | undefined;
175175
errorPropagation: boolean;
176176
}
177177

178178
interface IncrementalContext {
179-
errors: Array<GraphQLError> | undefined;
179+
errors: Array<GraphQLError>;
180180
completed: boolean;
181181
deferUsageSet?: DeferUsageSet | undefined;
182182
}
@@ -337,7 +337,7 @@ export function experimentalExecuteQueryOrMutationOrSubscriptionEvent(
337337
const abortSignal = validatedExecutionArgs.abortSignal;
338338
const exeContext: ExecutionContext = {
339339
validatedExecutionArgs,
340-
errors: undefined,
340+
errors: [],
341341
abortSignalListener: abortSignal
342342
? new AbortSignalListener(abortSignal)
343343
: undefined,
@@ -394,7 +394,7 @@ export function experimentalExecuteQueryOrMutationOrSubscriptionEvent(
394394
exeContext.abortSignalListener?.disconnect();
395395
return {
396396
data: null,
397-
errors: withError(exeContext.errors, error as GraphQLError),
397+
errors: addError(exeContext.errors, error as GraphQLError),
398398
};
399399
},
400400
);
@@ -406,15 +406,16 @@ export function experimentalExecuteQueryOrMutationOrSubscriptionEvent(
406406
// TODO: add test case for synchronous null bubbling to root with cancellation
407407
/* c8 ignore next */
408408
exeContext.abortSignalListener?.disconnect();
409-
return { data: null, errors: withError(exeContext.errors, error) };
409+
return { data: null, errors: addError(exeContext.errors, error) };
410410
}
411411
}
412412

413-
function withError(
414-
errors: Array<GraphQLError> | undefined,
413+
function addError(
414+
errors: Array<GraphQLError>,
415415
error: GraphQLError,
416416
): ReadonlyArray<GraphQLError> {
417-
return errors === undefined ? [error] : [...errors, error];
417+
errors.push(error);
418+
return errors;
418419
}
419420

420421
function buildDataResponse(
@@ -425,7 +426,7 @@ function buildDataResponse(
425426
const errors = exeContext.errors;
426427
if (incrementalDataRecords === undefined) {
427428
exeContext.abortSignalListener?.disconnect();
428-
return errors !== undefined ? { errors, data } : { data };
429+
return errors.length ? { errors, data } : { data };
429430
}
430431

431432
return buildIncrementalResponse(
@@ -1005,12 +1006,7 @@ function handleFieldError(
10051006
// Otherwise, error protection is applied, logging the error and resolving
10061007
// a null value for this field if one is encountered.
10071008
const context = incrementalContext ?? exeContext;
1008-
let errors = context.errors;
1009-
if (errors === undefined) {
1010-
errors = [];
1011-
context.errors = errors;
1012-
}
1013-
errors.push(error);
1009+
addError(context.errors, error);
10141010
}
10151011

10161012
/**
@@ -2397,7 +2393,7 @@ function collectExecutionGroups(
23972393
path,
23982394
groupedFieldSet,
23992395
{
2400-
errors: undefined,
2396+
errors: [],
24012397
completed: false,
24022398
deferUsageSet,
24032399
},
@@ -2462,7 +2458,7 @@ function executeExecutionGroup(
24622458
return {
24632459
pendingExecutionGroup,
24642460
path: pathToArray(path),
2465-
errors: withError(incrementalContext.errors, error),
2461+
errors: addError(incrementalContext.errors, error),
24662462
};
24672463
}
24682464

@@ -2482,7 +2478,7 @@ function executeExecutionGroup(
24822478
return {
24832479
pendingExecutionGroup,
24842480
path: pathToArray(path),
2485-
errors: withError(incrementalContext.errors, error as GraphQLError),
2481+
errors: addError(incrementalContext.errors, error as GraphQLError),
24862482
};
24872483
},
24882484
);
@@ -2498,7 +2494,7 @@ function executeExecutionGroup(
24982494
}
24992495

25002496
function buildCompletedExecutionGroup(
2501-
errors: ReadonlyArray<GraphQLError> | undefined,
2497+
errors: ReadonlyArray<GraphQLError>,
25022498
pendingExecutionGroup: PendingExecutionGroup,
25032499
path: Path | undefined,
25042500
result: GraphQLWrappedResult<ObjMap<unknown>>,
@@ -2507,7 +2503,7 @@ function buildCompletedExecutionGroup(
25072503
return {
25082504
pendingExecutionGroup,
25092505
path: pathToArray(path),
2510-
result: errors === undefined ? { data } : { data, errors },
2506+
result: errors.length ? { errors, data } : { data },
25112507
incrementalDataRecords,
25122508
};
25132509
}
@@ -2543,7 +2539,7 @@ function buildSyncStreamItemQueue(
25432539
initialPath,
25442540
initialItem,
25452541
exeContext,
2546-
{ errors: undefined, completed: false },
2542+
{ errors: [], completed: false },
25472543
fieldDetailsList,
25482544
info,
25492545
itemType,
@@ -2560,7 +2556,7 @@ function buildSyncStreamItemQueue(
25602556
/* c8 ignore next 6 */
25612557
if (currentStreamItem instanceof BoxedPromiseOrValue) {
25622558
const result = currentStreamItem.value;
2563-
if (!isPromise(result) && result.errors !== undefined) {
2559+
if (!isPromise(result) && result.item === undefined) {
25642560
break;
25652561
}
25662562
}
@@ -2574,7 +2570,7 @@ function buildSyncStreamItemQueue(
25742570
itemPath,
25752571
value,
25762572
exeContext,
2577-
{ errors: undefined, completed: false },
2573+
{ errors: [], completed: false },
25782574
fieldDetailsList,
25792575
info,
25802576
itemType,
@@ -2666,7 +2662,7 @@ async function getNextAsyncStreamItemResult(
26662662
itemPath,
26672663
iteration.value,
26682664
exeContext,
2669-
{ errors: undefined, completed: false },
2665+
{ errors: [], completed: false },
26702666
fieldDetailsList,
26712667
info,
26722668
itemType,
@@ -2724,7 +2720,7 @@ function completeStreamItem(
27242720
(error: unknown) => {
27252721
incrementalContext.completed = true;
27262722
return {
2727-
errors: withError(incrementalContext.errors, error as GraphQLError),
2723+
errors: addError(incrementalContext.errors, error as GraphQLError),
27282724
};
27292725
},
27302726
);
@@ -2757,7 +2753,7 @@ function completeStreamItem(
27572753
} catch (error) {
27582754
incrementalContext.completed = true;
27592755
return {
2760-
errors: withError(incrementalContext.errors, error),
2756+
errors: addError(incrementalContext.errors, error),
27612757
};
27622758
}
27632759

@@ -2782,7 +2778,7 @@ function completeStreamItem(
27822778
(error: unknown) => {
27832779
incrementalContext.completed = true;
27842780
return {
2785-
errors: withError(incrementalContext.errors, error as GraphQLError),
2781+
errors: addError(incrementalContext.errors, error as GraphQLError),
27862782
};
27872783
},
27882784
);
@@ -2793,7 +2789,7 @@ function completeStreamItem(
27932789
}
27942790

27952791
function buildStreamItemResult(
2796-
errors: ReadonlyArray<GraphQLError> | undefined,
2792+
errors: ReadonlyArray<GraphQLError>,
27972793
result: GraphQLWrappedResult<unknown>,
27982794
): StreamItemResult {
27992795
const { rawResult: item, incrementalDataRecords } = result;

src/execution/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,8 @@ export function isDeferredFragmentRecord(
247247

248248
export interface StreamItemResult {
249249
item?: unknown;
250+
errors?: ReadonlyArray<GraphQLError>;
250251
incrementalDataRecords?: ReadonlyArray<IncrementalDataRecord> | undefined;
251-
errors?: ReadonlyArray<GraphQLError> | undefined;
252252
}
253253

254254
export type StreamItemRecord = ThunkIncrementalResult<StreamItemResult>;

0 commit comments

Comments
 (0)