@@ -108,13 +108,13 @@ export type ExecutionResult = {
108
108
} ;
109
109
110
110
/**
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".
113
113
*/
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
+ ] ;
118
118
119
119
/**
120
120
* A partial result of GraphQL execution. `data` and `errors` as above.
@@ -239,17 +239,17 @@ function executeImpl(
239
239
}
240
240
241
241
/**
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.
243
244
*/
244
245
function buildResponse ( result : ExecutionPartialResult < mixed > ) {
245
246
const promise = getPromise ( result ) ;
246
247
if ( promise ) {
247
248
return promise . then ( resolved => buildResponse ( resolved ) ) ;
248
249
}
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 ] } ;
253
253
}
254
254
255
255
/**
@@ -418,14 +418,11 @@ function executeOperation(
418
418
: executeFields ( exeContext , type , rootValue , path , fields ) ;
419
419
const promise = getPromise ( result ) ;
420
420
if ( promise ) {
421
- return promise . then ( undefined , error => ( {
422
- data : null ,
423
- errors : [ error ] ,
424
- } ) ) ;
421
+ return promise . then ( undefined , error => [ null , [ error ] ] ) ;
425
422
}
426
423
return result ;
427
424
} catch (error) {
428
- return { data : null , errors : [ error ] } ;
425
+ return [ null , [ error ] ] ;
429
426
}
430
427
}
431
428
@@ -564,13 +561,13 @@ function mergeEPRs(
564
561
const values = keys . map ( name => eprMap [ name ] ) ;
565
562
return values . reduce (
566
563
( 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 ] ) ;
570
567
}
571
568
return merged ;
572
569
} ,
573
- { data : Object . create ( null ) , errors : [ ] } ,
570
+ [ Object . create ( null ) , [ ] ] ,
574
571
) ;
575
572
}
576
573
@@ -879,16 +876,13 @@ function completeValueCatchingError(
879
876
// the rejection error and resolve to null.
880
877
// Note: we don't rely on a `catch` method, but we do expect "thenable"
881
878
// 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 ] ] ) ;
886
880
}
887
881
return completed ;
888
882
} catch ( error ) {
889
883
// If `completeValueWithLocatedError` returned abruptly (threw an error),
890
884
// log the error and return null.
891
- return { data : null , errors : [ error ] } ;
885
+ return [ null , [ error ] ] ;
892
886
}
893
887
}
894
888
@@ -986,7 +980,7 @@ function completeValue(
986
980
path ,
987
981
result ,
988
982
) ;
989
- if ( completed . data === null ) {
983
+ if ( completed [ 0 ] === null ) {
990
984
throw new Error (
991
985
`Cannot return null for non-nullable field ${ info . parentType . name } .${
992
986
info . fieldName
@@ -998,7 +992,7 @@ function completeValue(
998
992
999
993
// If result value is null-ish (null, undefined, or NaN) then return null.
1000
994
if ( isNullish ( result ) ) {
1001
- return { data : null } ;
995
+ return [ null , null ] ;
1002
996
}
1003
997
1004
998
// If field type is List, complete each item in the list with the inner type
@@ -1016,7 +1010,7 @@ function completeValue(
1016
1010
// If field type is a leaf type, Scalar or Enum, serialize to a valid value,
1017
1011
// returning null if serialization is not possible.
1018
1012
if ( isLeafType ( returnType ) ) {
1019
- return { data : completeLeafValue ( returnType , result ) } ;
1013
+ return [ completeLeafValue ( returnType , result ) , null ] ;
1020
1014
}
1021
1015
1022
1016
// If field type is an abstract type, Interface or Union, determine the
@@ -1107,12 +1101,12 @@ function flattenEPRs(
1107
1101
const errors = [ ] ;
1108
1102
const data = [ ] ;
1109
1103
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 ] ) ;
1113
1107
}
1114
1108
} ) ;
1115
- return { data , errors } ;
1109
+ return [ data , errors . length ? errors : null ] ;
1116
1110
}
1117
1111
1118
1112
/**
0 commit comments