diff --git a/src/type/validate.js b/src/type/validate.js index 501e708086..282013b802 100644 --- a/src/type/validate.js +++ b/src/type/validate.js @@ -232,7 +232,11 @@ function validateName( } function validateTypes(context: SchemaValidationContext): void { + const validateInputObjectCircularRefs = createInputObjectCircularRefsValidator( + context, + ); const typeMap = context.schema.getTypeMap(); + objectValues(typeMap).forEach(type => { // Ensure all provided types are in fact GraphQL type. if (!isNamedType(type)) { @@ -266,11 +270,11 @@ function validateTypes(context: SchemaValidationContext): void { } else if (isInputObjectType(type)) { // Ensure Input Object fields are valid. validateInputFields(context, type); + + // Ensure Input Objects do not contain non-nullable circular references + validateInputObjectCircularRefs(type); } }); - - // Ensure Input Objects do not contain non-nullable circular references - validateInputObjectCircularReferences(context); } function validateFields( @@ -563,9 +567,9 @@ function validateInputFields( }); } -function validateInputObjectCircularReferences( +function createInputObjectCircularRefsValidator( context: SchemaValidationContext, -): void { +) { // Modified copy of algorithm from 'src/validation/rules/NoFragmentCycles.js'. // Tracks already visited types to maintain O(N) and to ensure that cycles // are not redundantly reported. @@ -577,12 +581,7 @@ function validateInputObjectCircularReferences( // Position in the type path const fieldPathIndexByTypeName = Object.create(null); - const typeMap = context.schema.getTypeMap(); - for (const type of objectValues(typeMap)) { - if (isInputObjectType(type)) { - detectCycleRecursive(type); - } - } + return detectCycleRecursive; // This does a straight-forward DFS to find cycles. // It does not terminate when a cycle was found but continues to explore