Skip to content

Commit 11cc52a

Browse files
committed
EPR resolveField
1 parent d40432f commit 11cc52a

File tree

1 file changed

+54
-31
lines changed

1 file changed

+54
-31
lines changed

src/execution/execute.js

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -520,17 +520,23 @@ function executeFieldsSerially(
520520
fieldNodes,
521521
fieldPath,
522522
);
523-
if (result === undefined) {
523+
if (result === null) {
524524
return results;
525525
}
526526
const promise = getPromise(result);
527527
if (promise) {
528528
return promise.then(resolvedResult => {
529-
results[responseName] = resolvedResult;
529+
if (resolvedResult.errors && resolvedResult.errors.length) {
530+
exeContext.errors.push.apply(exeContext.errors, resolvedResult.errors);
531+
}
532+
results[responseName] = resolvedResult.data;
530533
return results;
531534
});
532535
}
533-
results[responseName] = result;
536+
if (result.errors && result.errors.length) {
537+
exeContext.errors.push.apply(exeContext.errors, result.errors);
538+
}
539+
results[responseName] = result.data;
534540
return results;
535541
}),
536542
Promise.resolve({}),
@@ -560,7 +566,7 @@ function executeFields(
560566
fieldNodes,
561567
fieldPath,
562568
);
563-
if (result === undefined) {
569+
if (result === null) {
564570
return results;
565571
}
566572
results[responseName] = result;
@@ -572,14 +578,40 @@ function executeFields(
572578

573579
// If there are no promises, we can just return the object
574580
if (!containsPromise) {
575-
return finalResults;
581+
const merged = mergeEPRs(finalResults);
582+
if (merged.errors && merged.errors.length) {
583+
exeContext.errors.push.apply(exeContext.errors, merged.errors);
584+
}
585+
return merged.data;
576586
}
577587

578588
// Otherwise, results is a map from field name to the result
579589
// of resolving that field, which is possibly a promise. Return
580590
// a promise that will return this same map, but with any
581591
// promises replaced with the values they resolved to.
582-
return promiseForObject(finalResults);
592+
return promiseForObject(finalResults).then(merged => {
593+
if (merged.errors && merged.errors.length) {
594+
exeContext.errors.push.apply(exeContext.errors, merged.errors);
595+
}
596+
return merged.data;
597+
});
598+
}
599+
600+
function mergeEPRs(
601+
eprMap: ObjMap<ExecutionPartialResult<mixed>>,
602+
): ExecutionPartialResult<mixed> {
603+
const keys = Object.keys(eprMap);
604+
const values = keys.map(name => eprMap[name]);
605+
return values.reduce(
606+
(merged, value, i) => {
607+
merged.data[keys[i]] = value.data;
608+
if (value.errors && value.errors.length) {
609+
merged.errors.push.apply(merged.errors, value.errors);
610+
}
611+
return merged;
612+
},
613+
{ data: Object.create(null), errors: [] },
614+
);
583615
}
584616

585617
/**
@@ -705,21 +737,25 @@ function doesFragmentConditionMatch(
705737
}
706738

707739
/**
708-
* This function transforms a JS object `ObjMap<Promise<T>>` into
709-
* a `Promise<ObjMap<T>>`
740+
* This function transforms a JS object `ObjMap<ExecutionPartialResult<T>>` into
741+
* a `ExecutionPartialResult<T>`
710742
*
711743
* This is akin to bluebird's `Promise.props`, but implemented only using
712744
* `Promise.all` so it will work with any implementation of ES6 promises.
713745
*/
714-
function promiseForObject<T>(object: ObjMap<Promise<T>>): Promise<ObjMap<T>> {
746+
function promiseForObject<T>(
747+
object: ObjMap<ExecutionPartialResult<T>>,
748+
): ExecutionPartialResult<T> {
715749
const keys = Object.keys(object);
716750
const valuesAndPromises = keys.map(name => object[name]);
717-
return Promise.all(valuesAndPromises).then(values =>
718-
values.reduce((resolvedObject, value, i) => {
719-
resolvedObject[keys[i]] = value;
720-
return resolvedObject;
721-
}, Object.create(null)),
722-
);
751+
return Promise.all(valuesAndPromises)
752+
.then(values =>
753+
values.reduce((resolvedObject, value, i) => {
754+
resolvedObject[keys[i]] = value;
755+
return resolvedObject;
756+
}, Object.create(null)),
757+
)
758+
.then(valueMap => mergeEPRs(valueMap));
723759
}
724760

725761
/**
@@ -741,13 +777,13 @@ function resolveField(
741777
source: mixed,
742778
fieldNodes: $ReadOnlyArray<FieldNode>,
743779
path: ResponsePath,
744-
): mixed {
780+
): ExecutionPartialResult<mixed> | null {
745781
const fieldNode = fieldNodes[0];
746782
const fieldName = fieldNode.name.value;
747783

748784
const fieldDef = getFieldDef(exeContext.schema, parentType, fieldName);
749785
if (!fieldDef) {
750-
return;
786+
return null;
751787
}
752788

753789
const resolveFn = fieldDef.resolve || exeContext.fieldResolver;
@@ -771,27 +807,14 @@ function resolveField(
771807
info,
772808
);
773809

774-
const completed = completeValueCatchingError(
810+
return completeValueCatchingError(
775811
exeContext,
776812
fieldDef.type,
777813
fieldNodes,
778814
info,
779815
path,
780816
result,
781817
);
782-
const promise = getPromise(completed);
783-
if (promise) {
784-
return promise.then(r => {
785-
if (r.errors && r.errors.length) {
786-
exeContext.errors.push.apply(exeContext.errors, r.errors);
787-
}
788-
return r.data;
789-
});
790-
}
791-
if (completed.errors && completed.errors.length) {
792-
exeContext.errors.push.apply(exeContext.errors, completed.errors);
793-
}
794-
return completed.data;
795818
}
796819

797820
export function buildResolveInfo(

0 commit comments

Comments
 (0)