Skip to content

Commit 9ce4d26

Browse files
committed
EPRs to tuples
1 parent b765f23 commit 9ce4d26

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
@@ -108,13 +108,13 @@ export type ExecutionResult = {
108108
};
109109

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

119119
/**
120120
* A partial result of GraphQL execution. `data` and `errors` as above.
@@ -239,17 +239,17 @@ function executeImpl(
239239
}
240240

241241
/**
242-
* Strip out `errors` if empty.
242+
* Given a completed ExecutionPartialResult, build the { errors, data }
243+
* response defined by the "Response" section of the GraphQL specification.
243244
*/
244245
function buildResponse(result: ExecutionPartialResult<mixed>) {
245246
const promise = getPromise(result);
246247
if (promise) {
247248
return promise.then(resolved => buildResponse(resolved));
248249
}
249-
if (result.data && (!result.errors || !result.errors.length)) {
250-
return { data: result.data };
251-
}
252-
return result;
250+
return !result[1] || result[1].length === 0
251+
? { data: result[0] }
252+
: { data: result[0], errors: result[1] };
253253
}
254254

255255
/**
@@ -418,14 +418,11 @@ function executeOperation(
418418
: executeFields(exeContext, type, rootValue, path, fields);
419419
const promise = getPromise(result);
420420
if (promise) {
421-
return promise.then(undefined, error => ({
422-
data: null,
423-
errors: [error],
424-
}));
421+
return promise.then(undefined, error => [null, [error]]);
425422
}
426423
return result;
427424
} catch (error) {
428-
return { data: null, errors: [error] };
425+
return [null, [error]];
429426
}
430427
}
431428

@@ -564,13 +561,13 @@ function mergeEPRs(
564561
const values = keys.map(name => eprMap[name]);
565562
return values.reduce(
566563
(merged, value, i) => {
567-
merged.data[keys[i]] = value.data;
568-
if (value.errors && value.errors.length) {
569-
merged.errors.push(...value.errors);
564+
merged[0][keys[i]] = value[0];
565+
if (value[1] && value[1].length) {
566+
merged[1].push(...value[1]);
570567
}
571568
return merged;
572569
},
573-
{ data: Object.create(null), errors: [] },
570+
[Object.create(null), []],
574571
);
575572
}
576573

@@ -879,16 +876,13 @@ function completeValueCatchingError(
879876
// the rejection error and resolve to null.
880877
// Note: we don't rely on a `catch` method, but we do expect "thenable"
881878
// to take a second callback for the error case.
882-
return promise.then(undefined, error => ({
883-
data: null,
884-
errors: [error],
885-
}));
879+
return promise.then(undefined, error => [null, [error]]);
886880
}
887881
return completed;
888882
} catch (error) {
889883
// If `completeValueWithLocatedError` returned abruptly (threw an error),
890884
// log the error and return null.
891-
return { data: null, errors: [error] };
885+
return [null, [error]];
892886
}
893887
}
894888

@@ -986,7 +980,7 @@ function completeValue(
986980
path,
987981
result,
988982
);
989-
if (completed.data === null) {
983+
if (completed[0] === null) {
990984
throw new Error(
991985
`Cannot return null for non-nullable field ${info.parentType.name}.${
992986
info.fieldName
@@ -998,7 +992,7 @@ function completeValue(
998992

999993
// If result value is null-ish (null, undefined, or NaN) then return null.
1000994
if (isNullish(result)) {
1001-
return { data: null };
995+
return [null, null];
1002996
}
1003997

1004998
// If field type is List, complete each item in the list with the inner type
@@ -1016,7 +1010,7 @@ function completeValue(
10161010
// If field type is a leaf type, Scalar or Enum, serialize to a valid value,
10171011
// returning null if serialization is not possible.
10181012
if (isLeafType(returnType)) {
1019-
return { data: completeLeafValue(returnType, result) };
1013+
return [completeLeafValue(returnType, result), null];
10201014
}
10211015

10221016
// If field type is an abstract type, Interface or Union, determine the
@@ -1107,12 +1101,12 @@ function flattenEPRs(
11071101
const errors = [];
11081102
const data = [];
11091103
forEach((eprs: any), item => {
1110-
data.push(item.data);
1111-
if (item.errors && item.errors.length) {
1112-
errors.push(...item.errors);
1104+
data.push(item[0]);
1105+
if (item[1] && item[1].length) {
1106+
errors.push(...item[1]);
11131107
}
11141108
});
1115-
return { data, errors };
1109+
return [data, errors.length ? errors : null];
11161110
}
11171111

11181112
/**

0 commit comments

Comments
 (0)