Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use object for GraphQLWrappedResult instead of tuple #4265

Merged
merged 1 commit into from
Oct 29, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 83 additions & 65 deletions src/execution/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,10 @@ export interface StreamUsage {
fieldDetailsList: FieldDetailsList;
}

type GraphQLWrappedResult<T> = [T, Array<IncrementalDataRecord> | undefined];
interface GraphQLWrappedResult<T> {
rawResult: T;
incrementalDataRecords: Array<IncrementalDataRecord> | undefined;
}

const UNEXPECTED_EXPERIMENTAL_DIRECTIVES =
'The provided schema unexpectedly contains experimental directives (@defer or @stream). These directives may only be utilized if experimental execution features are explicitly enabled.';
Expand Down Expand Up @@ -360,18 +363,14 @@ export function experimentalExecuteQueryOrMutationOrSubscriptionEvent(

if (isPromise(graphqlWrappedResult)) {
return graphqlWrappedResult.then(
(resolved) => buildDataResponse(exeContext, resolved[0], resolved[1]),
(resolved) => buildDataResponse(exeContext, resolved),
(error: unknown) => ({
data: null,
errors: withError(exeContext.errors, error as GraphQLError),
}),
);
}
return buildDataResponse(
exeContext,
graphqlWrappedResult[0],
graphqlWrappedResult[1],
);
return buildDataResponse(exeContext, graphqlWrappedResult);
} catch (error) {
return { data: null, errors: withError(exeContext.errors, error) };
}
Expand Down Expand Up @@ -442,10 +441,10 @@ function addIncrementalDataRecords(
if (incrementalDataRecords === undefined) {
return;
}
if (graphqlWrappedResult[1] === undefined) {
graphqlWrappedResult[1] = [...incrementalDataRecords];
if (graphqlWrappedResult.incrementalDataRecords === undefined) {
graphqlWrappedResult.incrementalDataRecords = [...incrementalDataRecords];
} else {
graphqlWrappedResult[1].push(...incrementalDataRecords);
graphqlWrappedResult.incrementalDataRecords.push(...incrementalDataRecords);
}
}

Expand All @@ -458,9 +457,9 @@ function withError(

function buildDataResponse(
exeContext: ExecutionContext,
data: ObjMap<unknown>,
incrementalDataRecords: ReadonlyArray<IncrementalDataRecord> | undefined,
graphqlWrappedResult: GraphQLWrappedResult<ObjMap<unknown>>,
): ExecutionResult | ExperimentalIncrementalExecutionResults {
const { rawResult: data, incrementalDataRecords } = graphqlWrappedResult;
const errors = exeContext.errors;
if (incrementalDataRecords === undefined) {
return errors !== undefined ? { errors, data } : { data };
Expand Down Expand Up @@ -675,7 +674,7 @@ function executeFieldsSerially(
fieldPath,
incrementalContext,
);
graphqlWrappedResult[0][responseName] = null;
graphqlWrappedResult.rawResult[responseName] = null;
return graphqlWrappedResult;
}

Expand All @@ -693,16 +692,25 @@ function executeFieldsSerially(
}
if (isPromise(result)) {
return result.then((resolved) => {
graphqlWrappedResult[0][responseName] = resolved[0];
addIncrementalDataRecords(graphqlWrappedResult, resolved[1]);
graphqlWrappedResult.rawResult[responseName] = resolved.rawResult;
addIncrementalDataRecords(
graphqlWrappedResult,
resolved.incrementalDataRecords,
);
return graphqlWrappedResult;
});
}
graphqlWrappedResult[0][responseName] = result[0];
addIncrementalDataRecords(graphqlWrappedResult, result[1]);
graphqlWrappedResult.rawResult[responseName] = result.rawResult;
addIncrementalDataRecords(
graphqlWrappedResult,
result.incrementalDataRecords,
);
return graphqlWrappedResult;
},
[Object.create(null), undefined] as GraphQLWrappedResult<ObjMap<unknown>>,
{
rawResult: Object.create(null),
incrementalDataRecords: undefined,
},
);
}

