friendship ended with social-app. php is my new best friend
1<?php
2
3namespace React\Promise\Internal;
4
5use React\Promise\PromiseInterface;
6use function React\Promise\_checkTypehint;
7use function React\Promise\resolve;
8use function React\Promise\set_rejection_handler;
9
10/**
11 * @internal
12 *
13 * @template-implements PromiseInterface<never>
14 */
15final class RejectedPromise implements PromiseInterface
16{
17 /** @var \Throwable */
18 private $reason;
19
20 /** @var bool */
21 private $handled = false;
22
23 /**
24 * @param \Throwable $reason
25 */
26 public function __construct(\Throwable $reason)
27 {
28 $this->reason = $reason;
29 }
30
31 /** @throws void */
32 public function __destruct()
33 {
34 if ($this->handled) {
35 return;
36 }
37
38 $handler = set_rejection_handler(null);
39 if ($handler === null) {
40 $message = 'Unhandled promise rejection with ' . $this->reason;
41
42 \error_log($message);
43 return;
44 }
45
46 try {
47 $handler($this->reason);
48 } catch (\Throwable $e) {
49 \preg_match('/^([^:\s]++)(.*+)$/sm', (string) $e, $match);
50 \assert(isset($match[1], $match[2]));
51 $message = 'Fatal error: Uncaught ' . $match[1] . ' from unhandled promise rejection handler' . $match[2];
52
53 \error_log($message);
54 exit(255);
55 }
56 }
57
58 /**
59 * @template TRejected
60 * @param ?callable $onFulfilled
61 * @param ?(callable(\Throwable): (PromiseInterface<TRejected>|TRejected)) $onRejected
62 * @return PromiseInterface<($onRejected is null ? never : TRejected)>
63 */
64 public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface
65 {
66 if (null === $onRejected) {
67 return $this;
68 }
69
70 $this->handled = true;
71
72 try {
73 return resolve($onRejected($this->reason));
74 } catch (\Throwable $exception) {
75 return new RejectedPromise($exception);
76 }
77 }
78
79 /**
80 * @template TThrowable of \Throwable
81 * @template TRejected
82 * @param callable(TThrowable): (PromiseInterface<TRejected>|TRejected) $onRejected
83 * @return PromiseInterface<TRejected>
84 */
85 public function catch(callable $onRejected): PromiseInterface
86 {
87 if (!_checkTypehint($onRejected, $this->reason)) {
88 return $this;
89 }
90
91 /**
92 * @var callable(\Throwable):(PromiseInterface<TRejected>|TRejected) $onRejected
93 */
94 return $this->then(null, $onRejected);
95 }
96
97 public function finally(callable $onFulfilledOrRejected): PromiseInterface
98 {
99 return $this->then(null, function (\Throwable $reason) use ($onFulfilledOrRejected): PromiseInterface {
100 return resolve($onFulfilledOrRejected())->then(function () use ($reason): PromiseInterface {
101 return new RejectedPromise($reason);
102 });
103 });
104 }
105
106 public function cancel(): void
107 {
108 $this->handled = true;
109 }
110
111 /**
112 * @deprecated 3.0.0 Use `catch()` instead
113 * @see self::catch()
114 */
115 public function otherwise(callable $onRejected): PromiseInterface
116 {
117 return $this->catch($onRejected);
118 }
119
120 /**
121 * @deprecated 3.0.0 Use `always()` instead
122 * @see self::always()
123 */
124 public function always(callable $onFulfilledOrRejected): PromiseInterface
125 {
126 return $this->finally($onFulfilledOrRejected);
127 }
128}