Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit afc6b7c

Browse files
committed
Remove excessive cache inside buildSchema and extendSchema
1 parent f57a01e commit afc6b7c

File tree

2 files changed

+123
-132
lines changed

2 files changed

+123
-132
lines changed

src/utilities/buildASTSchema.js

Lines changed: 52 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -131,31 +131,35 @@ export function buildASTSchema(
131131
}
132132

133133
let schemaDef: ?SchemaDefinitionNode;
134-
const nodeMap: ObjMap<TypeDefinitionNode> = Object.create(null);
134+
const typeDefs: Array<TypeDefinitionNode> = [];
135135
const directiveDefs: Array<DirectiveDefinitionNode> = [];
136136

137137
for (const def of documentAST.definitions) {
138138
if (def.kind === Kind.SCHEMA_DEFINITION) {
139139
schemaDef = def;
140140
} else if (isTypeDefinitionNode(def)) {
141-
nodeMap[def.name.value] = def;
141+
typeDefs.push(def);
142142
} else if (def.kind === Kind.DIRECTIVE_DEFINITION) {
143143
directiveDefs.push(def);
144144
}
145145
}
146146

147+
const astBuilder = new ASTDefinitionBuilder(options, typeName => {
148+
const type = typeMap[typeName];
149+
invariant(type, `Type "${typeName}" not found in document.`);
150+
return type;
151+
});
152+
153+
const typeMap = keyByNameNode(typeDefs, node => astBuilder.buildType(node));
154+
147155
const operationTypes = schemaDef
148156
? getOperationTypes(schemaDef)
149157
: {
150-
query: nodeMap.Query,
151-
mutation: nodeMap.Mutation,
152-
subscription: nodeMap.Subscription,
158+
query: 'Query',
159+
mutation: 'Mutation',
160+
subscription: 'Subscription',
153161
};
154162

155-
const astBuilder = new ASTDefinitionBuilder(nodeMap, options, typeName => {
156-
throw new Error(`Type "${typeName}" not found in document.`);
157-
});
158-
159163
const directives = directiveDefs.map(def => astBuilder.buildDirective(def));
160164

161165
// If specified directives were not explicitly declared, add them.
@@ -171,20 +175,19 @@ export function buildASTSchema(
171175
directives.push(GraphQLDeprecatedDirective);
172176
}
173177

