Skip to content

Commit 87c1bc3

Browse files
Yoguleebyron
authored andcommitted
getTypeMap() does not include input types used in directives (#1189)
* Add failing test for directive's input types in getTypeMap() * Include directive argument types in getTypeMap() * Fix lint. Convert to reducer to solve flow issue.
1 parent f082e24 commit 87c1bc3

File tree

2 files changed

+72
-5
lines changed

2 files changed

+72
-5
lines changed

src/type/__tests__/schema-test.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ import {
1010
GraphQLInterfaceType,
1111
GraphQLObjectType,
1212
GraphQLString,
13+
GraphQLInputObjectType,
14+
GraphQLDirective,
1315
} from '../';
1416

1517
import { describe, it } from 'mocha';
1618
import { expect } from 'chai';
19+
import { GraphQLList } from '../wrappers';
1720

1821
const InterfaceType = new GraphQLInterfaceType({
1922
name: 'Interface',
@@ -26,6 +29,37 @@ const ImplementingType = new GraphQLObjectType({
2629
fields: { fieldName: { type: GraphQLString, resolve: () => '' } },
2730
});
2831

32+
const DirectiveInputType = new GraphQLInputObjectType({
33+
name: 'DirInput',
34+
fields: {
35+
field: {
36+
type: GraphQLString,
37+
},
38+
},
39+
});
40+
41+
const WrappedDirectiveInputType = new GraphQLInputObjectType({
42+
name: 'WrappedDirInput',
43+
fields: {
44+
field: {
45+
type: GraphQLString,
46+
},
47+
},
48+
});
49+
50+
const Directive = new GraphQLDirective({
51+
name: 'dir',
52+
locations: ['OBJECT'],
53+
args: {
54+
arg: {
55+
type: DirectiveInputType,
56+
},
57+
argList: {
58+
type: new GraphQLList(WrappedDirectiveInputType),
59+
},
60+
},
61+
});
62+
2963
const Schema = new GraphQLSchema({
3064
query: new GraphQLObjectType({
3165
name: 'Query',
@@ -38,6 +72,7 @@ const Schema = new GraphQLSchema({
3872
},
3973
},
4074
}),
75+
directives: [Directive],
4176
});
4277

4378
describe('Type System: Schema', () => {
@@ -53,4 +88,11 @@ describe('Type System: Schema', () => {
5388
);
5489
});
5590
});
91+
92+
describe('Type Map', () => {
93+
it('includes input types only used in directives', () => {
94+
expect(Schema.getTypeMap()).to.include.key('DirInput');
95+
expect(Schema.getTypeMap()).to.include.key('WrappedDirInput');
96+
});
97+
});
5698
});

src/type/schema.js

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ import type {
2222
GraphQLInterfaceType,
2323
} from './definition';
2424
import type { SchemaDefinitionNode } from '../language/ast';
25-
import { GraphQLDirective, specifiedDirectives } from './directives';
25+
import {
26+
GraphQLDirective,
27+
isDirective,
28+
specifiedDirectives,
29+
} from './directives';
2630
import type { GraphQLError } from '../error/GraphQLError';
2731
import { __Schema } from './introspection';
2832
import find from '../jsutils/find';
@@ -121,10 +125,17 @@ export class GraphQLSchema {
121125
initialTypes = initialTypes.concat(types);
122126
}
123127

124-
this._typeMap = initialTypes.reduce(
125-
typeMapReducer,
126-
(Object.create(null): TypeMap),
127-
);
128+
// Keep track of all types referenced within the schema.
129+
let typeMap: TypeMap = Object.create(null);
130+
131+
// First by deeply visiting all initial types.
132+
typeMap = initialTypes.reduce(typeMapReducer, typeMap);
133+
134+
// Then by deeply visiting all directive types.
135+
typeMap = this._directives.reduce(typeMapDirectiveReducer, typeMap);
136+
137+
// Storing the resulting map for reference by the schema.
138+
this._typeMap = typeMap;
128139

129140
// Keep track of all implementations by interface name.
130141
this._implementations = Object.create(null);
@@ -269,3 +280,17 @@ function typeMapReducer(map: TypeMap, type: ?GraphQLType): TypeMap {
269280

270281
return reducedMap;
271282
}
283+
284+
function typeMapDirectiveReducer(
285+
map: TypeMap,
286+
directive: ?GraphQLDirective,
287+
): TypeMap {
288+
// Directives are not validated until validateSchema() is called.
289+
if (!isDirective(directive)) {
290+
return map;
291+
}
292+
return directive.args.reduce(
293+
(_map, arg) => typeMapReducer(_map, arg.type),
294+
map,
295+
);
296+
}

0 commit comments

Comments
 (0)