Skip to content

Commit 06ecf38

Browse files
committed
Merge pull request #119 from graphql/arity
[RFC] Expose more information to field resolver functions.
2 parents 2314da3 + d919089 commit 06ecf38

File tree

4 files changed

+63
-72
lines changed

4 files changed

+63
-72
lines changed

src/execution/execute.js

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -461,47 +461,55 @@ function resolveField(
461461
fieldASTs: Array<Field>
462462
): any {
463463
var fieldAST = fieldASTs[0];
464+
var fieldName = fieldAST.name.value;
464465

465-
var fieldDef = getFieldDef(exeContext.schema, parentType, fieldAST);
466+
var fieldDef = getFieldDef(exeContext.schema, parentType, fieldName);
466467
if (!fieldDef) {
467468
return;
468469
}
469470

470-
var fieldType = fieldDef.type;
471+
var returnType = fieldDef.type;
471472
var resolveFn = fieldDef.resolve || defaultResolveFn;
472473

473474
// Build a JS object of arguments from the field.arguments AST, using the
474475
// variables scope to fulfill any variable references.
475476
// TODO: find a way to memoize, in case this field is within a List type.
476-
var args = fieldDef.args ?
477-
getArgumentValues(fieldDef.args, fieldAST.arguments, exeContext.variables) :
478-
null;
477+
var args = getArgumentValues(
478+
fieldDef.args,
479+
fieldAST.arguments,
480+
exeContext.variables
481+
);
482+
483+
// The resolve function's optional third argument is a collection of
484+
// information about the current execution state.
485+
var info = {
486+
fieldName,
487+
fieldASTs,
488+
returnType,
489+
parentType,
490+
schema: exeContext.schema,
491+
fragments: exeContext.fragments,
492+
rootValue: exeContext.rootValue,
493+
operation: exeContext.operation,
494+
variables: exeContext.variables,
495+
};
479496

480497
// If an error occurs while calling the field `resolve` function, ensure that
481498
// it is wrapped as a GraphQLError with locations. Log this error and return
482499
// null if allowed, otherwise throw the error so the parent field can handle
483500
// it.
484501
try {
485-
var result = resolveFn(
486-
source,
487-
args,
488-
exeContext.rootValue,
489-
// TODO: provide all fieldASTs, not just the first field
490-
fieldAST,
491-
fieldType,
492-
parentType,
493-
exeContext.schema
494-
);
502+
var result = resolveFn(source, args, info);
495503
} catch (error) {
496504
var reportedError = locatedError(error, fieldASTs);
497-
if (fieldType instanceof GraphQLNonNull) {
505+
if (returnType instanceof GraphQLNonNull) {
498506
throw reportedError;
499507
}
500508
exeContext.errors.push(reportedError);
501509
return null;
502510
}
503511

504-
return completeValueCatchingError(exeContext, fieldType, fieldASTs, result);
512+
return completeValueCatchingError(exeContext, returnType, fieldASTs, result);
505513
}
506514

507515
function completeValueCatchingError(
@@ -660,8 +668,8 @@ function completeValue(
660668
* and returns it as the result, or if it's a function, returns the result
661669
* of calling that function.
662670
*/
663-
function defaultResolveFn(source, args, root, fieldAST) {
664-
var property = source[fieldAST.name.value];
671+
function defaultResolveFn(source, args, { fieldName }) {
672+
var property = source[fieldName];
665673
return typeof property === 'function' ? property.call(source) : property;
666674
}
667675

@@ -685,17 +693,16 @@ function isThenable(value: any): boolean {
685693
function getFieldDef(
686694
schema: GraphQLSchema,
687695
parentType: GraphQLObjectType,
688-
fieldAST: Field
696+
fieldName: string
689697
): ?GraphQLFieldDefinition {
690-
var name = fieldAST.name.value;
691-
if (name === SchemaMetaFieldDef.name &&
698+
if (fieldName === SchemaMetaFieldDef.name &&
692699
schema.getQueryType() === parentType) {
693700
return SchemaMetaFieldDef;
694-
} else if (name === TypeMetaFieldDef.name &&
701+
} else if (fieldName === TypeMetaFieldDef.name &&
695702
schema.getQueryType() === parentType) {
696703
return TypeMetaFieldDef;
697-
} else if (name === TypeNameMetaFieldDef.name) {
704+
} else if (fieldName === TypeNameMetaFieldDef.name) {
698705
return TypeNameMetaFieldDef;
699706
}
700-
return parentType.getFields()[name];
707+
return parentType.getFields()[fieldName];
701708
}

src/execution/values.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@ export function getVariableValues(
5252
* definitions and list of argument AST nodes.
5353
*/
5454
export function getArgumentValues(
55-
argDefs: Array<GraphQLArgument>,
55+
argDefs: ?Array<GraphQLArgument>,
5656
argASTs: ?Array<Argument>,
5757
variables: { [key: string]: any }
5858
): { [key: string]: any } {
59-
if (!argASTs) {
59+
if (!argDefs || !argASTs) {
6060
return {};
6161
}
6262
var argASTMap = keyMap(argASTs, arg => arg.name.value);

src/type/definition.js

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010

1111
import invariant from '../jsutils/invariant';
1212
import { ENUM } from '../language/kinds';
13-
import type { Value } from '../language/ast';
13+
import type {
14+
OperationDefinition,
15+
Field,
16+
FragmentDefinition,
17+
Value,
18+
} from '../language/ast';
1419
import type { GraphQLSchema } from './schema';
1520

1621

@@ -350,18 +355,28 @@ type GraphQLInterfacesThunk = () => Array<GraphQLInterfaceType>;
350355

351356
type GraphQLFieldConfigMapThunk = () => GraphQLFieldConfigMap;
352357

358+
export type GraphQLFieldResolveFn = (
359+
source?: any,
360+
args?: {[argName: string]: any},
361+
info?: GraphQLFieldExeInfo
362+
) => any
363+
364+
export type GraphQLFieldExeInfo = {
365+
fieldName: string,
366+
fieldASTs: Array<Field>,
367+
returnType: GraphQLOutputType,
368+
parentType: GraphQLCompositeType,
369+
schema: GraphQLSchema,
370+
fragments: { [fragmentName: string]: FragmentDefinition },
371+
rootValue: any,
372+
operation: OperationDefinition,
373+
variables: { [variableName: string]: any },
374+
}
375+
353376
export type GraphQLFieldConfig = {
354377
type: GraphQLOutputType;
355378
args?: GraphQLFieldConfigArgumentMap;
356-
resolve?: (
357-
source?: any,
358-
args?: ?{[argName: string]: any},
359-
context?: any,
360-
fieldAST?: any,
361-
fieldType?: any,
362-
parentType?: any,
363-
schema?: GraphQLSchema
364-
) => any;
379+
resolve?: GraphQLFieldResolveFn;
365380
deprecationReason?: string;
366381
description?: ?string;
367382
}
@@ -384,15 +399,7 @@ export type GraphQLFieldDefinition = {
384399
description: ?string;
385400
type: GraphQLOutputType;
386401
args: Array<GraphQLArgument>;
387-
resolve?: (
388-
source?: any,
389-
args?: ?{[argName: string]: any},
390-
context?: any,
391-
fieldAST?: any,
392-
fieldType?: any,
393-
parentType?: any,
394-
schema?: GraphQLSchema
395-
) => any;
402+
resolve?: GraphQLFieldResolveFn;
396403
deprecationReason?: ?string;
397404
}
398405

src/type/introspection.js

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -288,15 +288,7 @@ export var SchemaMetaFieldDef: GraphQLFieldDefinition = {
288288
type: new GraphQLNonNull(__Schema),
289289
description: 'Access the current type schema of this server.',
290290
args: [],
291-
resolve: (
292-
source,
293-
args,
294-
root,
295-
fieldAST,
296-
fieldType,
297-
parentType,
298-
schema
299-
) => schema
291+
resolve: (source, args, { schema }) => schema
300292
};
301293

302294
export var TypeMetaFieldDef: GraphQLFieldDefinition = {
@@ -306,28 +298,13 @@ export var TypeMetaFieldDef: GraphQLFieldDefinition = {
306298
args: [
307299
{ name: 'name', type: new GraphQLNonNull(GraphQLString) }
308300
],
309-
resolve: (
310-
source,
311-
{ name },
312-
root,
313-
fieldAST,
314-
fieldType,
315-
parentType,
316-
schema
317-
) => schema.getType(name)
301+
resolve: (source, { name }, { schema }) => schema.getType(name)
318302
};
319303

320304
export var TypeNameMetaFieldDef: GraphQLFieldDefinition = {
321305
name: '__typename',
322306
type: new GraphQLNonNull(GraphQLString),
323307
description: 'The name of the current Object type at runtime.',
324308
args: [],
325-
resolve: (
326-
source,
327-
args,
328-
root,
329-
fieldAST,
330-
fieldType,
331-
parentType
332-
) => parentType.name
309+
resolve: (source, args, { parentType }) => parentType.name
333310
};

0 commit comments

Comments
 (0)