Skip to content

Commit

Permalink
feature: throw rejections that aren't handled
Browse files Browse the repository at this point in the history
closes #63
  • Loading branch information
g105b committed Jul 1, 2023
1 parent ccc1927 commit 907b3a4
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 35 deletions.
46 changes: 12 additions & 34 deletions src/Promise.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ class Promise implements PromiseInterface {
private array $chain;
/** @var CatchChain[] */
private array $uncalledCatchChain;
/** @var Throwable[] */
private array $handledRejections;
/** @var callable */
private $executor;
private bool $completed;

public function __construct(callable $executor) {
$this->completed = false;
$this->chain = [];
$this->uncalledCatchChain = [];
$this->handledRejections = [];

$this->executor = $executor;
$this->callExecutor();
Expand Down Expand Up @@ -123,7 +124,8 @@ private function reset():void {
}

private function tryComplete():void {
if(empty($this->chain) && $this->getState() === PromiseState::PENDING) {
if(empty($this->chain)) {
$this->throwUnhandledRejection();
return;
}
if($this->getState() !== PromiseState::PENDING) {
Expand All @@ -145,10 +147,7 @@ function(Chainable $a, Chainable $b) {
return 0;
}
);
$handledRejections = [];

$emptyChain = empty($this->chain);
$originalChain = $this->chain;
while($this->getState() !== PromiseState::PENDING) {
$chainItem = $this->getNextChainItem();
if(!$chainItem) {
Expand All @@ -160,17 +159,15 @@ function(Chainable $a, Chainable $b) {
}
elseif($chainItem instanceof CatchChain) {
if($handled = $this->handleCatch($chainItem)) {
array_push($handledRejections, $handled);
array_push($this->handledRejections, $handled);
}
}
elseif($chainItem instanceof FinallyChain) {
$this->handleFinally($chainItem);
}
}

$this->handleCatches($originalChain, $emptyChain, $handledRejections);

$this->completed = true;
$this->throwUnhandledRejection();
}

private function getNextChainItem():?Chainable {
Expand Down Expand Up @@ -200,7 +197,8 @@ private function handleThen(ThenChain $then):void {

private function handleCatch(CatchChain $catch):?Throwable {
if($this->getState() !== PromiseState::REJECTED) {
// TODO: This is where #52 can be implemented.
// TODO: This is where #52 can be implemented
// see: (https://github.com/PhpGt/Promise/issues/52)
array_push($this->uncalledCatchChain, $catch);
return null;
}
Expand Down Expand Up @@ -244,29 +242,9 @@ private function handleFinally(FinallyChain $finally):void {
}
}

/**
* @param array<Chainable> $chain
* @param bool $emptyChain
* @param array<Throwable> $handledRejections
*/
protected function handleCatches(
array $chain,
bool $emptyChain,
array $handledRejections,
):void {
if ($this->getState() === PromiseState::REJECTED) {
$hasCatch = false;
foreach ($chain as $chainItem) {
if ($chainItem instanceof CatchChain) {
$hasCatch = true;
}
}

if (!$hasCatch) {
throw $this->rejectedReason;
}

if (!$emptyChain && !in_array($this->rejectedReason, $handledRejections)) {
protected function throwUnhandledRejection():void {
if($this->getState() === PromiseState::REJECTED) {
if(!in_array($this->rejectedReason, $this->handledRejections)) {
throw $this->rejectedReason;
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/phpunit/PromiseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ public function testPromiseRejectsIfResolvedWithItself() {
$actualMessage = $reason->getMessage();
});

self::expectExceptionMessage("A Promise must not be resolved with another Promise.");
$promiseContainer->resolve($sut);
self::assertEquals(0, $onResolvedCallCount);
self::assertSame("A Promise must not be resolved with another Promise.", $actualMessage);
}

public function testRejectWithException() {
Expand Down

0 comments on commit 907b3a4

Please sign in to comment.