Merge pull request #127 from danez/throwable

Support PHP7 error exceptions everywhere
This commit is contained in:
Vladimir Razuvaev 2017-06-25 21:56:00 +07:00 committed by GitHub
commit d18cb84ec4
12 changed files with 37 additions and 26 deletions

View File

@ -54,6 +54,8 @@ class Deferred
$this->promise->resolve($cb()); $this->promise->resolve($cb());
} catch (\Exception $e) { } catch (\Exception $e) {
$this->promise->reject($e); $this->promise->reject($e);
} catch (\Throwable $e) {
$this->promise->reject($e);
} }
} }
} }

View File

@ -86,10 +86,7 @@ class Error extends \Exception implements \JsonSerializable
$nodes = $error->nodes ?: $nodes; $nodes = $error->nodes ?: $nodes;
$source = $error->source; $source = $error->source;
$positions = $error->positions; $positions = $error->positions;
} else if ($error instanceof \Exception) { } else if ($error instanceof \Exception || $error instanceof \Throwable) {
$message = $error->getMessage();
$originalError = $error;
} else if ($error instanceof \Error) {
$message = $error->getMessage(); $message = $error->getMessage();
$originalError = $error; $originalError = $error;
} else { } else {
@ -122,7 +119,7 @@ class Error extends \Exception implements \JsonSerializable
* @param Source $source * @param Source $source
* @param array|null $positions * @param array|null $positions
* @param array|null $path * @param array|null $path
* @param \Exception|\Error $previous * @param \Throwable $previous
*/ */
public function __construct($message, $nodes = null, Source $source = null, $positions = null, $path = null, $previous = null) public function __construct($message, $nodes = null, Source $source = null, $positions = null, $path = null, $previous = null)
{ {

View File

@ -46,10 +46,10 @@ class FormattedError
} }
/** /**
* @param \Exception $e * @param \Throwable $e
* @return array * @return array
*/ */
public static function createFromException(\Exception $e) public static function createFromException($e)
{ {
return [ return [
'message' => $e->getMessage(), 'message' => $e->getMessage(),

View File

@ -664,7 +664,7 @@ class Executor
* @param mixed $source * @param mixed $source
* @param mixed $context * @param mixed $context
* @param ResolveInfo $info * @param ResolveInfo $info
* @return \Exception|Promise|mixed * @return \Throwable|Promise|mixed
*/ */
private function resolveOrError($fieldDef, $fieldNode, $resolveFn, $source, $context, $info) private function resolveOrError($fieldDef, $fieldNode, $resolveFn, $source, $context, $info)
{ {
@ -680,7 +680,7 @@ class Executor
return $resolveFn($source, $args, $context, $info); return $resolveFn($source, $args, $context, $info);
} catch (\Exception $error) { } catch (\Exception $error) {
return $error; return $error;
} catch (\Error $error) { } catch (\Throwable $error) {
return $error; return $error;
} }
} }
@ -780,7 +780,7 @@ class Executor
return $completed; return $completed;
} catch (\Exception $error) { } catch (\Exception $error) {
throw Error::createLocatedError($error, $fieldNodes, $path); throw Error::createLocatedError($error, $fieldNodes, $path);
} catch (\Error $error) { } catch (\Throwable $error) {
throw Error::createLocatedError($error, $fieldNodes, $path); throw Error::createLocatedError($error, $fieldNodes, $path);
} }
} }
@ -813,8 +813,7 @@ class Executor
* @param $result * @param $result
* @return array|null|Promise * @return array|null|Promise
* @throws Error * @throws Error
* @throws \Exception * @throws \Throwable
* @throws \Error
*/ */
private function completeValue( private function completeValue(
Type $returnType, Type $returnType,
@ -836,11 +835,7 @@ class Executor
}); });
} }
if ($result instanceof \Exception) { if ($result instanceof \Exception || $result instanceof \Throwable) {
throw $result;
}
if ($result instanceof \Error) {
throw $result; throw $result;
} }

View File

@ -56,7 +56,7 @@ class ReactPromiseAdapter implements PromiseAdapter
/** /**
* @inheritdoc * @inheritdoc
*/ */
public function createRejected(\Exception $reason) public function createRejected($reason)
{ {
$promise = \React\Promise\reject($reason); $promise = \React\Promise\reject($reason);
return new Promise($promise, $this); return new Promise($promise, $this);

View File

@ -46,8 +46,12 @@ class SyncPromise
*/ */
private $waiting = []; private $waiting = [];
public function reject(\Exception $reason) public function reject($reason)
{ {
if (!$reason instanceof \Exception && !$reason instanceof \Throwable) {
throw new \Exception('SyncPromise::reject() has to be called with an instance of \Throwable');
}
switch ($this->state) { switch ($this->state) {
case self::PENDING: case self::PENDING:
$this->state = self::REJECTED; $this->state = self::REJECTED;
@ -131,6 +135,8 @@ class SyncPromise
$promise->resolve($onFulfilled ? $onFulfilled($this->result) : $this->result); $promise->resolve($onFulfilled ? $onFulfilled($this->result) : $this->result);
} catch (\Exception $e) { } catch (\Exception $e) {
$promise->reject($e); $promise->reject($e);
} catch (\Throwable $e) {
$promise->reject($e);
} }
} else if ($this->state === self::REJECTED) { } else if ($this->state === self::REJECTED) {
try { try {
@ -141,6 +147,8 @@ class SyncPromise
} }
} catch (\Exception $e) { } catch (\Exception $e) {
$promise->reject($e); $promise->reject($e);
} catch (\Throwable $e) {
$promise->reject($e);
} }
} }
}); });