Expand All @@ -720,10 +728,10 @@ function executeFields(
deferMap: ReadonlyMap<DeferUsage, DeferredFragmentRecord> | undefined,
): PromiseOrValue<GraphQLWrappedResult<ObjMap<unknown>>> {
const results = Object.create(null);
const graphqlWrappedResult: GraphQLWrappedResult<ObjMap<unknown>> = [
results,
undefined,
];
const graphqlWrappedResult: GraphQLWrappedResult<ObjMap<unknown>> = {
rawResult: results,
incrementalDataRecords: undefined,
};
let containsPromise = false;

try {
Expand All @@ -742,13 +750,19 @@ function executeFields(
if (result !== undefined) {
if (isPromise(result)) {
results[responseName] = result.then((resolved) => {
addIncrementalDataRecords(graphqlWrappedResult, resolved[1]);
return resolved[0];
addIncrementalDataRecords(
graphqlWrappedResult,
resolved.incrementalDataRecords,
);
return resolved.rawResult;
});
containsPromise = true;
} else {
results[responseName] = result[0];
addIncrementalDataRecords(graphqlWrappedResult, result[1]);
results[responseName] = result.rawResult;
addIncrementalDataRecords(
graphqlWrappedResult,
result.incrementalDataRecords,
);
}
}
}
Expand All @@ -772,10 +786,10 @@ function executeFields(
// Otherwise, results is a map from field name to the result of resolving that
// field, which is possibly a promise. Return a promise that will return this
// same map, but with any promises replaced with the values they resolved to.
return promiseForObject(results, (resolved) => [
resolved,
graphqlWrappedResult[1],
]);
return promiseForObject(results, (resolved) => ({
rawResult: resolved,
incrementalDataRecords: graphqlWrappedResult.incrementalDataRecords,
}));
}

function toNodes(fieldDetailsList: FieldDetailsList): ReadonlyArray<FieldNode> {
Expand Down Expand Up @@ -871,7 +885,7 @@ function executeField(
path,
incrementalContext,
);
return [null, undefined];
return { rawResult: null, incrementalDataRecords: undefined };
});
}
return completed;
Expand All @@ -884,7 +898,7 @@ function executeField(
path,
incrementalContext,
);
return [null, undefined];
return { rawResult: null, incrementalDataRecords: undefined };
}
}

