Skip to content

Commit 50501af

Browse files
committed
Revert "refactor buildResolveInfo into a lazy class (#4530)" (#4553)
Sadly, this would break existing users that resolver functions by spreading the info argument. BREAKING CHANGE: this PR changes `info.abortSignal` to `info.getAbortSignal()` => while `info` as a whole is not lazy, changing to a method allows us to maintain laziness at least with regards to the creation of the abort signal.
1 parent f6036a6 commit 50501af

File tree

7 files changed

+111
-305
lines changed

7 files changed

+111
-305
lines changed

src/execution/Executor.ts

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ import {
5151
collectFields,
5252
collectSubfields as _collectSubfields,
5353
} from './collectFields.js';
54-
import { ResolveInfo } from './ResolveInfo.js';
54+
import { buildResolveInfo } from './execute.js';
5555
import type { VariableValues } from './values.js';
5656
import { getArgumentValues } from './values.js';
5757

@@ -199,13 +199,13 @@ export interface FormattedExecutionResult<
199199
export class Executor {
200200
validatedExecutionArgs: ValidatedExecutionArgs;
201201
finished: boolean;
202-
resolverAbortControllers: Set<AbortController>;
202+
resolverAbortControllers: Map<Path, AbortController>;
203203
collectedErrors: CollectedErrors;
204204

205205
constructor(validatedExecutionArgs: ValidatedExecutionArgs) {
206206
this.validatedExecutionArgs = validatedExecutionArgs;
207207
this.finished = false;
208-
this.resolverAbortControllers = new Set();
208+
this.resolverAbortControllers = new Map();
209209
this.collectedErrors = new CollectedErrors();
210210
}
211211

@@ -306,10 +306,24 @@ export class Executor {
306306
const { resolverAbortControllers } = this;
307307
const finishReason =
308308
reason ?? new Error('Execution has already completed.');
309-
for (const abortController of resolverAbortControllers) {
309+
for (const abortController of resolverAbortControllers.values()) {
310310
abortController.abort(finishReason);
311311
}
312312
}
313+
314+
getAbortSignal(path: Path): AbortSignal {
315+
const resolverAbortSignal = this.resolverAbortControllers.get(path)?.signal;
316+
if (resolverAbortSignal !== undefined) {
317+
return resolverAbortSignal;
318+
}
319+
const abortController = new AbortController();
320+
this.resolverAbortControllers.set(path, abortController);
321+
if (this.finished) {
322+
abortController.abort(new Error('Execution has already completed.'));
323+
}
324+
return abortController.signal;
325+
}
326+
313327
/**
314328
* Given a completed execution context and data, build the `{ errors, data }`
315329
* response defined by the "Response" section of the GraphQL specification.
@@ -469,26 +483,13 @@ export class Executor {
469483
const returnType = fieldDef.type;
470484
const resolveFn = fieldDef.resolve ?? validatedExecutionArgs.fieldResolver;
471485

472-
const info = new ResolveInfo(
486+
const info = buildResolveInfo(
473487
validatedExecutionArgs,
474488
fieldDef,
475-
fieldDetailsList,
489+
toNodes(fieldDetailsList),
476490
parentType,
477491
path,
478-
() => {
479-
/* c8 ignore next 3 */
480-
if (this.finished) {
481-
throw new Error('Execution has already completed.');
482-
}
483-
const abortController = new AbortController();
484-
this.resolverAbortControllers.add(abortController);
485-
return {
486-
abortSignal: abortController.signal,
487-
unregister: () => {
488-
this.resolverAbortControllers.delete(abortController);
489-
},
490-
};
491-
},
492+
() => this.getAbortSignal(path),
492493
);
493494

494495
// Get the resolve function, regardless of if its result is normal or abrupt (error).
@@ -533,20 +534,20 @@ export class Executor {
533534
// to take a second callback for the error case.
534535
return completed.then(
535536
(resolved) => {
536-
info.unregisterAbortSignal();
537+
this.resolverAbortControllers.delete(path);
537538
return resolved;
538539
},
539540
(rawError: unknown) => {
540-
info.unregisterAbortSignal();
541+
this.resolverAbortControllers.delete(path);
541542
this.handleFieldError(rawError, returnType, fieldDetailsList, path);
542543
return null;
543544
},
544545
);
545546
}
546-
info.unregisterAbortSignal();
547+
this.resolverAbortControllers.delete(path);
547548
return completed;
548549
} catch (rawError) {
549-
info.unregisterAbortSignal();
550+
this.resolverAbortControllers.delete(path);
550551
this.handleFieldError(rawError, returnType, fieldDetailsList, path);
551552
return null;
552553
}
@@ -606,7 +607,7 @@ export class Executor {
606607
completeValue(
607608
returnType: GraphQLOutputType,
608609
fieldDetailsList: FieldDetailsList,
609-
info: ResolveInfo,
610+
info: GraphQLResolveInfo,
610611
path: Path,
611612
result: unknown,
612613
): PromiseOrValue<unknown> {
@@ -690,7 +691,7 @@ export class Executor {
690691
async completePromisedValue(
691692
returnType: GraphQLOutputType,
692693
fieldDetailsList: FieldDetailsList,
693-
info: ResolveInfo,
694+
info: GraphQLResolveInfo,
694695
path: Path,
695696
result: Promise<unknown>,
696697
isFieldValue?: boolean,
@@ -711,12 +712,12 @@ export class Executor {
711712
completed = await completed;
712713
}
713714
if (isFieldValue) {
714-
info.unregisterAbortSignal();
715+
this.resolverAbortControllers.delete(path);
715716
}
716717
return completed;
717718
} catch (rawError) {
718719
if (isFieldValue) {
719-
info.unregisterAbortSignal();
720+
this.resolverAbortControllers.delete(path);
720721
}
721722
this.handleFieldError(rawError, returnType, fieldDetailsList, path);
722723
return null;
@@ -730,7 +731,7 @@ export class Executor {
730731
async completeAsyncIterableValue(
731732
itemType: GraphQLOutputType,
732733
fieldDetailsList: FieldDetailsList,
733-
info: ResolveInfo,
734+
info: GraphQLResolveInfo,
734735
path: Path,
735736
items: AsyncIterable<unknown>,
736737
): Promise<ReadonlyArray<unknown>> {
@@ -806,7 +807,7 @@ export class Executor {
806807
completeListValue(
807808
returnType: GraphQLList<GraphQLOutputType>,
808809
fieldDetailsList: FieldDetailsList,
809-
info: ResolveInfo,
810+
info: GraphQLResolveInfo,
810811
path: Path,
811812
result: unknown,
812813
): PromiseOrValue<ReadonlyArray<unknown>> {
@@ -840,7 +841,7 @@ export class Executor {
840841
completeIterableValue(
841842
itemType: GraphQLOutputType,
842843
fieldDetailsList: FieldDetailsList,
843-
info: ResolveInfo,
844+
info: GraphQLResolveInfo,
844845
path: Path,
845846
items: Iterable<unknown>,
846847
): PromiseOrValue<ReadonlyArray<unknown>> {
@@ -905,7 +906,7 @@ export class Executor {
905906
completedResults: Array<unknown>,
906907
itemType: GraphQLOutputType,
907908
fieldDetailsList: FieldDetailsList,
908-
info: ResolveInfo,
909+
info: GraphQLResolveInfo,
909910
itemPath: Path,
910911
): boolean {
911912
try {
@@ -946,7 +947,7 @@ export class Executor {
946947
item: Promise<unknown>,
947948
itemType: GraphQLOutputType,
948949
fieldDetailsList: FieldDetailsList,
949-
info: ResolveInfo,
950+
info: GraphQLResolveInfo,
950951
itemPath: Path,
951952
): Promise<unknown> {
952953
try {

src/execution/ResolveInfo.ts

Lines changed: 0 additions & 131 deletions
This file was deleted.

0 commit comments

Comments
 (0)