@@ -113,53 +113,61 @@ export class TypeInfo {
113113 // Flow does not yet handle this case.
114114 enter ( node : any /* ASTNode */ ) {
115115 const schema = this . _schema ;
116+ // Note: many of the types below are explicitly typed as "mixed" to drop
117+ // any assumptions of a valid schema to ensure runtime types are properly
118+ // checked before continuing since TypeInfo is used as part of validation
119+ // which occurs before guarantees of schema and document validity.
116120 switch ( node . kind ) {
117121 case Kind . SELECTION_SET :
118- const namedType = getNamedType ( this . getType ( ) ) ;
122+ const namedType : mixed = getNamedType ( this . getType ( ) ) ;
119123 this . _parentTypeStack . push (
120124 isCompositeType ( namedType ) ? namedType : undefined ,
121125 ) ;
122126 break ;
123127 case Kind . FIELD :
124128 const parentType = this . getParentType ( ) ;
125129 let fieldDef ;
130+ let fieldType : mixed ;
126131 if ( parentType ) {
127132 fieldDef = this . _getFieldDef ( schema , parentType , node ) ;
133+ if ( fieldDef ) {
134+ fieldType = fieldDef . type ;
135+ }
128136 }
129137 this . _fieldDefStack . push ( fieldDef ) ;
130- this . _typeStack . push ( fieldDef && fieldDef . type ) ;
138+ this . _typeStack . push ( isOutputType ( fieldType ) ? fieldType : undefined ) ;
131139 break ;
132140 case Kind . DIRECTIVE :
133141 this . _directive = schema . getDirective ( node . name . value ) ;
134142 break ;
135143 case Kind . OPERATION_DEFINITION :
136- let type ;
144+ let type : mixed ;
137145 if ( node . operation === 'query' ) {
138146 type = schema . getQueryType ( ) ;
139147 } else if ( node . operation === 'mutation' ) {
140148 type = schema . getMutationType ( ) ;
141149 } else if ( node . operation === 'subscription' ) {
142150 type = schema . getSubscriptionType ( ) ;
143151 }
144- this . _typeStack . push ( type ) ;
152+ this . _typeStack . push ( isOutputType ( type ) ? type : undefined ) ;
145153 break ;
146154 case Kind . INLINE_FRAGMENT :
147155 case Kind . FRAGMENT_DEFINITION :
148156 const typeConditionAST = node . typeCondition ;
149- const outputType = typeConditionAST
157+ const outputType : mixed = typeConditionAST
150158 ? typeFromAST ( schema , typeConditionAST )
151159 : getNamedType ( this . getType ( ) ) ;
152160 this . _typeStack . push ( isOutputType ( outputType ) ? outputType : undefined ) ;
153161 break ;
154162 case Kind . VARIABLE_DEFINITION :
155- const inputType = typeFromAST ( schema , node . type ) ;
163+ const inputType : mixed = typeFromAST ( schema , node . type ) ;
156164 this . _inputTypeStack . push (
157165 isInputType ( inputType ) ? inputType : undefined ,
158166 ) ;
159167 break ;
160168 case Kind . ARGUMENT :
161169 let argDef ;
162- let argType ;
170+ let argType : mixed ;
163171 const fieldOrDirective = this . getDirective ( ) || this . getFieldDef ( ) ;
164172 if ( fieldOrDirective ) {
165173 argDef = find (
@@ -171,25 +179,31 @@ export class TypeInfo {
171179 }
172180 }
173181 this . _argument = argDef ;
174- this . _inputTypeStack . push ( argType ) ;
182+ this . _inputTypeStack . push ( isInputType ( argType ) ? argType : undefined ) ;
175183 break ;
176184 case Kind . LIST :
177- const listType = getNullableType ( this . getInputType ( ) ) ;
185+ const listType : mixed = getNullableType ( this . getInputType ( ) ) ;
178186 this . _inputTypeStack . push (
179- isListType ( listType ) ? listType . ofType : undefined ,
187+ isListType ( listType ) && isInputType ( listType . ofType )
188+ ? listType . ofType
189+ : undefined ,
180190 ) ;
181191 break ;
182192 case Kind . OBJECT_FIELD :
183- const objectType = getNamedType ( this . getInputType ( ) ) ;
184- let fieldType ;
193+ const objectType : mixed = getNamedType ( this . getInputType ( ) ) ;
194+ let inputFieldType : mixed ;
185195 if ( isInputObjectType ( objectType ) ) {
186196 const inputField = objectType . getFields ( ) [ node . name . value ] ;
187- fieldType = inputField ? inputField . type : undefined ;
197+ if ( inputField ) {
198+ inputFieldType = inputField . type ;
199+ }
188200 }
189- this . _inputTypeStack . push ( fieldType ) ;
201+ this . _inputTypeStack . push (
202+ isInputType ( inputFieldType ) ? inputFieldType : undefined ,
203+ ) ;
190204 break ;
191205 case Kind . ENUM :
192- const enumType = getNamedType ( this . getInputType ( ) ) ;
206+ const enumType : mixed = getNamedType ( this . getInputType ( ) ) ;
193207 let enumValue ;
194208 if ( isEnumType ( enumType ) ) {
195209 enumValue = enumType . getValue ( node . value ) ;
0 commit comments