diff --git a/README.md b/README.md index c258990b..9967bc3f 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,6 @@ Table of Contents * [Deferred::reject()](#deferredreject) * [PromiseInterface](#promiseinterface) * [PromiseInterface::then()](#promiseinterfacethen) - * [PromiseInterface::done()](#promiseinterfacedone) * [PromiseInterface::catch()](#promiseinterfacecatch) * [PromiseInterface::finally()](#promiseinterfacefinally) * [PromiseInterface::cancel()](#promiseinterfacecancel) @@ -48,7 +47,6 @@ Table of Contents * [Resolution forwarding](#resolution-forwarding) * [Rejection forwarding](#rejection-forwarding) * [Mixed resolution and rejection forwarding](#mixed-resolution-and-rejection-forwarding) - * [done() vs. then()](#done-vs-then) 5. [Install](#install) 6. [Credits](#credits) 7. [License](#license) @@ -183,28 +181,6 @@ the same call to `then()`: * [resolve()](#resolve) - Creating a resolved promise * [reject()](#reject) - Creating a rejected promise -* [PromiseInterface::done()](#promiseinterfacedone) -* [done() vs. then()](#done-vs-then) - -#### PromiseInterface::done() - -```php -$promise->done(callable $onFulfilled = null, callable $onRejected = null); -``` - -Consumes the promise's ultimate value if the promise fulfills, or handles the -ultimate error. - -It will cause a fatal error (`E_USER_ERROR`) if either `$onFulfilled` or -`$onRejected` throw or return a rejected promise. - -Since the purpose of `done()` is consumption rather than transformation, -`done()` always returns `null`. - -#### See also - -* [PromiseInterface::then()](#promiseinterfacethen) -* [done() vs. then()](#done-vs-then) #### PromiseInterface::catch() @@ -579,74 +555,6 @@ $deferred->promise() $deferred->resolve(1); // Prints "Mixed 4" ``` -### done() vs. then() - -The golden rule is: - - Either return your promise, or call done() on it. - -At a first glance, `then()` and `done()` seem very similar. However, there are -important distinctions. - -The intent of `then()` is to transform a promise's value and to pass or return -a new promise for the transformed value along to other parts of your code. - -The intent of `done()` is to consume a promise's value, transferring -responsibility for the value to your code. - -In addition to transforming a value, `then()` allows you to recover from, or -propagate intermediate errors. Any errors that are not handled will be caught -by the promise machinery and used to reject the promise returned by `then()`. - -Calling `done()` transfers all responsibility for errors to your code. If an -error (either a thrown exception or returned rejection) escapes the -`$onFulfilled` or `$onRejected` callbacks you provide to `done()`, it will cause -a fatal error. - -```php -function getJsonResult() -{ - return queryApi() - ->then( - // Transform API results to an object - function ($jsonResultString) { - return json_decode($jsonResultString); - }, - // Transform API errors to an exception - function ($jsonErrorString) { - $object = json_decode($jsonErrorString); - throw new ApiErrorException($object->errorMessage); - } - ); -} - -// Here we provide no rejection handler. If the promise returned has been -// rejected, the ApiErrorException will be thrown -getJsonResult() - ->done( - // Consume transformed object - function ($jsonResultObject) { - // Do something with $jsonResultObject - } - ); - -// Here we provide a rejection handler which will either throw while debugging -// or log the exception -getJsonResult() - ->done( - function ($jsonResultObject) { - // Do something with $jsonResultObject - }, - function (ApiErrorException $exception) { - if (isDebug()) { - throw $exception; - } else { - logException($exception); - } - } - ); -``` - Install ------- diff --git a/src/Internal/FulfilledPromise.php b/src/Internal/FulfilledPromise.php index df0c86b6..78fadf31 100644 --- a/src/Internal/FulfilledPromise.php +++ b/src/Internal/FulfilledPromise.php @@ -5,7 +5,6 @@ use React\Promise\Promise; use React\Promise\PromiseInterface; use function React\Promise\enqueue; -use function React\Promise\fatalError; use function React\Promise\resolve; /** @@ -41,25 +40,6 @@ public function then(callable $onFulfilled = null, callable $onRejected = null): }); } - public function done(callable $onFulfilled = null, callable $onRejected = null): void - { - if (null === $onFulfilled) { - return; - } - - enqueue(function () use ($onFulfilled) { - try { - $result = $onFulfilled($this->value); - } catch (\Throwable $exception) { - return fatalError($exception); - } - - if ($result instanceof PromiseInterface) { - $result->done(); - } - }); - } - public function catch(callable $onRejected): PromiseInterface { return $this; diff --git a/src/Internal/RejectedPromise.php b/src/Internal/RejectedPromise.php index 6b24d972..e5565989 100644 --- a/src/Internal/RejectedPromise.php +++ b/src/Internal/RejectedPromise.php @@ -6,7 +6,6 @@ use React\Promise\PromiseInterface; use function React\Promise\_checkTypehint; use function React\Promise\enqueue; -use function React\Promise\fatalError; use function React\Promise\resolve; /** @@ -38,29 +37,6 @@ public function then(callable $onFulfilled = null, callable $onRejected = null): }); } - public function done(callable $onFulfilled = null, callable $onRejected = null): void - { - enqueue(function () use ($onRejected) { - if (null === $onRejected) { - return fatalError($this->reason); - } - - try { - $result = $onRejected($this->reason); - } catch (\Throwable $exception) { - return fatalError($exception); - } - - if ($result instanceof self) { - return fatalError($result->reason); - } - - if ($result instanceof PromiseInterface) { - $result->done(); - } - }); - } - public function catch(callable $onRejected): PromiseInterface { if (!_checkTypehint($onRejected, $this->reason)) { diff --git a/src/Promise.php b/src/Promise.php index 865249de..5f886c9e 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -57,19 +57,6 @@ static function () use (&$parent) { ); } - public function done(callable $onFulfilled = null, callable $onRejected = null): void - { - if (null !== $this->result) { - $this->result->done($onFulfilled, $onRejected); - return; - } - - $this->handlers[] = static function (PromiseInterface $promise) use ($onFulfilled, $onRejected) { - $promise - ->done($onFulfilled, $onRejected); - }; - } - public function catch(callable $onRejected): PromiseInterface { return $this->then(null, static function ($reason) use ($onRejected) { @@ -151,9 +138,15 @@ private function resolver(callable $onFulfilled = null, callable $onRejected = n { return function ($resolve, $reject) use ($onFulfilled, $onRejected) { $this->handlers[] = static function (PromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject) { - $promise - ->then($onFulfilled, $onRejected) - ->done($resolve, $reject); + $promise = $promise->then($onFulfilled, $onRejected); + + if ($promise instanceof self && $promise->result === null) { + $promise->handlers[] = static function (PromiseInterface $promise) use ($resolve, $reject) { + $promise->then($resolve, $reject); + }; + } else { + $promise->then($resolve, $reject); + } }; }; } diff --git a/src/PromiseInterface.php b/src/PromiseInterface.php index e6b46c2a..47117072 100644 --- a/src/PromiseInterface.php +++ b/src/PromiseInterface.php @@ -34,22 +34,6 @@ interface PromiseInterface */ public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface; - /** - * Consumes the promise's ultimate value if the promise fulfills, or handles the - * ultimate error. - * - * It will cause a fatal error (`E_USER_ERROR`) if either `$onFulfilled` or - * `$onRejected` throw or return a rejected promise. - * - * Since the purpose of `done()` is consumption rather than transformation, - * `done()` always returns `null`. - * - * @param callable|null $onFulfilled - * @param callable|null $onRejected - * @return void - */ - public function done(callable $onFulfilled = null, callable $onRejected = null): void; - /** * Registers a rejection handler for promise. It is a shortcut for: * diff --git a/src/functions.php b/src/functions.php index f640fe1b..ad788f4f 100644 --- a/src/functions.php +++ b/src/functions.php @@ -88,7 +88,7 @@ function all(array $promisesOrValues): PromiseInterface $values[$i] = null; resolve($promiseOrValue) - ->done( + ->then( function ($mapped) use ($i, &$values, &$toResolve, $resolve): void { $values[$i] = $mapped; @@ -125,7 +125,7 @@ function race(array $promisesOrValues): PromiseInterface $cancellationQueue->enqueue($promiseOrValue); resolve($promiseOrValue) - ->done($resolve, $reject); + ->then($resolve, $reject); } }, $cancellationQueue); } @@ -187,7 +187,7 @@ function any(array $promisesOrValues): PromiseInterface $cancellationQueue->enqueue($promiseOrValue); resolve($promiseOrValue) - ->done($fulfiller, $rejecter); + ->then($fulfiller, $rejecter); } }, $cancellationQueue); } @@ -206,19 +206,6 @@ function enqueue(callable $task): void $queue->enqueue($task); } -/** - * @internal - */ -function fatalError($error): void -{ - try { - \trigger_error($error, E_USER_ERROR); - } catch (\Throwable $e) { - \set_error_handler(null); - \trigger_error($error, E_USER_ERROR); - } -} - /** * @internal */ diff --git a/tests/ErrorCollector.php b/tests/ErrorCollector.php deleted file mode 100644 index 0ad3fffd..00000000 --- a/tests/ErrorCollector.php +++ /dev/null @@ -1,29 +0,0 @@ -errors = &$errors; - } - - public function stop() - { - $errors = $this->errors; - $this->errors = []; - - restore_error_handler(); - - return $errors; - } -} diff --git a/tests/PromiseTest.php b/tests/PromiseTest.php index e8e9f090..49e05400 100644 --- a/tests/PromiseTest.php +++ b/tests/PromiseTest.php @@ -178,19 +178,6 @@ public function shouldRejectWithoutCreatingGarbageCyclesIfCancellerHoldsReferenc $this->assertSame(0, gc_collect_cycles()); } - /** @test */ - public function shouldIgnoreNotifyAfterReject() - { - $promise = new Promise(function () { }, function ($resolve, $reject, $notify) { - $reject(new \Exception('foo')); - $notify(42); - }); - - $promise->then(null, null, $this->expectCallableNever()); - $promise->cancel(); - } - - /** @test */ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromise() { @@ -212,17 +199,6 @@ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPro $this->assertSame(0, gc_collect_cycles()); } - /** @test */ - public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithDoneFollowers() - { - gc_collect_cycles(); - $promise = new Promise(function () { }); - $promise->done(); - unset($promise); - - $this->assertSame(0, gc_collect_cycles()); - } - /** @test */ public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithCatchFollowers() { diff --git a/tests/PromiseTest/PromiseFulfilledTestTrait.php b/tests/PromiseTest/PromiseFulfilledTestTrait.php index bcbe5c02..ec236147 100644 --- a/tests/PromiseTest/PromiseFulfilledTestTrait.php +++ b/tests/PromiseTest/PromiseFulfilledTestTrait.php @@ -3,7 +3,6 @@ namespace React\Promise\PromiseTest; use Exception; -use React\Promise\ErrorCollector; use React\Promise\PromiseAdapter\PromiseAdapterInterface; use stdClass; use function React\Promise\reject; @@ -205,61 +204,6 @@ public function cancelShouldHaveNoEffectForFulfilledPromise() $adapter->promise()->cancel(); } - /** @test */ - public function doneShouldInvokeFulfillmentHandlerForFulfilledPromise() - { - $adapter = $this->getPromiseTestAdapter(); - - $mock = $this->createCallableMock(); - $mock - ->expects($this->once()) - ->method('__invoke') - ->with($this->identicalTo(1)); - - $adapter->resolve(1); - self::assertNull($adapter->promise()->done($mock)); - } - - /** @test */ - public function doneShouldTriggerFatalErrorThrownFulfillmentHandlerForFulfilledPromise() - { - $adapter = $this->getPromiseTestAdapter(); - - $adapter->resolve(1); - - $errorCollector = new ErrorCollector(); - $errorCollector->start(); - - self::assertNull($adapter->promise()->done(function () { - throw new Exception('Unhandled Rejection'); - })); - - $errors = $errorCollector->stop(); - - self::assertEquals(E_USER_ERROR, $errors[0]['errno']); - self::assertStringContainsString('Unhandled Rejection', $errors[0]['errstr']); - } - - /** @test */ - public function doneShouldTriggerFatalErrorUnhandledRejectionExceptionWhenFulfillmentHandlerRejectsForFulfilledPromise() - { - $adapter = $this->getPromiseTestAdapter(); - - $adapter->resolve(1); - - $errorCollector = new ErrorCollector(); - $errorCollector->start(); - - self::assertNull($adapter->promise()->done(function () { - return reject(new Exception('Unhandled Rejection')); - })); - - $errors = $errorCollector->stop(); - - self::assertEquals(E_USER_ERROR, $errors[0]['errno']); - self::assertStringContainsString('Unhandled Rejection', $errors[0]['errstr']); - } - /** @test */ public function catchShouldNotInvokeRejectionHandlerForFulfilledPromise() { diff --git a/tests/PromiseTest/PromisePendingTestTrait.php b/tests/PromiseTest/PromisePendingTestTrait.php index 11f0e993..e7ed2881 100644 --- a/tests/PromiseTest/PromisePendingTestTrait.php +++ b/tests/PromiseTest/PromisePendingTestTrait.php @@ -36,22 +36,6 @@ public function cancelShouldReturnNullForPendingPromise() self::assertNull($adapter->promise()->cancel()); } - /** @test */ - public function doneShouldReturnNullForPendingPromise() - { - $adapter = $this->getPromiseTestAdapter(); - - self::assertNull($adapter->promise()->done()); - } - - /** @test */ - public function doneShouldReturnAllowNullForPendingPromise() - { - $adapter = $this->getPromiseTestAdapter(); - - self::assertNull($adapter->promise()->done(null, null)); - } - /** @test */ public function catchShouldNotInvokeRejectionHandlerForPendingPromise() { diff --git a/tests/PromiseTest/PromiseRejectedTestTrait.php b/tests/PromiseTest/PromiseRejectedTestTrait.php index cd85c2b1..b18baef6 100644 --- a/tests/PromiseTest/PromiseRejectedTestTrait.php +++ b/tests/PromiseTest/PromiseRejectedTestTrait.php @@ -4,8 +4,6 @@ use Exception; use InvalidArgumentException; -use React\Promise\Deferred; -use React\Promise\ErrorCollector; use React\Promise\PromiseAdapter\PromiseAdapterInterface; use function React\Promise\reject; use function React\Promise\resolve; @@ -196,121 +194,6 @@ function () use ($exception) { ); } - /** @test */ - public function doneShouldInvokeRejectionHandlerForRejectedPromise() - { - $adapter = $this->getPromiseTestAdapter(); - - $exception = new Exception(); - - $mock = $this->createCallableMock(); - $mock - ->expects($this->once()) - ->method('__invoke') - ->with($this->identicalTo($exception)); - - $adapter->reject($exception); - self::assertNull($adapter->promise()->done(null, $mock)); - } - - /** @test */ - public function doneShouldTriggerFatalErrorExceptionThrownByRejectionHandlerForRejectedPromise() - { - $errorCollector = new ErrorCollector(); - $errorCollector->start(); - - $adapter = $this->getPromiseTestAdapter(); - - $adapter->reject(new Exception()); - self::assertNull($adapter->promise()->done(null, function () { - throw new Exception('Unhandled Rejection'); - })); - - $errors = $errorCollector->stop(); - - self::assertEquals(E_USER_ERROR, $errors[0]['errno']); - self::assertStringContainsString('Unhandled Rejection', $errors[0]['errstr']); - } - - /** @test */ - public function doneShouldTriggerFatalErrorRejectionExceptionWhenRejectionHandlerRejectsWithExceptionForRejectedPromise() - { - $errorCollector = new ErrorCollector(); - $errorCollector->start(); - - $adapter = $this->getPromiseTestAdapter(); - - $adapter->reject(new Exception()); - self::assertNull($adapter->promise()->done(null, function () { - return reject(new Exception('Unhandled Rejection')); - })); - - $errors = $errorCollector->stop(); - - self::assertEquals(E_USER_ERROR, $errors[0]['errno']); - self::assertStringContainsString('Unhandled Rejection', $errors[0]['errstr']); - } - - /** @test */ - public function doneShouldTriggerFatalErrorExceptionProvidedAsRejectionValueForRejectedPromise() - { - $errorCollector = new ErrorCollector(); - $errorCollector->start(); - - $adapter = $this->getPromiseTestAdapter(); - - $exception = new Exception('Unhandled Rejection'); - - $adapter->reject($exception); - self::assertNull($adapter->promise()->done()); - - $errors = $errorCollector->stop(); - - self::assertEquals(E_USER_ERROR, $errors[0]['errno']); - self::assertEquals((string) $exception, $errors[0]['errstr']); - } - - /** @test */ - public function doneShouldTriggerFatalErrorWithDeepNestingPromiseChainsForRejectedPromise() - { - $errorCollector = new ErrorCollector(); - $errorCollector->start(); - - $exception = new Exception('UnhandledRejectionException'); - - $d = new Deferred(); - $d->resolve(null); - - $result = resolve(resolve($d->promise()->then(function () use ($exception) { - $d = new Deferred(); - $d->resolve(null); - - return resolve($d->promise()->then(function () {}))->then( - function () use ($exception) { - throw $exception; - } - ); - }))); - - $result->done(); - - $errors = $errorCollector->stop(); - - self::assertEquals(E_USER_ERROR, $errors[0]['errno']); - self::assertEquals((string) $exception, $errors[0]['errstr']); - } - - /** @test */ - public function doneShouldRecoverWhenRejectionHandlerCatchesExceptionForRejectedPromise() - { - $adapter = $this->getPromiseTestAdapter(); - - $adapter->reject(new Exception('UnhandledRejectionException')); - self::assertNull($adapter->promise()->done(null, function (Exception $e) { - - })); - } - /** @test */ public function catchShouldInvokeRejectionHandlerForRejectedPromise() { diff --git a/tests/PromiseTest/PromiseSettledTestTrait.php b/tests/PromiseTest/PromiseSettledTestTrait.php index 87879e91..5d489a59 100644 --- a/tests/PromiseTest/PromiseSettledTestTrait.php +++ b/tests/PromiseTest/PromiseSettledTestTrait.php @@ -50,24 +50,6 @@ public function cancelShouldHaveNoEffectForSettledPromise() $adapter->promise()->cancel(); } - /** @test */ - public function doneShouldReturnNullForSettledPromise() - { - $adapter = $this->getPromiseTestAdapter(); - - $adapter->settle(null); - self::assertNull($adapter->promise()->done(null, function () {})); - } - - /** @test */ - public function doneShouldReturnAllowNullForSettledPromise() - { - $adapter = $this->getPromiseTestAdapter(); - - $adapter->settle(null); - self::assertNull($adapter->promise()->done(null, function () {}, null)); - } - /** @test */ public function finallyShouldReturnAPromiseForSettledPromise() { diff --git a/tests/PromiseTest/RejectTestTrait.php b/tests/PromiseTest/RejectTestTrait.php index c6015812..7e9dbac8 100644 --- a/tests/PromiseTest/RejectTestTrait.php +++ b/tests/PromiseTest/RejectTestTrait.php @@ -109,143 +109,6 @@ public function rejectShouldInvokeCatchHandler() $adapter->reject($exception); } - /** @test */ - public function doneShouldInvokeRejectionHandler() - { - $adapter = $this->getPromiseTestAdapter(); - - $exception = new Exception(); - - $mock = $this->createCallableMock(); - $mock - ->expects($this->once()) - ->method('__invoke') - ->with($this->identicalTo($exception)); - - self::assertNull($adapter->promise()->done(null, $mock)); - $adapter->reject($exception); - } - - /** @test */ - public function doneShouldTriggerFatalErrorExceptionThrownByRejectionHandler() - { - $errorCollector = new Promise\ErrorCollector(); - $errorCollector->start(); - - $adapter = $this->getPromiseTestAdapter(); - - self::assertNull($adapter->promise()->done(null, function () { - throw new Exception('Unhandled Rejection'); - })); - $adapter->reject(new Exception()); - - $errors = $errorCollector->stop(); - - self::assertEquals(E_USER_ERROR, $errors[0]['errno']); - self::assertStringContainsString('Unhandled Rejection', $errors[0]['errstr']); - } - - /** @test */ - public function doneShouldTriggerFatalErrorRejectionExceptionWhenRejectionHandlerRejectsWithException() - { - $errorCollector = new Promise\ErrorCollector(); - $errorCollector->start(); - - $adapter = $this->getPromiseTestAdapter(); - - self::assertNull($adapter->promise()->done(null, function () { - return reject(new Exception('Unhandled Rejection')); - })); - $adapter->reject(new Exception()); - - $errors = $errorCollector->stop(); - - self::assertEquals(E_USER_ERROR, $errors[0]['errno']); - self::assertStringContainsString('Unhandled Rejection', $errors[0]['errstr']); - } - - /** @test */ - public function doneShouldTriggerFatalErrorUnhandledRejectionExceptionWhenRejectionHandlerRetunsPendingPromiseWhichRejectsLater() - { - $errorCollector = new Promise\ErrorCollector(); - $errorCollector->start(); - - $adapter = $this->getPromiseTestAdapter(); - - $d = new Deferred(); - $promise = $d->promise(); - - self::assertNull($adapter->promise()->done(null, function () use ($promise) { - return $promise; - })); - $adapter->reject(new Exception()); - $d->reject(new Exception('Unhandled Rejection')); - - $errors = $errorCollector->stop(); - - self::assertEquals(E_USER_ERROR, $errors[0]['errno']); - self::assertStringContainsString('Unhandled Rejection', $errors[0]['errstr']); - } - - /** @test */ - public function doneShouldTriggerFatalErrorExceptionProvidedAsRejectionValue() - { - $errorCollector = new Promise\ErrorCollector(); - $errorCollector->start(); - - $adapter = $this->getPromiseTestAdapter(); - - self::assertNull($adapter->promise()->done()); - $adapter->reject(new Exception('Unhandled Rejection')); - - $errors = $errorCollector->stop(); - - self::assertEquals(E_USER_ERROR, $errors[0]['errno']); - self::assertStringContainsString('Unhandled Rejection', $errors[0]['errstr']); - } - - /** @test */ - public function doneShouldTriggerFatalErrorWithDeepNestingPromiseChains() - { - $errorCollector = new Promise\ErrorCollector(); - $errorCollector->start(); - - $exception = new Exception('Unhandled Rejection'); - - $d = new Deferred(); - - $result = resolve(resolve($d->promise()->then(function () use ($exception) { - $d = new Deferred(); - $d->resolve(null); - - return resolve($d->promise()->then(function () {}))->then( - function () use ($exception) { - throw $exception; - } - ); - }))); - - $result->done(); - - $d->resolve(null); - - $errors = $errorCollector->stop(); - - self::assertEquals(E_USER_ERROR, $errors[0]['errno']); - self::assertEquals((string) $exception, $errors[0]['errstr']); - } - - /** @test */ - public function doneShouldRecoverWhenRejectionHandlerCatchesException() - { - $adapter = $this->getPromiseTestAdapter(); - - self::assertNull($adapter->promise()->done(null, function (Exception $e) { - - })); - $adapter->reject(new Exception('UnhandledRejectionException')); - } - /** @test */ public function finallyShouldNotSuppressRejection() { diff --git a/tests/PromiseTest/ResolveTestTrait.php b/tests/PromiseTest/ResolveTestTrait.php index e11d6a02..98bcc295 100644 --- a/tests/PromiseTest/ResolveTestTrait.php +++ b/tests/PromiseTest/ResolveTestTrait.php @@ -169,59 +169,6 @@ public function resolveShouldRejectWhenResolvedWithAPromiseWhichFollowsItself() $adapter2->resolve($promise1); } - /** @test */ - public function doneShouldInvokeFulfillmentHandler() - { - $adapter = $this->getPromiseTestAdapter(); - - $mock = $this->createCallableMock(); - $mock - ->expects($this->once()) - ->method('__invoke') - ->with($this->identicalTo(1)); - - self::assertNull($adapter->promise()->done($mock)); - $adapter->resolve(1); - } - - /** @test */ - public function doneShouldTriggerFatalErrorExceptionThrownFulfillmentHandler() - { - $errorCollector = new Promise\ErrorCollector(); - $errorCollector->start(); - - $adapter = $this->getPromiseTestAdapter(); - - self::assertNull($adapter->promise()->done(function () { - throw new Exception('Unhandled Rejection'); - })); - $adapter->resolve(1); - - $errors = $errorCollector->stop(); - - self::assertEquals(E_USER_ERROR, $errors[0]['errno']); - self::assertStringContainsString('Unhandled Rejection', $errors[0]['errstr']); - } - - /** @test */ - public function doneShouldTriggerFatalErrorUnhandledRejectionExceptionWhenFulfillmentHandlerRejects() - { - $errorCollector = new Promise\ErrorCollector(); - $errorCollector->start(); - - $adapter = $this->getPromiseTestAdapter(); - - self::assertNull($adapter->promise()->done(function () { - return reject(new Exception('Unhandled Rejection')); - })); - $adapter->resolve(1); - - $errors = $errorCollector->stop(); - - self::assertEquals(E_USER_ERROR, $errors[0]['errno']); - self::assertStringContainsString('Unhandled Rejection', $errors[0]['errstr']); - } - /** @test */ public function finallyShouldNotSuppressValue() {