174-
// Note: While this could make early assertions to get the correctly
175-
// typed values below, that would throw immediately while type system
176-
// validation with validateSchema() will produce more actionable results.
177178
return new GraphQLSchema({
178-
query: operationTypes.query
179-
? (astBuilder.buildType(operationTypes.query): any)
180-
: null,
179+
// Note: While this could make early assertions to get the correctly
180+
// typed values below, that would throw immediately while type system
181+
// validation with validateSchema() will produce more actionable results.
182+
query: operationTypes.query ? (typeMap[operationTypes.query]: any) : null,
181183
mutation: operationTypes.mutation
182-
? (astBuilder.buildType(operationTypes.mutation): any)
184+
? (typeMap[operationTypes.mutation]: any)
183185
: null,
184186
subscription: operationTypes.subscription
185-
? (astBuilder.buildType(operationTypes.subscription): any)
187+
? (typeMap[operationTypes.subscription]: any)
186188
: null,
187-
types: objectValues(nodeMap).map(node => astBuilder.buildType(node)),
189+
190+
types: objectValues(typeMap),
188191
directives,
189192
astNode: schemaDef,
190193
assumeValid: options && options.assumeValid,
@@ -194,62 +197,44 @@ export function buildASTSchema(
194197
function getOperationTypes(schema: SchemaDefinitionNode) {
195198
const opTypes = {};
196199
for (const operationType of schema.operationTypes) {
197-
opTypes[operationType.operation] = operationType.type;
200+
opTypes[operationType.operation] = operationType.type.name.value;
198201
}
199202
return opTypes;
200203
}
201204
}
202205

203-
type TypeDefinitionsMap = ObjMap<TypeDefinitionNode>;
204206
type TypeResolver = (typeName: string) => GraphQLNamedType;
205207

208+
const stdTypeMap = keyMap(
209+
specifiedScalarTypes.concat(introspectionTypes),
210+
type => type.name,
211+
);
212+
206213
export class ASTDefinitionBuilder {
207-
_typeDefinitionsMap: TypeDefinitionsMap;
208214
_options: ?BuildSchemaOptions;
209215
_resolveType: TypeResolver;
210-
_cache: ObjMap<GraphQLNamedType>;
211216

212-
constructor(
213-
typeDefinitionsMap: TypeDefinitionsMap,
214-
options: ?BuildSchemaOptions,
215-
resolveType: TypeResolver,
216-
) {
217-
this._typeDefinitionsMap = typeDefinitionsMap;
217+
constructor(options: ?BuildSchemaOptions, resolveType: TypeResolver) {
218218
this._options = options;
219219
this._resolveType = resolveType;
220-
// Initialize to the GraphQL built in scalars and introspection types.
221-
this._cache = keyMap(
222-
specifiedScalarTypes.concat(introspectionTypes),
223-
type => type.name,
224-
);
225220
}
226221

227-
buildType(node: NamedTypeNode | TypeDefinitionNode): GraphQLNamedType {
228-
const typeName = node.name.value;
229-
if (!this._cache[typeName]) {
230-
if (node.kind === Kind.NAMED_TYPE) {
231-
const defNode = this._typeDefinitionsMap[typeName];
232-
this._cache[typeName] = defNode
233-
? this._makeSchemaDef(defNode)
234-
: this._resolveType(node.name.value);
235-
} else {
236-
this._cache[typeName] = this._makeSchemaDef(node);
237-
}
238-
}
239-
return this._cache[typeName];
222+
getNamedType(node: NamedTypeNode): GraphQLNamedType {
223+
const name = node.name.value;
224+
return stdTypeMap[name] || this._resolveType(name);
240225
}
241226

242-
_buildWrappedType(typeNode: TypeNode): GraphQLType {
243-
if (typeNode.kind === Kind.LIST_TYPE) {
244-
return GraphQLList(this._buildWrappedType(typeNode.type));
227+
getWrappedType(node: TypeNode): GraphQLType {
228+
if (node.kind === Kind.LIST_TYPE) {
229+
return GraphQLList(this.getWrappedType(node.type));
245230
}
246-
if (typeNode.kind === Kind.NON_NULL_TYPE) {
231+
if (node.kind === Kind.NON_NULL_TYPE) {
247232
return GraphQLNonNull(
248233
// Note: GraphQLNonNull constructor validates this type
249-
(this._buildWrappedType(typeNode.type): any),
234+
(this.getWrappedType(node.type): any),
250235
);
251236
}
252-
return this.buildType(typeNode);
237+
return this.getNamedType(node);
253238
}
254239

255240
buildDirective(directive: DirectiveDefinitionNode): GraphQLDirective {
@@ -271,7 +256,7 @@ export class ASTDefinitionBuilder {
271256
// Note: While this could make assertions to get the correctly typed
272257
// value, that would throw immediately while type system validation
273258
// with validateSchema() will produce more actionable results.
274-
type: (this._buildWrappedType(field.type): any),
259+
type: (this.getWrappedType(field.type): any),
275260
description: getDescription(field, this._options),
276261
args: keyByNameNode(field.arguments || [], arg => this.buildArg(arg)),
277262
deprecationReason: getDeprecationReason(field),
@@ -283,7 +268,7 @@ export class ASTDefinitionBuilder {
283268
// Note: While this could make assertions to get the correctly typed
284269
// value, that would throw immediately while type system validation
285270
// with validateSchema() will produce more actionable results.
286-
const type: any = this._buildWrappedType(value.type);
271+
const type: any = this.getWrappedType(value.type);
287272
return {
288273
type,
289274
description: getDescription(value, this._options),
@@ -296,7 +281,7 @@ export class ASTDefinitionBuilder {
296281
// Note: While this could make assertions to get the correctly typed
297282
// value, that would throw immediately while type system validation
298283
// with validateSchema() will produce more actionable results.
299-
const type: any = this._buildWrappedType(value.type);
284+
const type: any = this.getWrappedType(value.type);
300285
return {
301286
type,
302287
description: getDescription(value, this._options),
@@ -313,7 +298,12 @@ export class ASTDefinitionBuilder {
313298
};
314299
}
315300

316-
_makeSchemaDef(astNode: TypeDefinitionNode): GraphQLNamedType {
301+
buildType(astNode: TypeDefinitionNode): GraphQLNamedType {
302+
const name = astNode.name.value;
303+
if (stdTypeMap[name]) {
304+
return stdTypeMap[name];
305+
}
306+
317307
switch (astNode.kind) {
318308
case Kind.OBJECT_TYPE_DEFINITION:
319309
return this._makeTypeDef(astNode);
@@ -327,9 +317,11 @@ export class ASTDefinitionBuilder {
327317
return this._makeScalarDef(astNode);
328318
case Kind.INPUT_OBJECT_TYPE_DEFINITION:
329319
return this._makeInputObjectDef(astNode);
330-
default:
331-
throw new Error(`Type kind "${astNode.kind}" not supported.`);
332320
}
321+
322+
// Not reachable. All possible type definition nodes have been considered.
323+
/* istanbul ignore next */
324+
throw new Error(`Type kind "${(astNode: empty).kind}" not supported.`);
333325
}
334326

335327
_makeTypeDef(astNode: ObjectTypeDefinitionNode) {
@@ -341,7 +333,7 @@ export class ASTDefinitionBuilder {
341333
// validation with validateSchema() will produce more actionable results.
342334
const interfaces =
343335
interfaceNodes && interfaceNodes.length > 0
344-
? () => interfaceNodes.map(ref => (this.buildType(ref): any))
336+
? () => interfaceNodes.map(ref => (this.getNamedType(ref): any))
345337
: [];
346338

347339
const fields =
@@ -393,7 +385,7 @@ export class ASTDefinitionBuilder {
393385
// validation with validateSchema() will produce more actionable results.
394386
const types =
395387
typeNodes && typeNodes.length > 0
396-
? () => typeNodes.map(ref => (this.buildType(ref): any))
388+
? () => typeNodes.map(ref => (this.getNamedType(ref): any))
397389
: [];
398390

399391
return new GraphQLUnionType({

0 commit comments

Comments
 (0)