Skip to content

Commit 965c3ff

Browse files
committed
Minor executor refactoring related to handling "resolve" errors
1 parent 83f4282 commit 965c3ff

File tree

1 file changed

+36
-27
lines changed

1 file changed

+36
-27
lines changed

src/Executor/Executor.php

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,13 @@ private static function shouldIncludeNode(ExecutionContext $exeContext, $directi
324324
*/
325325
private static function doesFragmentConditionMatch(ExecutionContext $exeContext,/* FragmentDefinition | InlineFragment*/ $fragment, ObjectType $type)
326326
{
327-
$conditionalType = Utils\TypeInfo::typeFromAST($exeContext->schema, $fragment->typeCondition);
327+
$typeConditionAST = $fragment->typeCondition;
328+
329+
if (!$typeConditionAST) {
330+
return true;
331+
}
332+
333+
$conditionalType = Utils\TypeInfo::typeFromAST($exeContext->schema, $typeConditionAST);
328334
if ($conditionalType === $type) {
329335
return true;
330336
}
@@ -394,22 +400,9 @@ private static function resolveField(ExecutionContext $exeContext, ObjectType $p
394400
'variableValues' => $exeContext->variableValues,
395401
]);
396402

397-
// If an error occurs while calling the field `resolve` function, ensure that
398-
// it is wrapped as a GraphQLError with locations. Log this error and return
399-
// null if allowed, otherwise throw the error so the parent field can handle
400-
// it.
401-
try {
402-
$result = call_user_func($resolveFn, $source, $args, $info);
403-
} catch (\Exception $error) {
404-
$reportedError = Error::createLocatedError($error, $fieldASTs);
405-
406-
if ($returnType instanceof NonNull) {
407-
throw $reportedError;
408-
}
409-
410-
$exeContext->addError($reportedError);
411-
return null;
412-
}
403+
// Get the resolve function, regardless of if its result is normal
404+
// or abrupt (error).
405+
$result = self::resolveOrError($resolveFn, $source, $args, $info);
413406

414407
return self::completeValueCatchingError(
415408
$exeContext,
@@ -420,6 +413,16 @@ private static function resolveField(ExecutionContext $exeContext, ObjectType $p
420413
);
421414
}
422415

416+
// Isolates the "ReturnOrAbrupt" behavior to not de-opt the `resolveField`
417+
// function. Returns the result of resolveFn or the abrupt-return Error object.
418+
private static function resolveOrError($resolveFn, $source, $args, $info)
419+
{
420+
try {
421+
return call_user_func($resolveFn, $source, $args, $info);
422+
} catch (\Exception $error) {
423+
return $error;
424+
}
425+
}
423426

424427
public static function completeValueCatchingError(
425428
ExecutionContext $exeContext,
@@ -440,6 +443,8 @@ public static function completeValueCatchingError(
440443
try {
441444
return self::completeValue($exeContext, $returnType, $fieldASTs, $info, $result);
442445
} catch (Error $err) {
446+
// If `completeValue` returned abruptly (threw an error), log the error
447+
// and return null.
443448
$exeContext->addError($err);
444449
return null;
445450
}
@@ -465,6 +470,10 @@ public static function completeValueCatchingError(
465470
*/
466471
private static function completeValue(ExecutionContext $exeContext, Type $returnType,/* Array<Field> */ $fieldASTs, ResolveInfo $info, &$result)
467472
{
473+
if ($result instanceof \Exception) {
474+
throw Error::createLocatedError($result, $fieldASTs);
475+
}
476+
468477
// If field type is NonNull, complete for inner type, and throw field error
469478
// if result is null.
470479
if ($returnType instanceof NonNull) {
@@ -514,29 +523,29 @@ private static function completeValue(ExecutionContext $exeContext, Type $return
514523

515524
// Field type must be Object, Interface or Union and expect sub-selections.
516525
if ($returnType instanceof ObjectType) {
517-
$objectType = $returnType;
526+
$runtimeType = $returnType;
518527
} else if ($returnType instanceof AbstractType) {
519-
$objectType = $returnType->getObjectType($result, $info);
528+
$runtimeType = $returnType->getObjectType($result, $info);
520529

521-
if ($objectType && !$returnType->isPossibleType($objectType)) {
530+
if ($runtimeType && !$returnType->isPossibleType($runtimeType)) {
522531
throw new Error(
523-
"Runtime Object type \"$objectType\" is not a possible type for \"$returnType\"."
532+
"Runtime Object type \"$runtimeType\" is not a possible type for \"$returnType\"."
524533
);
525534
}
526535
} else {
527-
$objectType = null;
536+
$runtimeType = null;
528537
}
529538

530-
if (!$objectType) {
539+
if (!$runtimeType) {
531540
return null;
532541
}
533542

534543
// If there is an isTypeOf predicate function, call it with the
535544
// current result. If isTypeOf returns false, then raise an error rather
536545
// than continuing execution.
537-
if (false === $objectType->isTypeOf($result, $info)) {
546+
if (false === $runtimeType->isTypeOf($result, $info)) {
538547
throw new Error(
539-
"Expected value of type $objectType but got: $result.",
548+
"Expected value of type $runtimeType but got: $result.",
540549
$fieldASTs
541550
);
542551
}
@@ -549,15 +558,15 @@ private static function completeValue(ExecutionContext $exeContext, Type $return
549558
if ($selectionSet) {
550559
$subFieldASTs = self::collectFields(
551560
$exeContext,
552-
$objectType,
561+
$runtimeType,
553562
$selectionSet,
554563
$subFieldASTs,
555564
$visitedFragmentNames
556565
);
557566
}
558567
}
559568

560-
return self::executeFields($exeContext, $objectType, $result, $subFieldASTs);
569+
return self::executeFields($exeContext, $runtimeType, $result, $subFieldASTs);
561570
}
562571

563572

0 commit comments

Comments
 (0)