From 3e4fde0d00a68ed4825b4e69f86258b79aaebfa4 Mon Sep 17 00:00:00 2001 From: Yaacov Rydzinski Date: Tue, 4 Apr 2023 11:15:24 +0300 Subject: [PATCH 1/6] introduce FieldGroup type --- src/execution/collectFields.ts | 8 ++++--- src/execution/execute.ts | 42 +++++++++++++++++----------------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/execution/collectFields.ts b/src/execution/collectFields.ts index 91ac792505..532597553e 100644 --- a/src/execution/collectFields.ts +++ b/src/execution/collectFields.ts @@ -26,13 +26,15 @@ import { typeFromAST } from '../utilities/typeFromAST.js'; import { getDirectiveValues } from './values.js'; +export type FieldGroup = ReadonlyArray; + export interface PatchFields { label: string | undefined; - fields: Map>; + fields: Map; } export interface FieldsAndPatches { - fields: Map>; + fields: Map; patches: Array; } @@ -85,7 +87,7 @@ export function collectSubfields( variableValues: { [variable: string]: unknown }, operation: OperationDefinitionNode, returnType: GraphQLObjectType, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, ): FieldsAndPatches { const subFieldNodes = new AccumulatorMap(); const visitedFragmentNames = new Set(); diff --git a/src/execution/execute.ts b/src/execution/execute.ts index a722563289..42cfe09c87 100644 --- a/src/execution/execute.ts +++ b/src/execution/execute.ts @@ -19,7 +19,6 @@ import { locatedError } from '../error/locatedError.js'; import type { DocumentNode, - FieldNode, FragmentDefinitionNode, OperationDefinitionNode, } from '../language/ast.js'; @@ -48,6 +47,7 @@ import { GraphQLStreamDirective } from '../type/directives.js'; import type { GraphQLSchema } from '../type/schema.js'; import { assertValidSchema } from '../type/validate.js'; +import type { FieldGroup } from './collectFields.js'; import { collectFields, collectSubfields as _collectSubfields, @@ -72,7 +72,7 @@ const collectSubfields = memoize3( ( exeContext: ExecutionContext, returnType: GraphQLObjectType, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, ) => _collectSubfields( exeContext.schema, @@ -589,7 +589,7 @@ function executeFieldsSerially( parentType: GraphQLObjectType, sourceValue: unknown, path: Path | undefined, - fields: Map>, + fields: Map, ): PromiseOrValue> { return promiseReduce( fields, @@ -627,7 +627,7 @@ function executeFields( parentType: GraphQLObjectType, sourceValue: unknown, path: Path | undefined, - fields: Map>, + fields: Map, asyncPayloadRecord?: AsyncPayloadRecord, ): PromiseOrValue> { const results = Object.create(null); @@ -683,7 +683,7 @@ function executeField( exeContext: ExecutionContext, parentType: GraphQLObjectType, source: unknown, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, path: Path, asyncPayloadRecord?: AsyncPayloadRecord, ): PromiseOrValue { @@ -771,7 +771,7 @@ function executeField( export function buildResolveInfo( exeContext: ExecutionContext, fieldDef: GraphQLField, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, parentType: GraphQLObjectType, path: Path, ): GraphQLResolveInfo { @@ -832,7 +832,7 @@ function handleFieldError( function completeValue( exeContext: ExecutionContext, returnType: GraphQLOutputType, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, info: GraphQLResolveInfo, path: Path, result: unknown, @@ -924,7 +924,7 @@ function completeValue( async function completePromisedValue( exeContext: ExecutionContext, returnType: GraphQLOutputType, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, info: GraphQLResolveInfo, path: Path, result: Promise, @@ -961,7 +961,7 @@ async function completePromisedValue( */ function getStreamValues( exeContext: ExecutionContext, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, path: Path, ): | undefined @@ -1018,7 +1018,7 @@ function getStreamValues( async function completeAsyncIteratorValue( exeContext: ExecutionContext, itemType: GraphQLOutputType, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, info: GraphQLResolveInfo, path: Path, iterator: AsyncIterator, @@ -1092,7 +1092,7 @@ async function completeAsyncIteratorValue( function completeListValue( exeContext: ExecutionContext, returnType: GraphQLList, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, info: GraphQLResolveInfo, path: Path, result: unknown, @@ -1187,7 +1187,7 @@ function completeListItemValue( errors: Array, exeContext: ExecutionContext, itemType: GraphQLOutputType, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, info: GraphQLResolveInfo, itemPath: Path, asyncPayloadRecord?: AsyncPayloadRecord, @@ -1274,7 +1274,7 @@ function completeLeafValue( function completeAbstractValue( exeContext: ExecutionContext, returnType: GraphQLAbstractType, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, info: GraphQLResolveInfo, path: Path, result: unknown, @@ -1327,7 +1327,7 @@ function ensureValidRuntimeType( runtimeTypeName: unknown, exeContext: ExecutionContext, returnType: GraphQLAbstractType, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, info: GraphQLResolveInfo, result: unknown, ): GraphQLObjectType { @@ -1384,7 +1384,7 @@ function ensureValidRuntimeType( function completeObjectValue( exeContext: ExecutionContext, returnType: GraphQLObjectType, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, info: GraphQLResolveInfo, path: Path, result: unknown, @@ -1430,7 +1430,7 @@ function completeObjectValue( function invalidReturnTypeError( returnType: GraphQLObjectType, result: unknown, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, ): GraphQLError { return new GraphQLError( `Expected value of type "${returnType.name}" but got: ${inspect(result)}.`, @@ -1441,7 +1441,7 @@ function invalidReturnTypeError( function collectAndExecuteSubfields( exeContext: ExecutionContext, returnType: GraphQLObjectType, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, path: Path, result: unknown, asyncPayloadRecord?: AsyncPayloadRecord, @@ -1770,7 +1770,7 @@ function executeDeferredFragment( exeContext: ExecutionContext, parentType: GraphQLObjectType, sourceValue: unknown, - fields: Map>, + fields: Map, label?: string, path?: Path, parentContext?: AsyncPayloadRecord, @@ -1810,7 +1810,7 @@ function executeStreamField( itemPath: Path, item: PromiseOrValue, exeContext: ExecutionContext, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, info: GraphQLResolveInfo, itemType: GraphQLOutputType, label?: string, @@ -1904,7 +1904,7 @@ function executeStreamField( async function executeStreamIteratorItem( iterator: AsyncIterator, exeContext: ExecutionContext, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, info: GraphQLResolveInfo, itemType: GraphQLOutputType, asyncPayloadRecord: StreamRecord, @@ -1961,7 +1961,7 @@ async function executeStreamIterator( initialIndex: number, iterator: AsyncIterator, exeContext: ExecutionContext, - fieldNodes: ReadonlyArray, + fieldNodes: FieldGroup, info: GraphQLResolveInfo, itemType: GraphQLOutputType, path: Path, From 2eb67bbc1941f451b657ee20b76d138e1fecfe58 Mon Sep 17 00:00:00 2001 From: Yaacov Rydzinski Date: Tue, 4 Apr 2023 11:18:53 +0300 Subject: [PATCH 2/6] rename fieldNodes variable to fieldGroup to match type --- src/execution/collectFields.ts | 4 +- src/execution/execute.ts | 158 +++++++++--------- .../rules/SingleFieldSubscriptionsRule.ts | 6 +- 3 files changed, 84 insertions(+), 84 deletions(-) diff --git a/src/execution/collectFields.ts b/src/execution/collectFields.ts index 532597553e..de2718d7bb 100644 --- a/src/execution/collectFields.ts +++ b/src/execution/collectFields.ts @@ -87,7 +87,7 @@ export function collectSubfields( variableValues: { [variable: string]: unknown }, operation: OperationDefinitionNode, returnType: GraphQLObjectType, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, ): FieldsAndPatches { const subFieldNodes = new AccumulatorMap(); const visitedFragmentNames = new Set(); @@ -98,7 +98,7 @@ export function collectSubfields( patches: subPatches, }; - for (const node of fieldNodes) { + for (const node of fieldGroup) { if (node.selectionSet) { collectFieldsImpl( schema, diff --git a/src/execution/execute.ts b/src/execution/execute.ts index 42cfe09c87..3decd52fe5 100644 --- a/src/execution/execute.ts +++ b/src/execution/execute.ts @@ -72,7 +72,7 @@ const collectSubfields = memoize3( ( exeContext: ExecutionContext, returnType: GraphQLObjectType, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, ) => _collectSubfields( exeContext.schema, @@ -80,7 +80,7 @@ const collectSubfields = memoize3( exeContext.variableValues, exeContext.operation, returnType, - fieldNodes, + fieldGroup, ), ); @@ -593,13 +593,13 @@ function executeFieldsSerially( ): PromiseOrValue> { return promiseReduce( fields, - (results, [responseName, fieldNodes]) => { + (results, [responseName, fieldGroup]) => { const fieldPath = addPath(path, responseName, parentType.name); const result = executeField( exeContext, parentType, sourceValue, - fieldNodes, + fieldGroup, fieldPath, ); if (result === undefined) { @@ -634,13 +634,13 @@ function executeFields( let containsPromise = false; try { - for (const [responseName, fieldNodes] of fields) { + for (const [responseName, fieldGroup] of fields) { const fieldPath = addPath(path, responseName, parentType.name); const result = executeField( exeContext, parentType, sourceValue, - fieldNodes, + fieldGroup, fieldPath, asyncPayloadRecord, ); @@ -683,12 +683,12 @@ function executeField( exeContext: ExecutionContext, parentType: GraphQLObjectType, source: unknown, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, path: Path, asyncPayloadRecord?: AsyncPayloadRecord, ): PromiseOrValue { const errors = asyncPayloadRecord?.errors ?? exeContext.errors; - const fieldName = fieldNodes[0].name.value; + const fieldName = fieldGroup[0].name.value; const fieldDef = exeContext.schema.getField(parentType, fieldName); if (!fieldDef) { return; @@ -700,7 +700,7 @@ function executeField( const info = buildResolveInfo( exeContext, fieldDef, - fieldNodes, + fieldGroup, parentType, path, ); @@ -712,7 +712,7 @@ function executeField( // TODO: find a way to memoize, in case this field is within a List type. const args = getArgumentValues( fieldDef, - fieldNodes[0], + fieldGroup[0], exeContext.variableValues, ); @@ -727,7 +727,7 @@ function executeField( return completePromisedValue( exeContext, returnType, - fieldNodes, + fieldGroup, info, path, result, @@ -738,7 +738,7 @@ function executeField( const completed = completeValue( exeContext, returnType, - fieldNodes, + fieldGroup, info, path, result, @@ -749,7 +749,7 @@ function executeField( // Note: we don't rely on a `catch` method, but we do expect "thenable" // to take a second callback for the error case. return completed.then(undefined, (rawError) => { - const error = locatedError(rawError, fieldNodes, pathToArray(path)); + const error = locatedError(rawError, fieldGroup, pathToArray(path)); const handledError = handleFieldError(error, returnType, errors); filterSubsequentPayloads(exeContext, path, asyncPayloadRecord); return handledError; @@ -757,7 +757,7 @@ function executeField( } return completed; } catch (rawError) { - const error = locatedError(rawError, fieldNodes, pathToArray(path)); + const error = locatedError(rawError, fieldGroup, pathToArray(path)); const handledError = handleFieldError(error, returnType, errors); filterSubsequentPayloads(exeContext, path, asyncPayloadRecord); return handledError; @@ -771,7 +771,7 @@ function executeField( export function buildResolveInfo( exeContext: ExecutionContext, fieldDef: GraphQLField, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, parentType: GraphQLObjectType, path: Path, ): GraphQLResolveInfo { @@ -779,7 +779,7 @@ export function buildResolveInfo( // information about the current execution state. return { fieldName: fieldDef.name, - fieldNodes, + fieldNodes: fieldGroup, returnType: fieldDef.type, parentType, path, @@ -832,7 +832,7 @@ function handleFieldError( function completeValue( exeContext: ExecutionContext, returnType: GraphQLOutputType, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, info: GraphQLResolveInfo, path: Path, result: unknown, @@ -849,7 +849,7 @@ function completeValue( const completed = completeValue( exeContext, returnType.ofType, - fieldNodes, + fieldGroup, info, path, result, @@ -873,7 +873,7 @@ function completeValue( return completeListValue( exeContext, returnType, - fieldNodes, + fieldGroup, info, path, result, @@ -893,7 +893,7 @@ function completeValue( return completeAbstractValue( exeContext, returnType, - fieldNodes, + fieldGroup, info, path, result, @@ -906,7 +906,7 @@ function completeValue( return completeObjectValue( exeContext, returnType, - fieldNodes, + fieldGroup, info, path, result, @@ -924,7 +924,7 @@ function completeValue( async function completePromisedValue( exeContext: ExecutionContext, returnType: GraphQLOutputType, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, info: GraphQLResolveInfo, path: Path, result: Promise, @@ -935,7 +935,7 @@ async function completePromisedValue( let completed = completeValue( exeContext, returnType, - fieldNodes, + fieldGroup, info, path, resolved, @@ -947,7 +947,7 @@ async function completePromisedValue( return completed; } catch (rawError) { const errors = asyncPayloadRecord?.errors ?? exeContext.errors; - const error = locatedError(rawError, fieldNodes, pathToArray(path)); + const error = locatedError(rawError, fieldGroup, pathToArray(path)); const handledError = handleFieldError(error, returnType, errors); filterSubsequentPayloads(exeContext, path, asyncPayloadRecord); return handledError; @@ -961,7 +961,7 @@ async function completePromisedValue( */ function getStreamValues( exeContext: ExecutionContext, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, path: Path, ): | undefined @@ -978,7 +978,7 @@ function getStreamValues( // safe to only check the first fieldNode for the stream directive const stream = getDirectiveValues( GraphQLStreamDirective, - fieldNodes[0], + fieldGroup[0], exeContext.variableValues, ); @@ -1018,14 +1018,14 @@ function getStreamValues( async function completeAsyncIteratorValue( exeContext: ExecutionContext, itemType: GraphQLOutputType, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, info: GraphQLResolveInfo, path: Path, iterator: AsyncIterator, asyncPayloadRecord?: AsyncPayloadRecord, ): Promise> { const errors = asyncPayloadRecord?.errors ?? exeContext.errors; - const stream = getStreamValues(exeContext, fieldNodes, path); + const stream = getStreamValues(exeContext, fieldGroup, path); let containsPromise = false; const completedResults: Array = []; let index = 0; @@ -1041,7 +1041,7 @@ async function completeAsyncIteratorValue( index, iterator, exeContext, - fieldNodes, + fieldGroup, info, itemType, path, @@ -1060,7 +1060,7 @@ async function completeAsyncIteratorValue( break; } } catch (rawError) { - const error = locatedError(rawError, fieldNodes, pathToArray(itemPath)); + const error = locatedError(rawError, fieldGroup, pathToArray(itemPath)); completedResults.push(handleFieldError(error, itemType, errors)); break; } @@ -1072,7 +1072,7 @@ async function completeAsyncIteratorValue( errors, exeContext, itemType, - fieldNodes, + fieldGroup, info, itemPath, asyncPayloadRecord, @@ -1092,7 +1092,7 @@ async function completeAsyncIteratorValue( function completeListValue( exeContext: ExecutionContext, returnType: GraphQLList, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, info: GraphQLResolveInfo, path: Path, result: unknown, @@ -1107,7 +1107,7 @@ function completeListValue( return completeAsyncIteratorValue( exeContext, itemType, - fieldNodes, + fieldGroup, info, path, iterator, @@ -1121,7 +1121,7 @@ function completeListValue( ); } - const stream = getStreamValues(exeContext, fieldNodes, path); + const stream = getStreamValues(exeContext, fieldGroup, path); // This is specified as a simple map, however we're optimizing the path // where the list contains no Promises by avoiding creating another Promise. @@ -1144,7 +1144,7 @@ function completeListValue( itemPath, item, exeContext, - fieldNodes, + fieldGroup, info, itemType, stream.label, @@ -1161,7 +1161,7 @@ function completeListValue( errors, exeContext, itemType, - fieldNodes, + fieldGroup, info, itemPath, asyncPayloadRecord, @@ -1187,7 +1187,7 @@ function completeListItemValue( errors: Array, exeContext: ExecutionContext, itemType: GraphQLOutputType, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, info: GraphQLResolveInfo, itemPath: Path, asyncPayloadRecord?: AsyncPayloadRecord, @@ -1197,7 +1197,7 @@ function completeListItemValue( completePromisedValue( exeContext, itemType, - fieldNodes, + fieldGroup, info, itemPath, item, @@ -1212,7 +1212,7 @@ function completeListItemValue( const completedItem = completeValue( exeContext, itemType, - fieldNodes, + fieldGroup, info, itemPath, item, @@ -1226,7 +1226,7 @@ function completeListItemValue( completedItem.then(undefined, (rawError) => { const error = locatedError( rawError, - fieldNodes, + fieldGroup, pathToArray(itemPath), ); const handledError = handleFieldError(error, itemType, errors); @@ -1240,7 +1240,7 @@ function completeListItemValue( completedResults.push(completedItem); } catch (rawError) { - const error = locatedError(rawError, fieldNodes, pathToArray(itemPath)); + const error = locatedError(rawError, fieldGroup, pathToArray(itemPath)); const handledError = handleFieldError(error, itemType, errors); filterSubsequentPayloads(exeContext, itemPath, asyncPayloadRecord); completedResults.push(handledError); @@ -1274,7 +1274,7 @@ function completeLeafValue( function completeAbstractValue( exeContext: ExecutionContext, returnType: GraphQLAbstractType, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, info: GraphQLResolveInfo, path: Path, result: unknown, @@ -1292,11 +1292,11 @@ function completeAbstractValue( resolvedRuntimeType, exeContext, returnType, - fieldNodes, + fieldGroup, info, result, ), - fieldNodes, + fieldGroup, info, path, result, @@ -1311,11 +1311,11 @@ function completeAbstractValue( runtimeType, exeContext, returnType, - fieldNodes, + fieldGroup, info, result, ), - fieldNodes, + fieldGroup, info, path, result, @@ -1327,14 +1327,14 @@ function ensureValidRuntimeType( runtimeTypeName: unknown, exeContext: ExecutionContext, returnType: GraphQLAbstractType, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, info: GraphQLResolveInfo, result: unknown, ): GraphQLObjectType { if (runtimeTypeName == null) { throw new GraphQLError( `Abstract type "${returnType.name}" must resolve to an Object type at runtime for field "${info.parentType.name}.${info.fieldName}". Either the "${returnType.name}" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.`, - { nodes: fieldNodes }, + { nodes: fieldGroup }, ); } @@ -1357,21 +1357,21 @@ function ensureValidRuntimeType( if (runtimeType == null) { throw new GraphQLError( `Abstract type "${returnType.name}" was resolved to a type "${runtimeTypeName}" that does not exist inside the schema.`, - { nodes: fieldNodes }, + { nodes: fieldGroup }, ); } if (!isObjectType(runtimeType)) { throw new GraphQLError( `Abstract type "${returnType.name}" was resolved to a non-object type "${runtimeTypeName}".`, - { nodes: fieldNodes }, + { nodes: fieldGroup }, ); } if (!exeContext.schema.isSubType(returnType, runtimeType)) { throw new GraphQLError( `Runtime Object type "${runtimeType.name}" is not a possible type for "${returnType.name}".`, - { nodes: fieldNodes }, + { nodes: fieldGroup }, ); } @@ -1384,7 +1384,7 @@ function ensureValidRuntimeType( function completeObjectValue( exeContext: ExecutionContext, returnType: GraphQLObjectType, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, info: GraphQLResolveInfo, path: Path, result: unknown, @@ -1399,12 +1399,12 @@ function completeObjectValue( if (isPromise(isTypeOf)) { return isTypeOf.then((resolvedIsTypeOf) => { if (!resolvedIsTypeOf) { - throw invalidReturnTypeError(returnType, result, fieldNodes); + throw invalidReturnTypeError(returnType, result, fieldGroup); } return collectAndExecuteSubfields( exeContext, returnType, - fieldNodes, + fieldGroup, path, result, asyncPayloadRecord, @@ -1413,14 +1413,14 @@ function completeObjectValue( } if (!isTypeOf) { - throw invalidReturnTypeError(returnType, result, fieldNodes); + throw invalidReturnTypeError(returnType, result, fieldGroup); } } return collectAndExecuteSubfields( exeContext, returnType, - fieldNodes, + fieldGroup, path, result, asyncPayloadRecord, @@ -1430,18 +1430,18 @@ function completeObjectValue( function invalidReturnTypeError( returnType: GraphQLObjectType, result: unknown, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, ): GraphQLError { return new GraphQLError( `Expected value of type "${returnType.name}" but got: ${inspect(result)}.`, - { nodes: fieldNodes }, + { nodes: fieldGroup }, ); } function collectAndExecuteSubfields( exeContext: ExecutionContext, returnType: GraphQLObjectType, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, path: Path, result: unknown, asyncPayloadRecord?: AsyncPayloadRecord, @@ -1450,7 +1450,7 @@ function collectAndExecuteSubfields( const { fields: subFieldNodes, patches: subPatches } = collectSubfields( exeContext, returnType, - fieldNodes, + fieldGroup, ); const subFields = executeFields( @@ -1700,14 +1700,14 @@ function executeSubscription( ); const firstRootField = rootFields.entries().next().value; - const [responseName, fieldNodes] = firstRootField; - const fieldName = fieldNodes[0].name.value; + const [responseName, fieldGroup] = firstRootField; + const fieldName = fieldGroup[0].name.value; const fieldDef = schema.getField(rootType, fieldName); if (!fieldDef) { throw new GraphQLError( `The subscription field "${fieldName}" is not defined.`, - { nodes: fieldNodes }, + { nodes: fieldGroup }, ); } @@ -1715,7 +1715,7 @@ function executeSubscription( const info = buildResolveInfo( exeContext, fieldDef, - fieldNodes, + fieldGroup, rootType, path, ); @@ -1726,7 +1726,7 @@ function executeSubscription( // Build a JS object of arguments from the field.arguments AST, using the // variables scope to fulfill any variable references. - const args = getArgumentValues(fieldDef, fieldNodes[0], variableValues); + const args = getArgumentValues(fieldDef, fieldGroup[0], variableValues); // The resolve function's optional third argument is a context value that // is provided to every resolve function within an execution. It is commonly @@ -1740,13 +1740,13 @@ function executeSubscription( if (isPromise(result)) { return result.then(assertEventStream).then(undefined, (error) => { - throw locatedError(error, fieldNodes, pathToArray(path)); + throw locatedError(error, fieldGroup, pathToArray(path)); }); } return assertEventStream(result); } catch (error) { - throw locatedError(error, fieldNodes, pathToArray(path)); + throw locatedError(error, fieldGroup, pathToArray(path)); } } @@ -1810,7 +1810,7 @@ function executeStreamField( itemPath: Path, item: PromiseOrValue, exeContext: ExecutionContext, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, info: GraphQLResolveInfo, itemType: GraphQLOutputType, label?: string, @@ -1826,7 +1826,7 @@ function executeStreamField( const completedItems = completePromisedValue( exeContext, itemType, - fieldNodes, + fieldGroup, info, itemPath, item, @@ -1850,14 +1850,14 @@ function executeStreamField( completedItem = completeValue( exeContext, itemType, - fieldNodes, + fieldGroup, info, itemPath, item, asyncPayloadRecord, ); } catch (rawError) { - const error = locatedError(rawError, fieldNodes, pathToArray(itemPath)); + const error = locatedError(rawError, fieldGroup, pathToArray(itemPath)); completedItem = handleFieldError( error, itemType, @@ -1875,7 +1875,7 @@ function executeStreamField( if (isPromise(completedItem)) { const completedItems = completedItem .then(undefined, (rawError) => { - const error = locatedError(rawError, fieldNodes, pathToArray(itemPath)); + const error = locatedError(rawError, fieldGroup, pathToArray(itemPath)); const handledError = handleFieldError( error, itemType, @@ -1904,7 +1904,7 @@ function executeStreamField( async function executeStreamIteratorItem( iterator: AsyncIterator, exeContext: ExecutionContext, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, info: GraphQLResolveInfo, itemType: GraphQLOutputType, asyncPayloadRecord: StreamRecord, @@ -1919,7 +1919,7 @@ async function executeStreamIteratorItem( } item = value; } catch (rawError) { - const error = locatedError(rawError, fieldNodes, pathToArray(itemPath)); + const error = locatedError(rawError, fieldGroup, pathToArray(itemPath)); const value = handleFieldError(error, itemType, asyncPayloadRecord.errors); // don't continue if iterator throws return { done: true, value }; @@ -1929,7 +1929,7 @@ async function executeStreamIteratorItem( completedItem = completeValue( exeContext, itemType, - fieldNodes, + fieldGroup, info, itemPath, item, @@ -1938,7 +1938,7 @@ async function executeStreamIteratorItem( if (isPromise(completedItem)) { completedItem = completedItem.then(undefined, (rawError) => { - const error = locatedError(rawError, fieldNodes, pathToArray(itemPath)); + const error = locatedError(rawError, fieldGroup, pathToArray(itemPath)); const handledError = handleFieldError( error, itemType, @@ -1950,7 +1950,7 @@ async function executeStreamIteratorItem( } return { done: false, value: completedItem }; } catch (rawError) { - const error = locatedError(rawError, fieldNodes, pathToArray(itemPath)); + const error = locatedError(rawError, fieldGroup, pathToArray(itemPath)); const value = handleFieldError(error, itemType, asyncPayloadRecord.errors); filterSubsequentPayloads(exeContext, itemPath, asyncPayloadRecord); return { done: false, value }; @@ -1961,7 +1961,7 @@ async function executeStreamIterator( initialIndex: number, iterator: AsyncIterator, exeContext: ExecutionContext, - fieldNodes: FieldGroup, + fieldGroup: FieldGroup, info: GraphQLResolveInfo, itemType: GraphQLOutputType, path: Path, @@ -1987,7 +1987,7 @@ async function executeStreamIterator( iteration = await executeStreamIteratorItem( iterator, exeContext, - fieldNodes, + fieldGroup, info, itemType, asyncPayloadRecord, diff --git a/src/validation/rules/SingleFieldSubscriptionsRule.ts b/src/validation/rules/SingleFieldSubscriptionsRule.ts index 4a3d834124..9830f14428 100644 --- a/src/validation/rules/SingleFieldSubscriptionsRule.ts +++ b/src/validation/rules/SingleFieldSubscriptionsRule.ts @@ -61,15 +61,15 @@ export function SingleFieldSubscriptionsRule( ), ); } - for (const fieldNodes of fields.values()) { - const fieldName = fieldNodes[0].name.value; + for (const fieldGroup of fields.values()) { + const fieldName = fieldGroup[0].name.value; if (fieldName.startsWith('__')) { context.reportError( new GraphQLError( operationName != null ? `Subscription "${operationName}" must not select an introspection top level field.` : 'Anonymous Subscription must not select an introspection top level field.', - { nodes: fieldNodes }, + { nodes: fieldGroup }, ), ); } From 52ccb18c584100bb1397b05467ab6462bf6d7dd6 Mon Sep 17 00:00:00 2001 From: Yaacov Rydzinski Date: Tue, 4 Apr 2023 11:22:17 +0300 Subject: [PATCH 3/6] introduce GroupedFieldSet type --- src/execution/collectFields.ts | 6 ++++-- src/execution/execute.ts | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/execution/collectFields.ts b/src/execution/collectFields.ts index de2718d7bb..6c6516bdc0 100644 --- a/src/execution/collectFields.ts +++ b/src/execution/collectFields.ts @@ -28,13 +28,15 @@ import { getDirectiveValues } from './values.js'; export type FieldGroup = ReadonlyArray; +export type GroupedFieldSet = Map; + export interface PatchFields { label: string | undefined; - fields: Map; + fields: GroupedFieldSet; } export interface FieldsAndPatches { - fields: Map; + fields: GroupedFieldSet; patches: Array; } diff --git a/src/execution/execute.ts b/src/execution/execute.ts index 3decd52fe5..e1bc6a02cf 100644 --- a/src/execution/execute.ts +++ b/src/execution/execute.ts @@ -47,7 +47,7 @@ import { GraphQLStreamDirective } from '../type/directives.js'; import type { GraphQLSchema } from '../type/schema.js'; import { assertValidSchema } from '../type/validate.js'; -import type { FieldGroup } from './collectFields.js'; +import type { FieldGroup, GroupedFieldSet } from './collectFields.js'; import { collectFields, collectSubfields as _collectSubfields, @@ -589,7 +589,7 @@ function executeFieldsSerially( parentType: GraphQLObjectType, sourceValue: unknown, path: Path | undefined, - fields: Map, + fields: GroupedFieldSet, ): PromiseOrValue> { return promiseReduce( fields, @@ -627,7 +627,7 @@ function executeFields( parentType: GraphQLObjectType, sourceValue: unknown, path: Path | undefined, - fields: Map, + fields: GroupedFieldSet, asyncPayloadRecord?: AsyncPayloadRecord, ): PromiseOrValue> { const results = Object.create(null); @@ -1770,7 +1770,7 @@ function executeDeferredFragment( exeContext: ExecutionContext, parentType: GraphQLObjectType, sourceValue: unknown, - fields: Map, + fields: GroupedFieldSet, label?: string, path?: Path, parentContext?: AsyncPayloadRecord, From 93989eb63d01dd005ad7b32ada88e615f1cbf035 Mon Sep 17 00:00:00 2001 From: Yaacov Rydzinski Date: Tue, 4 Apr 2023 11:31:46 +0300 Subject: [PATCH 4/6] use groupedFieldSet as variable name to match type --- src/execution/collectFields.ts | 28 ++++++------- src/execution/execute.ts | 41 +++++++++++-------- .../rules/SingleFieldSubscriptionsRule.ts | 8 ++-- 3 files changed, 43 insertions(+), 34 deletions(-) diff --git a/src/execution/collectFields.ts b/src/execution/collectFields.ts index 6c6516bdc0..af263112ec 100644 --- a/src/execution/collectFields.ts +++ b/src/execution/collectFields.ts @@ -32,11 +32,11 @@ export type GroupedFieldSet = Map; export interface PatchFields { label: string | undefined; - fields: GroupedFieldSet; + groupedFieldSet: GroupedFieldSet; } export interface FieldsAndPatches { - fields: GroupedFieldSet; + groupedFieldSet: GroupedFieldSet; patches: Array; } @@ -56,7 +56,7 @@ export function collectFields( runtimeType: GraphQLObjectType, operation: OperationDefinitionNode, ): FieldsAndPatches { - const fields = new AccumulatorMap(); + const groupedFieldSet = new AccumulatorMap(); const patches: Array = []; collectFieldsImpl( schema, @@ -65,11 +65,11 @@ export function collectFields( operation, runtimeType, operation.selectionSet, - fields, + groupedFieldSet, patches, new Set(), ); - return { fields, patches }; + return { groupedFieldSet, patches }; } /** @@ -91,12 +91,12 @@ export function collectSubfields( returnType: GraphQLObjectType, fieldGroup: FieldGroup, ): FieldsAndPatches { - const subFieldNodes = new AccumulatorMap(); + const subGroupedFieldSet = new AccumulatorMap(); const visitedFragmentNames = new Set(); const subPatches: Array = []; const subFieldsAndPatches = { - fields: subFieldNodes, + groupedFieldSet: subGroupedFieldSet, patches: subPatches, }; @@ -109,7 +109,7 @@ export function collectSubfields( operation, returnType, node.selectionSet, - subFieldNodes, + subGroupedFieldSet, subPatches, visitedFragmentNames, ); @@ -126,7 +126,7 @@ function collectFieldsImpl( operation: OperationDefinitionNode, runtimeType: GraphQLObjectType, selectionSet: SelectionSetNode, - fields: AccumulatorMap, + groupedFieldSet: AccumulatorMap, patches: Array, visitedFragmentNames: Set, ): void { @@ -136,7 +136,7 @@ function collectFieldsImpl( if (!shouldIncludeNode(variableValues, selection)) { continue; } - fields.add(getFieldEntryKey(selection), selection); + groupedFieldSet.add(getFieldEntryKey(selection), selection); break; } case Kind.INLINE_FRAGMENT: { @@ -164,7 +164,7 @@ function collectFieldsImpl( ); patches.push({ label: defer.label, - fields: patchFields, + groupedFieldSet: patchFields, }); } else { collectFieldsImpl( @@ -174,7 +174,7 @@ function collectFieldsImpl( operation, runtimeType, selection.selectionSet, - fields, + groupedFieldSet, patches, visitedFragmentNames, ); @@ -220,7 +220,7 @@ function collectFieldsImpl( ); patches.push({ label: defer.label, - fields: patchFields, + groupedFieldSet: patchFields, }); } else { collectFieldsImpl( @@ -230,7 +230,7 @@ function collectFieldsImpl( operation, runtimeType, fragment.selectionSet, - fields, + groupedFieldSet, patches, visitedFragmentNames, ); diff --git a/src/execution/execute.ts b/src/execution/execute.ts index e1bc6a02cf..de4a305af1 100644 --- a/src/execution/execute.ts +++ b/src/execution/execute.ts @@ -536,7 +536,7 @@ function executeOperation( ); } - const { fields: rootFields, patches } = collectFields( + const { groupedFieldSet, patches } = collectFields( schema, fragments, variableValues, @@ -548,7 +548,13 @@ function executeOperation( switch (operation.operation) { case OperationTypeNode.QUERY: - result = executeFields(exeContext, rootType, rootValue, path, rootFields); + result = executeFields( + exeContext, + rootType, + rootValue, + path, + groupedFieldSet, + ); break; case OperationTypeNode.MUTATION: result = executeFieldsSerially( @@ -556,22 +562,28 @@ function executeOperation( rootType, rootValue, path, - rootFields, + groupedFieldSet, ); break; case OperationTypeNode.SUBSCRIPTION: // TODO: deprecate `subscribe` and move all logic here // Temporary solution until we finish merging execute and subscribe together - result = executeFields(exeContext, rootType, rootValue, path, rootFields); + result = executeFields( + exeContext, + rootType, + rootValue, + path, + groupedFieldSet, + ); } for (const patch of patches) { - const { label, fields: patchFields } = patch; + const { label, groupedFieldSet: patchGroupedFieldSet } = patch; executeDeferredFragment( exeContext, rootType, rootValue, - patchFields, + patchGroupedFieldSet, label, path, ); @@ -1447,28 +1459,25 @@ function collectAndExecuteSubfields( asyncPayloadRecord?: AsyncPayloadRecord, ): PromiseOrValue> { // Collect sub-fields to execute to complete this value. - const { fields: subFieldNodes, patches: subPatches } = collectSubfields( - exeContext, - returnType, - fieldGroup, - ); + const { groupedFieldSet: subGroupedFieldSet, patches: subPatches } = + collectSubfields(exeContext, returnType, fieldGroup); const subFields = executeFields( exeContext, returnType, result, path, - subFieldNodes, + subGroupedFieldSet, asyncPayloadRecord, ); for (const subPatch of subPatches) { - const { label, fields: subPatchFieldNodes } = subPatch; + const { label, groupedFieldSet: subPatchGroupedFieldSet } = subPatch; executeDeferredFragment( exeContext, returnType, result, - subPatchFieldNodes, + subPatchGroupedFieldSet, label, path, asyncPayloadRecord, @@ -1691,7 +1700,7 @@ function executeSubscription( ); } - const { fields: rootFields } = collectFields( + const { groupedFieldSet } = collectFields( schema, fragments, variableValues, @@ -1699,7 +1708,7 @@ function executeSubscription( operation, ); - const firstRootField = rootFields.entries().next().value; + const firstRootField = groupedFieldSet.entries().next().value; const [responseName, fieldGroup] = firstRootField; const fieldName = fieldGroup[0].name.value; const fieldDef = schema.getField(rootType, fieldName); diff --git a/src/validation/rules/SingleFieldSubscriptionsRule.ts b/src/validation/rules/SingleFieldSubscriptionsRule.ts index 9830f14428..c6cd93ab58 100644 --- a/src/validation/rules/SingleFieldSubscriptionsRule.ts +++ b/src/validation/rules/SingleFieldSubscriptionsRule.ts @@ -41,15 +41,15 @@ export function SingleFieldSubscriptionsRule( fragments[definition.name.value] = definition; } } - const { fields } = collectFields( + const { groupedFieldSet } = collectFields( schema, fragments, variableValues, subscriptionType, node, ); - if (fields.size > 1) { - const fieldSelectionLists = [...fields.values()]; + if (groupedFieldSet.size > 1) { + const fieldSelectionLists = [...groupedFieldSet.values()]; const extraFieldSelectionLists = fieldSelectionLists.slice(1); const extraFieldSelections = extraFieldSelectionLists.flat(); context.reportError( @@ -61,7 +61,7 @@ export function SingleFieldSubscriptionsRule( ), ); } - for (const fieldGroup of fields.values()) { + for (const fieldGroup of groupedFieldSet.values()) { const fieldName = fieldGroup[0].name.value; if (fieldName.startsWith('__')) { context.reportError( From ccca251a5f0d6f41e19379c5f7fc4a8c27497d7f Mon Sep 17 00:00:00 2001 From: Yaacov Rydzinski Date: Tue, 4 Apr 2023 11:46:09 +0300 Subject: [PATCH 5/6] refactor handleFieldError = integrate locatedError, which was always called on the input = avoid constant return value, which causes return value to hide value of this constant = add optional asyncPayloadRecord parameter so that caller does not have to supply errors list --- src/execution/execute.ts | 149 ++++++++++++++++++++++++++------------- 1 file changed, 100 insertions(+), 49 deletions(-) diff --git a/src/execution/execute.ts b/src/execution/execute.ts index de4a305af1..fcd414e806 100644 --- a/src/execution/execute.ts +++ b/src/execution/execute.ts @@ -699,7 +699,6 @@ function executeField( path: Path, asyncPayloadRecord?: AsyncPayloadRecord, ): PromiseOrValue { - const errors = asyncPayloadRecord?.errors ?? exeContext.errors; const fieldName = fieldGroup[0].name.value; const fieldDef = exeContext.schema.getField(parentType, fieldName); if (!fieldDef) { @@ -761,18 +760,30 @@ function executeField( // Note: we don't rely on a `catch` method, but we do expect "thenable" // to take a second callback for the error case. return completed.then(undefined, (rawError) => { - const error = locatedError(rawError, fieldGroup, pathToArray(path)); - const handledError = handleFieldError(error, returnType, errors); + handleFieldError( + rawError, + exeContext, + returnType, + fieldGroup, + path, + asyncPayloadRecord, + ); filterSubsequentPayloads(exeContext, path, asyncPayloadRecord); - return handledError; + return null; }); } return completed; } catch (rawError) { - const error = locatedError(rawError, fieldGroup, pathToArray(path)); - const handledError = handleFieldError(error, returnType, errors); + handleFieldError( + rawError, + exeContext, + returnType, + fieldGroup, + path, + asyncPayloadRecord, + ); filterSubsequentPayloads(exeContext, path, asyncPayloadRecord); - return handledError; + return null; } } @@ -804,20 +815,26 @@ export function buildResolveInfo( } function handleFieldError( - error: GraphQLError, + rawError: unknown, + exeContext: ExecutionContext, returnType: GraphQLOutputType, - errors: Array, -): null { + fieldGroup: FieldGroup, + path: Path, + asyncPayloadRecord?: AsyncPayloadRecord | undefined, +): void { + const error = locatedError(rawError, fieldGroup, pathToArray(path)); + // If the field type is non-nullable, then it is resolved without any // protection from errors, however it still properly locates the error. if (isNonNullType(returnType)) { throw error; } + const errors = asyncPayloadRecord?.errors ?? exeContext.errors; + // Otherwise, error protection is applied, logging the error and resolving // a null value for this field if one is encountered. errors.push(error); - return null; } /** @@ -958,11 +975,16 @@ async function completePromisedValue( } return completed; } catch (rawError) { - const errors = asyncPayloadRecord?.errors ?? exeContext.errors; - const error = locatedError(rawError, fieldGroup, pathToArray(path)); - const handledError = handleFieldError(error, returnType, errors); + handleFieldError( + rawError, + exeContext, + returnType, + fieldGroup, + path, + asyncPayloadRecord, + ); filterSubsequentPayloads(exeContext, path, asyncPayloadRecord); - return handledError; + return null; } } @@ -1036,7 +1058,6 @@ async function completeAsyncIteratorValue( iterator: AsyncIterator, asyncPayloadRecord?: AsyncPayloadRecord, ): Promise> { - const errors = asyncPayloadRecord?.errors ?? exeContext.errors; const stream = getStreamValues(exeContext, fieldGroup, path); let containsPromise = false; const completedResults: Array = []; @@ -1072,8 +1093,15 @@ async function completeAsyncIteratorValue( break; } } catch (rawError) { - const error = locatedError(rawError, fieldGroup, pathToArray(itemPath)); - completedResults.push(handleFieldError(error, itemType, errors)); + handleFieldError( + rawError, + exeContext, + itemType, + fieldGroup, + itemPath, + asyncPayloadRecord, + ); + completedResults.push(null); break; } @@ -1081,7 +1109,6 @@ async function completeAsyncIteratorValue( completeListItemValue( iteration.value, completedResults, - errors, exeContext, itemType, fieldGroup, @@ -1111,7 +1138,6 @@ function completeListValue( asyncPayloadRecord?: AsyncPayloadRecord, ): PromiseOrValue> { const itemType = returnType.ofType; - const errors = asyncPayloadRecord?.errors ?? exeContext.errors; if (isAsyncIterable(result)) { const iterator = result[Symbol.asyncIterator](); @@ -1170,7 +1196,6 @@ function completeListValue( completeListItemValue( item, completedResults, - errors, exeContext, itemType, fieldGroup, @@ -1196,7 +1221,6 @@ function completeListValue( function completeListItemValue( item: unknown, completedResults: Array, - errors: Array, exeContext: ExecutionContext, itemType: GraphQLOutputType, fieldGroup: FieldGroup, @@ -1236,14 +1260,16 @@ function completeListItemValue( // to take a second callback for the error case. completedResults.push( completedItem.then(undefined, (rawError) => { - const error = locatedError( + handleFieldError( rawError, + exeContext, + itemType, fieldGroup, - pathToArray(itemPath), + itemPath, + asyncPayloadRecord, ); - const handledError = handleFieldError(error, itemType, errors); filterSubsequentPayloads(exeContext, itemPath, asyncPayloadRecord); - return handledError; + return null; }), ); @@ -1252,10 +1278,16 @@ function completeListItemValue( completedResults.push(completedItem); } catch (rawError) { - const error = locatedError(rawError, fieldGroup, pathToArray(itemPath)); - const handledError = handleFieldError(error, itemType, errors); + handleFieldError( + rawError, + exeContext, + itemType, + fieldGroup, + itemPath, + asyncPayloadRecord, + ); filterSubsequentPayloads(exeContext, itemPath, asyncPayloadRecord); - completedResults.push(handledError); + completedResults.push(null); } return false; @@ -1866,12 +1898,15 @@ function executeStreamField( asyncPayloadRecord, ); } catch (rawError) { - const error = locatedError(rawError, fieldGroup, pathToArray(itemPath)); - completedItem = handleFieldError( - error, + handleFieldError( + rawError, + exeContext, itemType, - asyncPayloadRecord.errors, + fieldGroup, + itemPath, + asyncPayloadRecord, ); + completedItem = null; filterSubsequentPayloads(exeContext, itemPath, asyncPayloadRecord); } } catch (error) { @@ -1884,14 +1919,16 @@ function executeStreamField( if (isPromise(completedItem)) { const completedItems = completedItem .then(undefined, (rawError) => { - const error = locatedError(rawError, fieldGroup, pathToArray(itemPath)); - const handledError = handleFieldError( - error, + handleFieldError( + rawError, + exeContext, itemType, - asyncPayloadRecord.errors, + fieldGroup, + itemPath, + asyncPayloadRecord, ); filterSubsequentPayloads(exeContext, itemPath, asyncPayloadRecord); - return handledError; + return null; }) .then( (value) => [value], @@ -1928,10 +1965,16 @@ async function executeStreamIteratorItem( } item = value; } catch (rawError) { - const error = locatedError(rawError, fieldGroup, pathToArray(itemPath)); - const value = handleFieldError(error, itemType, asyncPayloadRecord.errors); + handleFieldError( + rawError, + exeContext, + itemType, + fieldGroup, + itemPath, + asyncPayloadRecord, + ); // don't continue if iterator throws - return { done: true, value }; + return { done: true, value: null }; } let completedItem; try { @@ -1947,22 +1990,30 @@ async function executeStreamIteratorItem( if (isPromise(completedItem)) { completedItem = completedItem.then(undefined, (rawError) => { - const error = locatedError(rawError, fieldGroup, pathToArray(itemPath)); - const handledError = handleFieldError( - error, + handleFieldError( + rawError, + exeContext, itemType, - asyncPayloadRecord.errors, + fieldGroup, + itemPath, + asyncPayloadRecord, ); filterSubsequentPayloads(exeContext, itemPath, asyncPayloadRecord); - return handledError; + return null; }); } return { done: false, value: completedItem }; } catch (rawError) { - const error = locatedError(rawError, fieldGroup, pathToArray(itemPath)); - const value = handleFieldError(error, itemType, asyncPayloadRecord.errors); + handleFieldError( + rawError, + exeContext, + itemType, + fieldGroup, + itemPath, + asyncPayloadRecord, + ); filterSubsequentPayloads(exeContext, itemPath, asyncPayloadRecord); - return { done: false, value }; + return { done: false, value: null }; } } From 566c29e2d2a9ed9c9b5a00dcc005b58c0da9c8ea Mon Sep 17 00:00:00 2001 From: Yaacov Rydzinski Date: Tue, 4 Apr 2023 12:41:04 +0300 Subject: [PATCH 6/6] rename executeStreamIterator to executeStreamAsyncIterator --- src/execution/execute.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/execution/execute.ts b/src/execution/execute.ts index fcd414e806..df048480ba 100644 --- a/src/execution/execute.ts +++ b/src/execution/execute.ts @@ -1070,7 +1070,7 @@ async function completeAsyncIteratorValue( index >= stream.initialCount ) { // eslint-disable-next-line @typescript-eslint/no-floating-promises - executeStreamIterator( + executeStreamAsyncIterator( index, iterator, exeContext, @@ -1947,7 +1947,7 @@ function executeStreamField( return asyncPayloadRecord; } -async function executeStreamIteratorItem( +async function executeStreamAsyncIteratorItem( iterator: AsyncIterator, exeContext: ExecutionContext, fieldGroup: FieldGroup, @@ -2017,7 +2017,7 @@ async function executeStreamIteratorItem( } } -async function executeStreamIterator( +async function executeStreamAsyncIterator( initialIndex: number, iterator: AsyncIterator, exeContext: ExecutionContext, @@ -2044,7 +2044,7 @@ async function executeStreamIterator( let iteration; try { // eslint-disable-next-line no-await-in-loop - iteration = await executeStreamIteratorItem( + iteration = await executeStreamAsyncIteratorItem( iterator, exeContext, fieldGroup,