View File

@ -60,6 +60,8 @@ class SyncPromiseAdapter implements PromiseAdapter
); );
} catch (\Exception $e) { } catch (\Exception $e) {
$promise->reject($e); $promise->reject($e);
} catch (\Throwable $e) {
$promise->reject($e);
} }
return new Promise($promise, $this); return new Promise($promise, $this);
@ -77,7 +79,7 @@ class SyncPromiseAdapter implements PromiseAdapter
/** /**
* @inheritdoc * @inheritdoc
*/ */
public function createRejected(\Exception $reason) public function createRejected($reason)
{ {
$promise = new SyncPromise(); $promise = new SyncPromise();
return new Promise($promise->reject($reason), $this); return new Promise($promise->reject($reason), $this);

View File

@ -53,11 +53,11 @@ interface PromiseAdapter
* Creates a rejected promise for a reason if the reason is not a promise. If * Creates a rejected promise for a reason if the reason is not a promise. If
* the provided reason is a promise, then it is returned as-is. * the provided reason is a promise, then it is returned as-is.
* *
* @param mixed $reason * @param \Throwable $reason
* *
* @return Promise * @return Promise
*/ */
public function createRejected(\Exception $reason); public function createRejected($reason);
/** /**
* Given an array of promises (or values), returns a promise that is fulfilled when all the * Given an array of promises (or values), returns a promise that is fulfilled when all the

View File

@ -552,7 +552,7 @@ class Server
$httpStatus = $this->unexpectedErrorStatus; $httpStatus = $this->unexpectedErrorStatus;
$error = new Error($this->unexpectedErrorMessage, null, null, null, null, $e); $error = new Error($this->unexpectedErrorMessage, null, null, null, null, $e);
$result = ['errors' => [$this->formatError($error)]]; $result = ['errors' => [$this->formatError($error)]];
} catch (\Error $e) { } catch (\Throwable $e) {
$httpStatus = $this->unexpectedErrorStatus; $httpStatus = $this->unexpectedErrorStatus;
$error = new Error($this->unexpectedErrorMessage, null, null, null, null, $e); $error = new Error($this->unexpectedErrorMessage, null, null, null, null, $e);
$result = ['errors' => [$this->formatError($error)]]; $result = ['errors' => [$this->formatError($error)]];
@ -561,7 +561,10 @@ class Server
$this->produceOutput($result, $httpStatus); $this->produceOutput($result, $httpStatus);
} }
private function formatException(\Exception $e) /**
* @param \Throwable $e
*/
private function formatException($e)
{ {
$formatter = $this->exceptionFormatter; $formatter = $this->exceptionFormatter;
return $formatter($e); return $formatter($e);

View File

@ -263,6 +263,8 @@ abstract class Type implements \JsonSerializable
return $this->toString(); return $this->toString();
} catch (\Exception $e) { } catch (\Exception $e) {
echo $e; echo $e;
} catch (\Throwable $e) {
echo $e;
} }
} }
} }

View File

@ -130,8 +130,8 @@ class DocumentValidator
public static function isError($value) public static function isError($value)
{ {
return is_array($value) return is_array($value)
? count(array_filter($value, function($item) { return $item instanceof \Exception;})) === count($value) ? count(array_filter($value, function($item) { return $item instanceof \Exception || $item instanceof \Throwable;})) === count($value)
: $value instanceof \Exception; : ($value instanceof \Exception || $value instanceof \Throwable);
} }
public static function append(&$arr, $items) public static function append(&$arr, $items)

View File

@ -218,6 +218,8 @@ class SyncPromiseTest extends \PHPUnit_Framework_TestCase
try { try {
$promise->reject('a'); $promise->reject('a');
$this->fail('Expected exception not thrown'); $this->fail('Expected exception not thrown');
} catch (\PHPUnit_Framework_AssertionFailedError $e) {
throw $e;
} catch (\Throwable $e) { } catch (\Throwable $e) {
$this->assertEquals(SyncPromise::PENDING, $promise->state); $this->assertEquals(SyncPromise::PENDING, $promise->state);
} catch (\Exception $e) { } catch (\Exception $e) {