Expand Down Expand Up @@ -997,7 +1011,7 @@ function completeValue(
incrementalContext,
deferMap,
);
if ((completed as GraphQLWrappedResult<unknown>)[0] === null) {
if ((completed as GraphQLWrappedResult<unknown>).rawResult === null) {
throw new Error(
`Cannot return null for non-nullable field ${info.parentType}.${info.fieldName}.`,
);
Expand All @@ -1007,7 +1021,7 @@ function completeValue(

// If result value is null or undefined then return null.
if (result == null) {
return [null, undefined];
return { rawResult: null, incrementalDataRecords: undefined };
}

// If field type is List, complete each item in the list with the inner type
Expand All @@ -1027,7 +1041,10 @@ function completeValue(
// If field type is a leaf type, Scalar or Enum, coerce to a valid value,
// returning null if coercion is not possible.
if (isLeafType(returnType)) {
return [completeLeafValue(returnType, result), undefined];
return {
rawResult: completeLeafValue(returnType, result),
incrementalDataRecords: undefined,
};
}

// If field type is an abstract type, Interface or Union, determine the
Expand Down Expand Up @@ -1103,7 +1120,7 @@ async function completePromisedValue(
path,
incrementalContext,
);
return [null, undefined];
return { rawResult: null, incrementalDataRecords: undefined };
}
}

Expand Down Expand Up @@ -1201,10 +1218,10 @@ async function completeAsyncIteratorValue(
): Promise<GraphQLWrappedResult<ReadonlyArray<unknown>>> {
let containsPromise = false;
const completedResults: Array<unknown> = [];
const graphqlWrappedResult: GraphQLWrappedResult<Array<unknown>> = [
completedResults,
undefined,
];
const graphqlWrappedResult: GraphQLWrappedResult<Array<unknown>> = {
rawResult: completedResults,
incrementalDataRecords: undefined,
};
let index = 0;
const streamUsage = getStreamUsage(
exeContext.validatedExecutionArgs,
Expand Down Expand Up @@ -1323,10 +1340,10 @@ async function completeAsyncIteratorValue(
}

return containsPromise
? /* c8 ignore start */ Promise.all(completedResults).then((resolved) => [
resolved,
graphqlWrappedResult[1],
])
? /* c8 ignore start */ Promise.all(completedResults).then((resolved) => ({
rawResult: resolved,
incrementalDataRecords: graphqlWrappedResult.incrementalDataRecords,
}))
: /* c8 ignore stop */ graphqlWrappedResult;
}

Expand Down Expand Up @@ -1393,10 +1410,10 @@ function completeIterableValue(
// where the list contains no Promises by avoiding creating another Promise.
let containsPromise = false;
const completedResults: Array<unknown> = [];
const graphqlWrappedResult: GraphQLWrappedResult<Array<unknown>> = [
completedResults,
undefined,
];
const graphqlWrappedResult: GraphQLWrappedResult<Array<unknown>> = {
rawResult: completedResults,
incrementalDataRecords: undefined,
};
let index = 0;
const streamUsage = getStreamUsage(
exeContext.validatedExecutionArgs,
Expand Down Expand Up @@ -1469,10 +1486,10 @@ function completeIterableValue(
}

return containsPromise
? Promise.all(completedResults).then((resolved) => [
resolved,
graphqlWrappedResult[1],
])
? Promise.all(completedResults).then((resolved) => ({
rawResult: resolved,
incrementalDataRecords: graphqlWrappedResult.incrementalDataRecords,
}))
: graphqlWrappedResult;
}

Expand Down Expand Up @@ -1511,8 +1528,8 @@ function completeListItemValue(
completedResults.push(
completedItem.then(
(resolved) => {
addIncrementalDataRecords(parent, resolved[1]);
return resolved[0];
addIncrementalDataRecords(parent, resolved.incrementalDataRecords);
return resolved.rawResult;
},
(rawError: unknown) => {
handleFieldError(
Expand All @@ -1530,8 +1547,8 @@ function completeListItemValue(
return true;
}

completedResults.push(completedItem[0]);
addIncrementalDataRecords(parent, completedItem[1]);
completedResults.push(completedItem.rawResult);
addIncrementalDataRecords(parent, completedItem.incrementalDataRecords);
} catch (rawError) {
handleFieldError(
rawError,
Expand Down Expand Up @@ -1572,8 +1589,8 @@ async function completePromisedListItemValue(
if (isPromise(completed)) {
completed = await completed;
}
addIncrementalDataRecords(parent, completed[1]);
return completed[0];
addIncrementalDataRecords(parent, completed.incrementalDataRecords);
return completed.rawResult;
} catch (rawError) {
handleFieldError(
rawError,
Expand Down Expand Up @@ -2343,12 +2360,12 @@ function buildCompletedExecutionGroup(
path: Path | undefined,
result: GraphQLWrappedResult<ObjMap<unknown>>,
): CompletedExecutionGroup {
const { rawResult: data, incrementalDataRecords } = result;
return {
pendingExecutionGroup,
path: pathToArray(path),
result:
errors === undefined ? { data: result[0] } : { data: result[0], errors },
incrementalDataRecords: result[1],
result: errors === undefined ? { data } : { data, errors },
incrementalDataRecords,
};
}

Expand Down Expand Up @@ -2583,7 +2600,7 @@ function completeStreamItem(
itemPath,
incrementalContext,
);
result = [null, undefined];
result = { rawResult: null, incrementalDataRecords: undefined };
}
} catch (error) {
return {
Expand All @@ -2602,7 +2619,7 @@ function completeStreamItem(
itemPath,
incrementalContext,
);
return [null, undefined] as GraphQLWrappedResult<unknown>;
return { rawResult: null, incrementalDataRecords: undefined };
})
.then(
(resolvedItem) =>
Expand All @@ -2620,9 +2637,10 @@ function buildStreamItemResult(
errors: ReadonlyArray<GraphQLError> | undefined,
result: GraphQLWrappedResult<unknown>,
): StreamItemResult {
const { rawResult: item, incrementalDataRecords } = result;
return {
item: result[0],
item,
errors,
incrementalDataRecords: result[1],
incrementalDataRecords,
};
}
Loading