diff --git a/src/execution/collectFields.ts b/src/execution/collectFields.ts index 06ade32c5b..03d163373f 100644 --- a/src/execution/collectFields.ts +++ b/src/execution/collectFields.ts @@ -21,8 +21,8 @@ import { typeFromAST } from '../utilities/typeFromAST'; import { getDirectiveValues } from './values'; -interface FragmentEntry { - fragment: FragmentDefinitionNode; +interface StackEntry { + selectionSet: SelectionSetNode; runtimeType: GraphQLObjectType; } @@ -42,31 +42,21 @@ export function collectFields( runtimeType: GraphQLObjectType, selectionSet: SelectionSetNode, ): Map> { - const foundFragments: Array = []; + const stack: Array = [{ selectionSet, runtimeType }]; const fields = new Map(); const visited = new Set(); - collectFieldsImpl( - schema, - fragments, - variableValues, - runtimeType, - selectionSet, - fields, - visited, - foundFragments, - ); let entry; - while ((entry = foundFragments.pop()) !== undefined) { + while ((entry = stack.shift()) !== undefined) { collectFieldsImpl( schema, fragments, variableValues, entry.runtimeType, - entry.fragment.selectionSet, + entry.selectionSet, fields, visited, - foundFragments, + stack, ); } @@ -91,34 +81,25 @@ export function collectSubfields( fieldNodes: ReadonlyArray, ): Map> { const subFieldNodes = new Map(); - const foundFragments: Array = []; + const stack: Array = []; const visitedFragmentNames = new Set(); for (const node of fieldNodes) { if (node.selectionSet) { - collectFieldsImpl( - schema, - fragments, - variableValues, - returnType, - node.selectionSet, - subFieldNodes, - visitedFragmentNames, - foundFragments, - ); + stack.push({ selectionSet: node.selectionSet, runtimeType: returnType }); } } let entry; - while ((entry = foundFragments.pop()) !== undefined) { + while ((entry = stack.shift()) !== undefined) { collectFieldsImpl( schema, fragments, variableValues, entry.runtimeType, - entry.fragment.selectionSet, + entry.selectionSet, subFieldNodes, visitedFragmentNames, - foundFragments, + stack, ); } @@ -133,8 +114,9 @@ function collectFieldsImpl( selectionSet: SelectionSetNode, fields: Map>, visitedFragmentNames: Set, - foundFragments: Array, + stack: Array, ): void { + const discovered = []; for (const selection of selectionSet.selections) { switch (selection.kind) { case Kind.FIELD: { @@ -157,16 +139,7 @@ function collectFieldsImpl( ) { continue; } - collectFieldsImpl( - schema, - fragments, - variableValues, - runtimeType, - selection.selectionSet, - fields, - visitedFragmentNames, - foundFragments, - ); + discovered.push({ selectionSet: selection.selectionSet, runtimeType }); break; } case Kind.FRAGMENT_SPREAD: { @@ -186,11 +159,15 @@ function collectFieldsImpl( continue; } - foundFragments.push({ runtimeType, fragment }); + discovered.push({ selectionSet: fragment.selectionSet, runtimeType }); break; } } } + + if (discovered.length !== 0) { + stack.unshift(...discovered); + } } /**