Skip to content

Commit 8a3a34a

Browse files
committed
EPRs to tuples
1 parent 062f606 commit 8a3a34a

File tree

1 file changed

+26
-32
lines changed

1 file changed

+26
-32
lines changed

src/execution/execute.js

Lines changed: 26 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,13 @@ export type ExecutionResult = {
109109
};
110110

111111
/**
112-
* A partial result of GraphQL execution. `data` and `errors` as above.
113-
* "NP" = "Not Promise".
112+
* A partial result of GraphQL execution. `data` and `errors` as above, but
113+
* tuple to avoid allocating/destroying objects. "NP" = "Not Promise".
114114
*/
115-
export type ExecutionPartialResultNP<T> = {
116-
errors?: $ReadOnlyArray<GraphQLError>,
117-
data?: T | null,
118-
};
115+
export type ExecutionPartialResultNP<T> = [
116+
T | null,
117+
$ReadOnlyArray<GraphQLError> | null,
118+
];
119119

120120
/**
121121
* A partial result of GraphQL execution. `data` and `errors` as above.
@@ -234,17 +234,17 @@ function executeImpl(
234234
}
235235

236236
/**
237-
* Strip out `errors` if empty.
237+
* Given a completed ExecutionPartialResult, build the { errors, data }
238+
* response defined by the "Response" section of the GraphQL specification.
238239
*/
239240
function buildResponse(result: ExecutionPartialResult<mixed>) {
240241
const promise = getPromise(result);
241242
if (promise) {
242243
return promise.then(resolved => buildResponse(resolved));
243244
}
244-
if (result.data && (!result.errors || !result.errors.length)) {
245-
return { data: result.data };
246-
}
247-
return result;
245+
return !result[1] || result[1].length === 0
246+
? { data: result[0] }
247+
: { data: result[0], errors: result[1] };
248248
}
249249

250250
/**
@@ -413,14 +413,11 @@ function executeOperation(
413413
: executeFields(exeContext, type, rootValue, path, fields);
414414
const promise = getPromise(result);
415415
if (promise) {
416-
return promise.then(undefined, error => ({
417-
data: null,
418-
errors: [error],
419-
}));
416+
return promise.then(undefined, error => [null, [error]]);
420417
}
421418
return result;
422419
} catch (error) {
423-
return { data: null, errors: [error] };
420+
return [null, [error]];
424421
}
425422
}
426423

@@ -559,13 +556,13 @@ function mergeEPRs(
559556
const values = keys.map(name => eprMap[name]);
560557
return values.reduce(
561558
(merged, value, i) => {
562-
merged.data[keys[i]] = value.data;
563-
if (value.errors && value.errors.length) {
564-
merged.errors.push(...value.errors);
559+
merged[0][keys[i]] = value[0];
560+
if (value[1] && value[1].length) {
561+
merged[1].push(...value[1]);
565562
}
566563
return merged;
567564
},
568-
{ data: Object.create(null), errors: [] },
565+
[Object.create(null), []],
569566
);
570567
}
571568

@@ -874,16 +871,13 @@ function completeValueCatchingError(
874871
// the rejection error and resolve to null.
875872
// Note: we don't rely on a `catch` method, but we do expect "thenable"
876873
// to take a second callback for the error case.
877-
return promise.then(undefined, error => ({
878-
data: null,
879-
errors: [error],
880-
}));
874+
return promise.then(undefined, error => [null, [error]]);
881875
}
882876
return completed;
883877
} catch (error) {
884878
// If `completeValueWithLocatedError` returned abruptly (threw an error),
885879
// log the error and return null.
886-
return { data: null, errors: [error] };
880+
return [null, [error]];
887881
}
888882
}
889883

@@ -981,7 +975,7 @@ function completeValue(
981975
path,
982976
result,
983977
);
984-
if (completed.data === null) {
978+
if (completed[0] === null) {
985979
throw new Error(
986980
`Cannot return null for non-nullable field ${info.parentType.name}.${
987981
info.fieldName
@@ -993,7 +987,7 @@ function completeValue(
993987

994988
// If result value is null-ish (null, undefined, or NaN) then return null.
995989
if (isNullish(result)) {
996-
return { data: null };
990+
return [null, null];
997991
}
998992

999993
// If field type is List, complete each item in the list with the inner type
@@ -1011,7 +1005,7 @@ function completeValue(
10111005
// If field type is a leaf type, Scalar or Enum, serialize to a valid value,
10121006
// returning null if serialization is not possible.
10131007
if (isLeafType(returnType)) {
1014-
return { data: completeLeafValue(returnType, result) };
1008+
return [completeLeafValue(returnType, result), null];
10151009
}
10161010

10171011
// If field type is an abstract type, Interface or Union, determine the
@@ -1102,12 +1096,12 @@ function flattenEPRs(
11021096
const errors = [];
11031097
const data = [];
11041098
forEach((eprs: any), item => {
1105-
data.push(item.data);
1106-
if (item.errors && item.errors.length) {
1107-
errors.push(...item.errors);
1099+
data.push(item[0]);
1100+
if (item[1] && item[1].length) {
1101+
errors.push(...item[1]);
11081102
}
11091103
});
1110-
return { data, errors };
1104+
return [data, errors.length ? errors : null];
11111105
}
11121106

11131107
/**

0 commit comments

Comments
 (0)