Refactored isThenable checks in Executor

This commit is contained in:
Vladimir Razuvaev 2017-07-04 13:47:50 +07:00
parent 32376dd6ee
commit 3e1fc1a922

View File

@ -322,8 +322,9 @@ class Executor
if ($result === self::$UNDEFINED) { if ($result === self::$UNDEFINED) {
return $results; return $results;
} }
if ($result instanceof Promise) { $promise = $this->getPromise($result);
return $result->then(function ($resolvedResult) use ($responseName, $results) { if ($promise) {
return $promise->then(function ($resolvedResult) use ($responseName, $results) {
$results[$responseName] = $resolvedResult; $results[$responseName] = $resolvedResult;
return $results; return $results;
}); });
@ -365,7 +366,7 @@ class Executor
if ($result === self::$UNDEFINED) { if ($result === self::$UNDEFINED) {
continue; continue;
} }
if (!$containsPromise && $result instanceof Promise) { if (!$containsPromise && $this->getPromise($result)) {
$containsPromise = true; $containsPromise = true;
} }
$finalResults[$responseName] = $result; $finalResults[$responseName] = $result;
@ -728,8 +729,10 @@ class Executor
$path, $path,
$result $result
); );
if ($completed instanceof Promise) {
return $completed->then(null, function ($error) use ($exeContext) { $promise = $this->getPromise($completed);
if ($promise) {
return $promise->then(null, function ($error) use ($exeContext) {
$exeContext->addError($error); $exeContext->addError($error);
return $this->promises->createFulfilled(null); return $this->promises->createFulfilled(null);
}); });
@ -772,8 +775,9 @@ class Executor
$path, $path,
$result $result
); );
if ($completed instanceof Promise) { $promise = $this->getPromise($completed);
return $completed->then(null, function ($error) use ($fieldNodes, $path) { if ($promise) {
return $promise->then(null, function ($error) use ($fieldNodes, $path) {
return $this->promises->createRejected(Error::createLocatedError($error, $fieldNodes, $path)); return $this->promises->createRejected(Error::createLocatedError($error, $fieldNodes, $path));
}); });
} }
@ -823,14 +827,11 @@ class Executor
&$result &$result
) )
{ {
if ($this->promises->isThenable($result)) { $promise = $this->getPromise($result);
$result = $this->promises->convertThenable($result);
Utils::invariant($result instanceof Promise);
}
// If result is a Promise, apply-lift over completeValue. // If result is a Promise, apply-lift over completeValue.
if ($result instanceof Promise) { if ($promise) {
return $result->then(function (&$resolved) use ($returnType, $fieldNodes, $info, $path) { return $promise->then(function (&$resolved) use ($returnType, $fieldNodes, $info, $path) {
return $this->completeValue($returnType, $fieldNodes, $info, $path, $resolved); return $this->completeValue($returnType, $fieldNodes, $info, $path, $resolved);
}); });
} }
@ -968,17 +969,13 @@ class Executor
$exeContext = $this->exeContext; $exeContext = $this->exeContext;
$runtimeType = $returnType->resolveType($result, $exeContext->contextValue, $info); $runtimeType = $returnType->resolveType($result, $exeContext->contextValue, $info);
if ($this->promises->isThenable($runtimeType)) {
$runtimeType = $this->promises->convertThenable($runtimeType);
Utils::invariant($runtimeType instanceof Promise);
}
if (null === $runtimeType) { if (null === $runtimeType) {
$runtimeType = self::defaultTypeResolver($result, $exeContext->contextValue, $info, $returnType); $runtimeType = self::defaultTypeResolver($result, $exeContext->contextValue, $info, $returnType);
} }
if ($runtimeType instanceof Promise) { $promise = $this->getPromise($runtimeType);
return $runtimeType->then(function($resolvedRuntimeType) use ($returnType, $fieldNodes, $info, $path, &$result) { if ($promise) {
return $promise->then(function($resolvedRuntimeType) use ($returnType, $fieldNodes, $info, $path, &$result) {
return $this->completeObjectValue( return $this->completeObjectValue(
$this->ensureValidRuntimeType( $this->ensureValidRuntimeType(
$resolvedRuntimeType, $resolvedRuntimeType,
@ -1077,7 +1074,7 @@ class Executor
$fieldPath = $path; $fieldPath = $path;
$fieldPath[] = $i++; $fieldPath[] = $i++;
$completedItem = $this->completeValueCatchingError($itemType, $fieldNodes, $info, $fieldPath, $item); $completedItem = $this->completeValueCatchingError($itemType, $fieldNodes, $info, $fieldPath, $item);
if (!$containsPromise && $completedItem instanceof Promise) { if (!$containsPromise && $this->getPromise($completedItem)) {
$containsPromise = true; $containsPromise = true;
} }
$completedItems[] = $completedItem; $completedItems[] = $completedItem;
@ -1125,12 +1122,9 @@ class Executor
$isTypeOf = $returnType->isTypeOf($result, $this->exeContext->contextValue, $info); $isTypeOf = $returnType->isTypeOf($result, $this->exeContext->contextValue, $info);
if (null !== $isTypeOf) { if (null !== $isTypeOf) {
if ($this->promises->isThenable($isTypeOf)) { $promise = $this->getPromise($isTypeOf);
/** @var Promise $isTypeOf */ if ($promise) {
$isTypeOf = $this->promises->convertThenable($isTypeOf); return $promise->then(function($isTypeOfResult) use ($returnType, $fieldNodes, $info, $path, &$result) {
Utils::invariant($isTypeOf instanceof Promise);
return $isTypeOf->then(function($isTypeOfResult) use ($returnType, $fieldNodes, $info, $path, &$result) {
if (!$isTypeOfResult) { if (!$isTypeOfResult) {
throw $this->invalidReturnTypeError($returnType, $result, $fieldNodes); throw $this->invalidReturnTypeError($returnType, $result, $fieldNodes);
} }
@ -1232,8 +1226,9 @@ class Executor
$isTypeOfResult = $type->isTypeOf($value, $context, $info); $isTypeOfResult = $type->isTypeOf($value, $context, $info);
if (null !== $isTypeOfResult) { if (null !== $isTypeOfResult) {
if ($this->promises->isThenable($isTypeOfResult)) { $promise = $this->getPromise($isTypeOfResult);
$promisedIsTypeOfResults[$index] = $this->promises->convertThenable($isTypeOfResult); if ($promise) {
$promisedIsTypeOfResults[$index] = $promise;
} else if ($isTypeOfResult) { } else if ($isTypeOfResult) {
return $type; return $type;
} }
@ -1255,6 +1250,32 @@ class Executor
return null; return null;
} }
/**
* Only returns the value if it acts like a Promise, i.e. has a "then" function,
* otherwise returns null.
*
* @param mixed $value
* @return Promise|null
*/
private function getPromise($value)
{
if (null === $value || $value instanceof Promise) {
return $value;
}
if ($this->promises->isThenable($value)) {
$promise = $this->promises->convertThenable($value);
if (!$promise instanceof Promise) {
throw new InvariantViolation(sprintf(
'%s::convertThenable is expected to return instance of GraphQL\Executor\Promise\Promise, got: %s',
get_class($this->promises),
Utils::printSafe($promise)
));
}
return $promise;
}
return null;
}
/** /**
* @deprecated as of v0.8.0 should use self::defaultFieldResolver method * @deprecated as of v0.8.0 should use self::defaultFieldResolver method
* *