tipo: modificación del cpanel y gitignore de la carpeta vendor
This commit is contained in:
+52
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace React\Promise;
|
||||
|
||||
/**
|
||||
* @template T
|
||||
*/
|
||||
final class Deferred
|
||||
{
|
||||
/**
|
||||
* @var PromiseInterface<T>
|
||||
*/
|
||||
private $promise;
|
||||
|
||||
/** @var callable(T):void */
|
||||
private $resolveCallback;
|
||||
|
||||
/** @var callable(\Throwable):void */
|
||||
private $rejectCallback;
|
||||
|
||||
/**
|
||||
* @param (callable(callable(T):void,callable(\Throwable):void):void)|null $canceller
|
||||
*/
|
||||
public function __construct(?callable $canceller = null)
|
||||
{
|
||||
$this->promise = new Promise(function ($resolve, $reject): void {
|
||||
$this->resolveCallback = $resolve;
|
||||
$this->rejectCallback = $reject;
|
||||
}, $canceller);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PromiseInterface<T>
|
||||
*/
|
||||
public function promise(): PromiseInterface
|
||||
{
|
||||
return $this->promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param T $value
|
||||
*/
|
||||
public function resolve($value): void
|
||||
{
|
||||
($this->resolveCallback)($value);
|
||||
}
|
||||
|
||||
public function reject(\Throwable $reason): void
|
||||
{
|
||||
($this->rejectCallback)($reason);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace React\Promise\Exception;
|
||||
|
||||
/**
|
||||
* Represents an exception that is a composite of one or more other exceptions.
|
||||
*
|
||||
* This exception is useful in situations where a promise must be rejected
|
||||
* with multiple exceptions. It is used for example to reject the returned
|
||||
* promise from `some()` and `any()` when too many input promises reject.
|
||||
*/
|
||||
class CompositeException extends \Exception
|
||||
{
|
||||
/** @var \Throwable[] */
|
||||
private $throwables;
|
||||
|
||||
/** @param \Throwable[] $throwables */
|
||||
public function __construct(array $throwables, string $message = '', int $code = 0, ?\Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
|
||||
$this->throwables = $throwables;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Throwable[]
|
||||
*/
|
||||
public function getThrowables(): array
|
||||
{
|
||||
return $this->throwables;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace React\Promise\Exception;
|
||||
|
||||
class LengthException extends \LengthException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace React\Promise\Internal;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class CancellationQueue
|
||||
{
|
||||
/** @var bool */
|
||||
private $started = false;
|
||||
|
||||
/** @var object[] */
|
||||
private $queue = [];
|
||||
|
||||
public function __invoke(): void
|
||||
{
|
||||
if ($this->started) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->started = true;
|
||||
$this->drain();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $cancellable
|
||||
*/
|
||||
public function enqueue($cancellable): void
|
||||
{
|
||||
if (!\is_object($cancellable) || !\method_exists($cancellable, 'then') || !\method_exists($cancellable, 'cancel')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$length = \array_push($this->queue, $cancellable);
|
||||
|
||||
if ($this->started && 1 === $length) {
|
||||
$this->drain();
|
||||
}
|
||||
}
|
||||
|
||||
private function drain(): void
|
||||
{
|
||||
for ($i = \key($this->queue); isset($this->queue[$i]); $i++) {
|
||||
$cancellable = $this->queue[$i];
|
||||
assert(\method_exists($cancellable, 'cancel'));
|
||||
|
||||
$exception = null;
|
||||
|
||||
try {
|
||||
$cancellable->cancel();
|
||||
} catch (\Throwable $exception) {
|
||||
}
|
||||
|
||||
unset($this->queue[$i]);
|
||||
|
||||
if ($exception) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
$this->queue = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace React\Promise\Internal;
|
||||
|
||||
use React\Promise\PromiseInterface;
|
||||
use function React\Promise\resolve;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @template T
|
||||
* @template-implements PromiseInterface<T>
|
||||
*/
|
||||
final class FulfilledPromise implements PromiseInterface
|
||||
{
|
||||
/** @var T */
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @param T $value
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct($value = null)
|
||||
{
|
||||
if ($value instanceof PromiseInterface) {
|
||||
throw new \InvalidArgumentException('You cannot create React\Promise\FulfilledPromise with a promise. Use React\Promise\resolve($promiseOrValue) instead.');
|
||||
}
|
||||
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template TFulfilled
|
||||
* @param ?(callable((T is void ? null : T)): (PromiseInterface<TFulfilled>|TFulfilled)) $onFulfilled
|
||||
* @return PromiseInterface<($onFulfilled is null ? T : TFulfilled)>
|
||||
*/
|
||||
public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface
|
||||
{
|
||||
if (null === $onFulfilled) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
try {
|
||||
/**
|
||||
* @var PromiseInterface<T>|T $result
|
||||
*/
|
||||
$result = $onFulfilled($this->value);
|
||||
return resolve($result);
|
||||
} catch (\Throwable $exception) {
|
||||
return new RejectedPromise($exception);
|
||||
}
|
||||
}
|
||||
|
||||
public function catch(callable $onRejected): PromiseInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function finally(callable $onFulfilledOrRejected): PromiseInterface
|
||||
{
|
||||
return $this->then(function ($value) use ($onFulfilledOrRejected): PromiseInterface {
|
||||
/** @var T $value */
|
||||
return resolve($onFulfilledOrRejected())->then(function () use ($value) {
|
||||
return $value;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public function cancel(): void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 3.0.0 Use `catch()` instead
|
||||
* @see self::catch()
|
||||
*/
|
||||
public function otherwise(callable $onRejected): PromiseInterface
|
||||
{
|
||||
return $this->catch($onRejected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 3.0.0 Use `finally()` instead
|
||||
* @see self::finally()
|
||||
*/
|
||||
public function always(callable $onFulfilledOrRejected): PromiseInterface
|
||||
{
|
||||
return $this->finally($onFulfilledOrRejected);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace React\Promise\Internal;
|
||||
|
||||
use React\Promise\PromiseInterface;
|
||||
use function React\Promise\_checkTypehint;
|
||||
use function React\Promise\resolve;
|
||||
use function React\Promise\set_rejection_handler;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @template-implements PromiseInterface<never>
|
||||
*/
|
||||
final class RejectedPromise implements PromiseInterface
|
||||
{
|
||||
/** @var \Throwable */
|
||||
private $reason;
|
||||
|
||||
/** @var bool */
|
||||
private $handled = false;
|
||||
|
||||
/**
|
||||
* @param \Throwable $reason
|
||||
*/
|
||||
public function __construct(\Throwable $reason)
|
||||
{
|
||||
$this->reason = $reason;
|
||||
}
|
||||
|
||||
/** @throws void */
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->handled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$handler = set_rejection_handler(null);
|
||||
if ($handler === null) {
|
||||
$message = 'Unhandled promise rejection with ' . $this->reason;
|
||||
|
||||
\error_log($message);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$handler($this->reason);
|
||||
} catch (\Throwable $e) {
|
||||
\preg_match('/^([^:\s]++)(.*+)$/sm', (string) $e, $match);
|
||||
\assert(isset($match[1], $match[2]));
|
||||
$message = 'Fatal error: Uncaught ' . $match[1] . ' from unhandled promise rejection handler' . $match[2];
|
||||
|
||||
\error_log($message);
|
||||
exit(255);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @template TRejected
|
||||
* @param ?callable $onFulfilled
|
||||
* @param ?(callable(\Throwable): (PromiseInterface<TRejected>|TRejected)) $onRejected
|
||||
* @return PromiseInterface<($onRejected is null ? never : TRejected)>
|
||||
*/
|
||||
public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface
|
||||
{
|
||||
if (null === $onRejected) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->handled = true;
|
||||
|
||||
try {
|
||||
return resolve($onRejected($this->reason));
|
||||
} catch (\Throwable $exception) {
|
||||
return new RejectedPromise($exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @template TThrowable of \Throwable
|
||||
* @template TRejected
|
||||
* @param callable(TThrowable): (PromiseInterface<TRejected>|TRejected) $onRejected
|
||||
* @return PromiseInterface<TRejected>
|
||||
*/
|
||||
public function catch(callable $onRejected): PromiseInterface
|
||||
{
|
||||
if (!_checkTypehint($onRejected, $this->reason)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var callable(\Throwable):(PromiseInterface<TRejected>|TRejected) $onRejected
|
||||
*/
|
||||
return $this->then(null, $onRejected);
|
||||
}
|
||||
|
||||
public function finally(callable $onFulfilledOrRejected): PromiseInterface
|
||||
{
|
||||
return $this->then(null, function (\Throwable $reason) use ($onFulfilledOrRejected): PromiseInterface {
|
||||
return resolve($onFulfilledOrRejected())->then(function () use ($reason): PromiseInterface {
|
||||
return new RejectedPromise($reason);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public function cancel(): void
|
||||
{
|
||||
$this->handled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 3.0.0 Use `catch()` instead
|
||||
* @see self::catch()
|
||||
*/
|
||||
public function otherwise(callable $onRejected): PromiseInterface
|
||||
{
|
||||
return $this->catch($onRejected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 3.0.0 Use `always()` instead
|
||||
* @see self::always()
|
||||
*/
|
||||
public function always(callable $onFulfilledOrRejected): PromiseInterface
|
||||
{
|
||||
return $this->finally($onFulfilledOrRejected);
|
||||
}
|
||||
}
|
||||
Vendored
+304
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
|
||||
namespace React\Promise;
|
||||
|
||||
use React\Promise\Internal\RejectedPromise;
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @template-implements PromiseInterface<T>
|
||||
*/
|
||||
final class Promise implements PromiseInterface
|
||||
{
|
||||
/** @var (callable(callable(T):void,callable(\Throwable):void):void)|null */
|
||||
private $canceller;
|
||||
|
||||
/** @var ?PromiseInterface<T> */
|
||||
private $result;
|
||||
|
||||
/** @var list<callable(PromiseInterface<T>):void> */
|
||||
private $handlers = [];
|
||||
|
||||
/** @var int */
|
||||
private $requiredCancelRequests = 0;
|
||||
|
||||
/** @var bool */
|
||||
private $cancelled = false;
|
||||
|
||||
/**
|
||||
* @param callable(callable(T):void,callable(\Throwable):void):void $resolver
|
||||
* @param (callable(callable(T):void,callable(\Throwable):void):void)|null $canceller
|
||||
*/
|
||||
public function __construct(callable $resolver, ?callable $canceller = null)
|
||||
{
|
||||
$this->canceller = $canceller;
|
||||
|
||||
// Explicitly overwrite arguments with null values before invoking
|
||||
// resolver function. This ensure that these arguments do not show up
|
||||
// in the stack trace in PHP 7+ only.
|
||||
$cb = $resolver;
|
||||
$resolver = $canceller = null;
|
||||
$this->call($cb);
|
||||
}
|
||||
|
||||
public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface
|
||||
{
|
||||
if (null !== $this->result) {
|
||||
return $this->result->then($onFulfilled, $onRejected);
|
||||
}
|
||||
|
||||
if (null === $this->canceller) {
|
||||
return new static($this->resolver($onFulfilled, $onRejected));
|
||||
}
|
||||
|
||||
// This promise has a canceller, so we create a new child promise which
|
||||
// has a canceller that invokes the parent canceller if all other
|
||||
// followers are also cancelled. We keep a reference to this promise
|
||||
// instance for the static canceller function and clear this to avoid
|
||||
// keeping a cyclic reference between parent and follower.
|
||||
$parent = $this;
|
||||
++$parent->requiredCancelRequests;
|
||||
|
||||
return new static(
|
||||
$this->resolver($onFulfilled, $onRejected),
|
||||
static function () use (&$parent): void {
|
||||
assert($parent instanceof self);
|
||||
--$parent->requiredCancelRequests;
|
||||
|
||||
if ($parent->requiredCancelRequests <= 0) {
|
||||
$parent->cancel();
|
||||
}
|
||||
|
||||
$parent = null;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @template TThrowable of \Throwable
|
||||
* @template TRejected
|
||||
* @param callable(TThrowable): (PromiseInterface<TRejected>|TRejected) $onRejected
|
||||
* @return PromiseInterface<T|TRejected>
|
||||
*/
|
||||
public function catch(callable $onRejected): PromiseInterface
|
||||
{
|
||||
return $this->then(null, static function (\Throwable $reason) use ($onRejected) {
|
||||
if (!_checkTypehint($onRejected, $reason)) {
|
||||
return new RejectedPromise($reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var callable(\Throwable):(PromiseInterface<TRejected>|TRejected) $onRejected
|
||||
*/
|
||||
return $onRejected($reason);
|
||||
});
|
||||
}
|
||||
|
||||
public function finally(callable $onFulfilledOrRejected): PromiseInterface
|
||||
{
|
||||
return $this->then(static function ($value) use ($onFulfilledOrRejected): PromiseInterface {
|
||||
/** @var T $value */
|
||||
return resolve($onFulfilledOrRejected())->then(function () use ($value) {
|
||||
return $value;
|
||||
});
|
||||
}, static function (\Throwable $reason) use ($onFulfilledOrRejected): PromiseInterface {
|
||||
return resolve($onFulfilledOrRejected())->then(function () use ($reason): RejectedPromise {
|
||||
return new RejectedPromise($reason);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public function cancel(): void
|
||||
{
|
||||
$this->cancelled = true;
|
||||
$canceller = $this->canceller;
|
||||
$this->canceller = null;
|
||||
|
||||
$parentCanceller = null;
|
||||
|
||||
if (null !== $this->result) {
|
||||
// Forward cancellation to rejected promise to avoid reporting unhandled rejection
|
||||
if ($this->result instanceof RejectedPromise) {
|
||||
$this->result->cancel();
|
||||
}
|
||||
|
||||
// Go up the promise chain and reach the top most promise which is
|
||||
// itself not following another promise
|
||||
$root = $this->unwrap($this->result);
|
||||
|
||||
// Return if the root promise is already resolved or a
|
||||
// FulfilledPromise or RejectedPromise
|
||||
if (!$root instanceof self || null !== $root->result) {
|
||||
return;
|
||||
}
|
||||
|
||||
$root->requiredCancelRequests--;
|
||||
|
||||
if ($root->requiredCancelRequests <= 0) {
|
||||
$parentCanceller = [$root, 'cancel'];
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $canceller) {
|
||||
$this->call($canceller);
|
||||
}
|
||||
|
||||
// For BC, we call the parent canceller after our own canceller
|
||||
if ($parentCanceller) {
|
||||
$parentCanceller();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 3.0.0 Use `catch()` instead
|
||||
* @see self::catch()
|
||||
*/
|
||||
public function otherwise(callable $onRejected): PromiseInterface
|
||||
{
|
||||
return $this->catch($onRejected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 3.0.0 Use `finally()` instead
|
||||
* @see self::finally()
|
||||
*/
|
||||
public function always(callable $onFulfilledOrRejected): PromiseInterface
|
||||
{
|
||||
return $this->finally($onFulfilledOrRejected);
|
||||
}
|
||||
|
||||
private function resolver(?callable $onFulfilled = null, ?callable $onRejected = null): callable
|
||||
{
|
||||
return function (callable $resolve, callable $reject) use ($onFulfilled, $onRejected): void {
|
||||
$this->handlers[] = static function (PromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject): void {
|
||||
$promise = $promise->then($onFulfilled, $onRejected);
|
||||
|
||||
if ($promise instanceof self && $promise->result === null) {
|
||||
$promise->handlers[] = static function (PromiseInterface $promise) use ($resolve, $reject): void {
|
||||
$promise->then($resolve, $reject);
|
||||
};
|
||||
} else {
|
||||
$promise->then($resolve, $reject);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
private function reject(\Throwable $reason): void
|
||||
{
|
||||
if (null !== $this->result) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->settle(reject($reason));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PromiseInterface<T> $result
|
||||
*/
|
||||
private function settle(PromiseInterface $result): void
|
||||
{
|
||||
$result = $this->unwrap($result);
|
||||
|
||||
if ($result === $this) {
|
||||
$result = new RejectedPromise(
|
||||
new \LogicException('Cannot resolve a promise with itself.')
|
||||
);
|
||||
}
|
||||
|
||||
if ($result instanceof self) {
|
||||
$result->requiredCancelRequests++;
|
||||
} else {
|
||||
// Unset canceller only when not following a pending promise
|
||||
$this->canceller = null;
|
||||
}
|
||||
|
||||
$handlers = $this->handlers;
|
||||
|
||||
$this->handlers = [];
|
||||
$this->result = $result;
|
||||
|
||||
foreach ($handlers as $handler) {
|
||||
$handler($result);
|
||||
}
|
||||
|
||||
// Forward cancellation to rejected promise to avoid reporting unhandled rejection
|
||||
if ($this->cancelled && $result instanceof RejectedPromise) {
|
||||
$result->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PromiseInterface<T> $promise
|
||||
* @return PromiseInterface<T>
|
||||
*/
|
||||
private function unwrap(PromiseInterface $promise): PromiseInterface
|
||||
{
|
||||
while ($promise instanceof self && null !== $promise->result) {
|
||||
/** @var PromiseInterface<T> $promise */
|
||||
$promise = $promise->result;
|
||||
}
|
||||
|
||||
return $promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable(callable(mixed):void,callable(\Throwable):void):void $cb
|
||||
*/
|
||||
private function call(callable $cb): void
|
||||
{
|
||||
// Explicitly overwrite argument with null value. This ensure that this
|
||||
// argument does not show up in the stack trace in PHP 7+ only.
|
||||
$callback = $cb;
|
||||
$cb = null;
|
||||
|
||||
// Use reflection to inspect number of arguments expected by this callback.
|
||||
// We did some careful benchmarking here: Using reflection to avoid unneeded
|
||||
// function arguments is actually faster than blindly passing them.
|
||||
// Also, this helps avoiding unnecessary function arguments in the call stack
|
||||
// if the callback creates an Exception (creating garbage cycles).
|
||||
if (\is_array($callback)) {
|
||||
$ref = new \ReflectionMethod($callback[0], $callback[1]);
|
||||
} elseif (\is_object($callback) && !$callback instanceof \Closure) {
|
||||
$ref = new \ReflectionMethod($callback, '__invoke');
|
||||
} else {
|
||||
assert($callback instanceof \Closure || \is_string($callback));
|
||||
$ref = new \ReflectionFunction($callback);
|
||||
}
|
||||
$args = $ref->getNumberOfParameters();
|
||||
|
||||
try {
|
||||
if ($args === 0) {
|
||||
$callback();
|
||||
} else {
|
||||
// Keep references to this promise instance for the static resolve/reject functions.
|
||||
// By using static callbacks that are not bound to this instance
|
||||
// and passing the target promise instance by reference, we can
|
||||
// still execute its resolving logic and still clear this
|
||||
// reference when settling the promise. This helps avoiding
|
||||
// garbage cycles if any callback creates an Exception.
|
||||
// These assumptions are covered by the test suite, so if you ever feel like
|
||||
// refactoring this, go ahead, any alternative suggestions are welcome!
|
||||
$target =& $this;
|
||||
|
||||
$callback(
|
||||
static function ($value) use (&$target): void {
|
||||
if ($target !== null) {
|
||||
$target->settle(resolve($value));
|
||||
$target = null;
|
||||
}
|
||||
},
|
||||
static function (\Throwable $reason) use (&$target): void {
|
||||
if ($target !== null) {
|
||||
$target->reject($reason);
|
||||
$target = null;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$target = null;
|
||||
$this->reject($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace React\Promise;
|
||||
|
||||
/**
|
||||
* @template-covariant T
|
||||
*/
|
||||
interface PromiseInterface
|
||||
{
|
||||
/**
|
||||
* Transforms a promise's value by applying a function to the promise's fulfillment
|
||||
* or rejection value. Returns a new promise for the transformed result.
|
||||
*
|
||||
* The `then()` method registers new fulfilled and rejection handlers with a promise
|
||||
* (all parameters are optional):
|
||||
*
|
||||
* * `$onFulfilled` will be invoked once the promise is fulfilled and passed
|
||||
* the result as the first argument.
|
||||
* * `$onRejected` will be invoked once the promise is rejected and passed the
|
||||
* reason as the first argument.
|
||||
*
|
||||
* It returns a new promise that will fulfill with the return value of either
|
||||
* `$onFulfilled` or `$onRejected`, whichever is called, or will reject with
|
||||
* the thrown exception if either throws.
|
||||
*
|
||||
* A promise makes the following guarantees about handlers registered in
|
||||
* the same call to `then()`:
|
||||
*
|
||||
* 1. Only one of `$onFulfilled` or `$onRejected` will be called,
|
||||
* never both.
|
||||
* 2. `$onFulfilled` and `$onRejected` will never be called more
|
||||
* than once.
|
||||
*
|
||||
* @template TFulfilled
|
||||
* @template TRejected
|
||||
* @param ?(callable((T is void ? null : T)): (PromiseInterface<TFulfilled>|TFulfilled)) $onFulfilled
|
||||
* @param ?(callable(\Throwable): (PromiseInterface<TRejected>|TRejected)) $onRejected
|
||||
* @return PromiseInterface<($onRejected is null ? ($onFulfilled is null ? T : TFulfilled) : ($onFulfilled is null ? T|TRejected : TFulfilled|TRejected))>
|
||||
*/
|
||||
public function then(?callable $onFulfilled = null, ?callable $onRejected = null): PromiseInterface;
|
||||
|
||||
/**
|
||||
* Registers a rejection handler for promise. It is a shortcut for:
|
||||
*
|
||||
* ```php
|
||||
* $promise->then(null, $onRejected);
|
||||
* ```
|
||||
*
|
||||
* Additionally, you can type hint the `$reason` argument of `$onRejected` to catch
|
||||
* only specific errors.
|
||||
*
|
||||
* @template TThrowable of \Throwable
|
||||
* @template TRejected
|
||||
* @param callable(TThrowable): (PromiseInterface<TRejected>|TRejected) $onRejected
|
||||
* @return PromiseInterface<T|TRejected>
|
||||
*/
|
||||
public function catch(callable $onRejected): PromiseInterface;
|
||||
|
||||
/**
|
||||
* Allows you to execute "cleanup" type tasks in a promise chain.
|
||||
*
|
||||
* It arranges for `$onFulfilledOrRejected` to be called, with no arguments,
|
||||
* when the promise is either fulfilled or rejected.
|
||||
*
|
||||
* * If `$promise` fulfills, and `$onFulfilledOrRejected` returns successfully,
|
||||
* `$newPromise` will fulfill with the same value as `$promise`.
|
||||
* * If `$promise` fulfills, and `$onFulfilledOrRejected` throws or returns a
|
||||
* rejected promise, `$newPromise` will reject with the thrown exception or
|
||||
* rejected promise's reason.
|
||||
* * If `$promise` rejects, and `$onFulfilledOrRejected` returns successfully,
|
||||
* `$newPromise` will reject with the same reason as `$promise`.
|
||||
* * If `$promise` rejects, and `$onFulfilledOrRejected` throws or returns a
|
||||
* rejected promise, `$newPromise` will reject with the thrown exception or
|
||||
* rejected promise's reason.
|
||||
*
|
||||
* `finally()` behaves similarly to the synchronous finally statement. When combined
|
||||
* with `catch()`, `finally()` allows you to write code that is similar to the familiar
|
||||
* synchronous catch/finally pair.
|
||||
*
|
||||
* Consider the following synchronous code:
|
||||
*
|
||||
* ```php
|
||||
* try {
|
||||
* return doSomething();
|
||||
* } catch(\Exception $e) {
|
||||
* return handleError($e);
|
||||
* } finally {
|
||||
* cleanup();
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Similar asynchronous code (with `doSomething()` that returns a promise) can be
|
||||
* written:
|
||||
*
|
||||
* ```php
|
||||
* return doSomething()
|
||||
* ->catch('handleError')
|
||||
* ->finally('cleanup');
|
||||
* ```
|
||||
*
|
||||
* @param callable(): (void|PromiseInterface<void>) $onFulfilledOrRejected
|
||||
* @return PromiseInterface<T>
|
||||
*/
|
||||
public function finally(callable $onFulfilledOrRejected): PromiseInterface;
|
||||
|
||||
/**
|
||||
* The `cancel()` method notifies the creator of the promise that there is no
|
||||
* further interest in the results of the operation.
|
||||
*
|
||||
* Once a promise is settled (either fulfilled or rejected), calling `cancel()` on
|
||||
* a promise has no effect.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cancel(): void;
|
||||
|
||||
/**
|
||||
* [Deprecated] Registers a rejection handler for a promise.
|
||||
*
|
||||
* This method continues to exist only for BC reasons and to ease upgrading
|
||||
* between versions. It is an alias for:
|
||||
*
|
||||
* ```php
|
||||
* $promise->catch($onRejected);
|
||||
* ```
|
||||
*
|
||||
* @template TThrowable of \Throwable
|
||||
* @template TRejected
|
||||
* @param callable(TThrowable): (PromiseInterface<TRejected>|TRejected) $onRejected
|
||||
* @return PromiseInterface<T|TRejected>
|
||||
* @deprecated 3.0.0 Use catch() instead
|
||||
* @see self::catch()
|
||||
*/
|
||||
public function otherwise(callable $onRejected): PromiseInterface;
|
||||
|
||||
/**
|
||||
* [Deprecated] Allows you to execute "cleanup" type tasks in a promise chain.
|
||||
*
|
||||
* This method continues to exist only for BC reasons and to ease upgrading
|
||||
* between versions. It is an alias for:
|
||||
*
|
||||
* ```php
|
||||
* $promise->finally($onFulfilledOrRejected);
|
||||
* ```
|
||||
*
|
||||
* @param callable(): (void|PromiseInterface<void>) $onFulfilledOrRejected
|
||||
* @return PromiseInterface<T>
|
||||
* @deprecated 3.0.0 Use finally() instead
|
||||
* @see self::finally()
|
||||
*/
|
||||
public function always(callable $onFulfilledOrRejected): PromiseInterface;
|
||||
}
|
||||
+345
@@ -0,0 +1,345 @@
|
||||
<?php
|
||||
|
||||
namespace React\Promise;
|
||||
|
||||
use React\Promise\Exception\CompositeException;
|
||||
use React\Promise\Internal\FulfilledPromise;
|
||||
use React\Promise\Internal\RejectedPromise;
|
||||
|
||||
/**
|
||||
* Creates a promise for the supplied `$promiseOrValue`.
|
||||
*
|
||||
* If `$promiseOrValue` is a value, it will be the resolution value of the
|
||||
* returned promise.
|
||||
*
|
||||
* If `$promiseOrValue` is a thenable (any object that provides a `then()` method),
|
||||
* a trusted promise that follows the state of the thenable is returned.
|
||||
*
|
||||
* If `$promiseOrValue` is a promise, it will be returned as is.
|
||||
*
|
||||
* @template T
|
||||
* @param PromiseInterface<T>|T $promiseOrValue
|
||||
* @return PromiseInterface<T>
|
||||
*/
|
||||
function resolve($promiseOrValue): PromiseInterface
|
||||
{
|
||||
if ($promiseOrValue instanceof PromiseInterface) {
|
||||
return $promiseOrValue;
|
||||
}
|
||||
|
||||
if (\is_object($promiseOrValue) && \method_exists($promiseOrValue, 'then')) {
|
||||
$canceller = null;
|
||||
|
||||
if (\method_exists($promiseOrValue, 'cancel')) {
|
||||
$canceller = [$promiseOrValue, 'cancel'];
|
||||
assert(\is_callable($canceller));
|
||||
}
|
||||
|
||||
/** @var Promise<T> */
|
||||
return new Promise(function (callable $resolve, callable $reject) use ($promiseOrValue): void {
|
||||
$promiseOrValue->then($resolve, $reject);
|
||||
}, $canceller);
|
||||
}
|
||||
|
||||
return new FulfilledPromise($promiseOrValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a rejected promise for the supplied `$reason`.
|
||||
*
|
||||
* If `$reason` is a value, it will be the rejection value of the
|
||||
* returned promise.
|
||||
*
|
||||
* If `$reason` is a promise, its completion value will be the rejected
|
||||
* value of the returned promise.
|
||||
*
|
||||
* This can be useful in situations where you need to reject a promise without
|
||||
* throwing an exception. For example, it allows you to propagate a rejection with
|
||||
* the value of another promise.
|
||||
*
|
||||
* @return PromiseInterface<never>
|
||||
*/
|
||||
function reject(\Throwable $reason): PromiseInterface
|
||||
{
|
||||
return new RejectedPromise($reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a promise that will resolve only once all the items in
|
||||
* `$promisesOrValues` have resolved. The resolution value of the returned promise
|
||||
* will be an array containing the resolution values of each of the items in
|
||||
* `$promisesOrValues`.
|
||||
*
|
||||
* @template T
|
||||
* @param iterable<PromiseInterface<T>|T> $promisesOrValues
|
||||
* @return PromiseInterface<array<T>>
|
||||
*/
|
||||
function all(iterable $promisesOrValues): PromiseInterface
|
||||
{
|
||||
$cancellationQueue = new Internal\CancellationQueue();
|
||||
|
||||
/** @var Promise<array<T>> */
|
||||
return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void {
|
||||
$toResolve = 0;
|
||||
/** @var bool */
|
||||
$continue = true;
|
||||
$values = [];
|
||||
|
||||
foreach ($promisesOrValues as $i => $promiseOrValue) {
|
||||
$cancellationQueue->enqueue($promiseOrValue);
|
||||
$values[$i] = null;
|
||||
++$toResolve;
|
||||
|
||||
resolve($promiseOrValue)->then(
|
||||
function ($value) use ($i, &$values, &$toResolve, &$continue, $resolve): void {
|
||||
$values[$i] = $value;
|
||||
|
||||
if (0 === --$toResolve && !$continue) {
|
||||
$resolve($values);
|
||||
}
|
||||
},
|
||||
function (\Throwable $reason) use (&$continue, $reject): void {
|
||||
$continue = false;
|
||||
$reject($reason);
|
||||
}
|
||||
);
|
||||
|
||||
if (!$continue && !\is_array($promisesOrValues)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$continue = false;
|
||||
if ($toResolve === 0) {
|
||||
$resolve($values);
|
||||
}
|
||||
}, $cancellationQueue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates a competitive race that allows one winner. Returns a promise which is
|
||||
* resolved in the same way the first settled promise resolves.
|
||||
*
|
||||
* The returned promise will become **infinitely pending** if `$promisesOrValues`
|
||||
* contains 0 items.
|
||||
*
|
||||
* @template T
|
||||
* @param iterable<PromiseInterface<T>|T> $promisesOrValues
|
||||
* @return PromiseInterface<T>
|
||||
*/
|
||||
function race(iterable $promisesOrValues): PromiseInterface
|
||||
{
|
||||
$cancellationQueue = new Internal\CancellationQueue();
|
||||
|
||||
/** @var Promise<T> */
|
||||
return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void {
|
||||
$continue = true;
|
||||
|
||||
foreach ($promisesOrValues as $promiseOrValue) {
|
||||
$cancellationQueue->enqueue($promiseOrValue);
|
||||
|
||||
resolve($promiseOrValue)->then($resolve, $reject)->finally(function () use (&$continue): void {
|
||||
$continue = false;
|
||||
});
|
||||
|
||||
if (!$continue && !\is_array($promisesOrValues)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, $cancellationQueue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a promise that will resolve when any one of the items in
|
||||
* `$promisesOrValues` resolves. The resolution value of the returned promise
|
||||
* will be the resolution value of the triggering item.
|
||||
*
|
||||
* The returned promise will only reject if *all* items in `$promisesOrValues` are
|
||||
* rejected. The rejection value will be an array of all rejection reasons.
|
||||
*
|
||||
* The returned promise will also reject with a `React\Promise\Exception\LengthException`
|
||||
* if `$promisesOrValues` contains 0 items.
|
||||
*
|
||||
* @template T
|
||||
* @param iterable<PromiseInterface<T>|T> $promisesOrValues
|
||||
* @return PromiseInterface<T>
|
||||
*/
|
||||
function any(iterable $promisesOrValues): PromiseInterface
|
||||
{
|
||||
$cancellationQueue = new Internal\CancellationQueue();
|
||||
|
||||
/** @var Promise<T> */
|
||||
return new Promise(function (callable $resolve, callable $reject) use ($promisesOrValues, $cancellationQueue): void {
|
||||
$toReject = 0;
|
||||
$continue = true;
|
||||
$reasons = [];
|
||||
|
||||
foreach ($promisesOrValues as $i => $promiseOrValue) {
|
||||
$cancellationQueue->enqueue($promiseOrValue);
|
||||
++$toReject;
|
||||
|
||||
resolve($promiseOrValue)->then(
|
||||
function ($value) use ($resolve, &$continue): void {
|
||||
$continue = false;
|
||||
$resolve($value);
|
||||
},
|
||||
function (\Throwable $reason) use ($i, &$reasons, &$toReject, $reject, &$continue): void {
|
||||
$reasons[$i] = $reason;
|
||||
|
||||
if (0 === --$toReject && !$continue) {
|
||||
$reject(new CompositeException(
|
||||
$reasons,
|
||||
'All promises rejected.'
|
||||
));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (!$continue && !\is_array($promisesOrValues)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$continue = false;
|
||||
if ($toReject === 0 && !$reasons) {
|
||||
$reject(new Exception\LengthException(
|
||||
'Must contain at least 1 item but contains only 0 items.'
|
||||
));
|
||||
} elseif ($toReject === 0) {
|
||||
$reject(new CompositeException(
|
||||
$reasons,
|
||||
'All promises rejected.'
|
||||
));
|
||||
}
|
||||
}, $cancellationQueue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the global rejection handler for unhandled promise rejections.
|
||||
*
|
||||
* Note that rejected promises should always be handled similar to how any
|
||||
* exceptions should always be caught in a `try` + `catch` block. If you remove
|
||||
* the last reference to a rejected promise that has not been handled, it will
|
||||
* report an unhandled promise rejection. See also the [`reject()` function](#reject)
|
||||
* for more details.
|
||||
*
|
||||
* The `?callable $callback` argument MUST be a valid callback function that
|
||||
* accepts a single `Throwable` argument or a `null` value to restore the
|
||||
* default promise rejection handler. The return value of the callback function
|
||||
* will be ignored and has no effect, so you SHOULD return a `void` value. The
|
||||
* callback function MUST NOT throw or the program will be terminated with a
|
||||
* fatal error.
|
||||
*
|
||||
* The function returns the previous rejection handler or `null` if using the
|
||||
* default promise rejection handler.
|
||||
*
|
||||
* The default promise rejection handler will log an error message plus its
|
||||
* stack trace:
|
||||
*
|
||||
* ```php
|
||||
* // Unhandled promise rejection with RuntimeException: Unhandled in example.php:2
|
||||
* React\Promise\reject(new RuntimeException('Unhandled'));
|
||||
* ```
|
||||
*
|
||||
* The promise rejection handler may be used to use customize the log message or
|
||||
* write to custom log targets. As a rule of thumb, this function should only be
|
||||
* used as a last resort and promise rejections are best handled with either the
|
||||
* [`then()` method](#promiseinterfacethen), the
|
||||
* [`catch()` method](#promiseinterfacecatch), or the
|
||||
* [`finally()` method](#promiseinterfacefinally).
|
||||
* See also the [`reject()` function](#reject) for more details.
|
||||
*
|
||||
* @param callable(\Throwable):void|null $callback
|
||||
* @return callable(\Throwable):void|null
|
||||
*/
|
||||
function set_rejection_handler(?callable $callback): ?callable
|
||||
{
|
||||
static $current = null;
|
||||
$previous = $current;
|
||||
$current = $callback;
|
||||
|
||||
return $previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function _checkTypehint(callable $callback, \Throwable $reason): bool
|
||||
{
|
||||
if (\is_array($callback)) {
|
||||
$callbackReflection = new \ReflectionMethod($callback[0], $callback[1]);
|
||||
} elseif (\is_object($callback) && !$callback instanceof \Closure) {
|
||||
$callbackReflection = new \ReflectionMethod($callback, '__invoke');
|
||||
} else {
|
||||
assert($callback instanceof \Closure || \is_string($callback));
|
||||
$callbackReflection = new \ReflectionFunction($callback);
|
||||
}
|
||||
|
||||
$parameters = $callbackReflection->getParameters();
|
||||
|
||||
if (!isset($parameters[0])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$expectedException = $parameters[0];
|
||||
|
||||
// Extract the type of the argument and handle different possibilities
|
||||
$type = $expectedException->getType();
|
||||
|
||||
$isTypeUnion = true;
|
||||
$types = [];
|
||||
|
||||
switch (true) {
|
||||
case $type === null:
|
||||
break;
|
||||
case $type instanceof \ReflectionNamedType:
|
||||
$types = [$type];
|
||||
break;
|
||||
case $type instanceof \ReflectionIntersectionType:
|
||||
$isTypeUnion = false;
|
||||
case $type instanceof \ReflectionUnionType:
|
||||
$types = $type->getTypes();
|
||||
break;
|
||||
default:
|
||||
throw new \LogicException('Unexpected return value of ReflectionParameter::getType');
|
||||
}
|
||||
|
||||
// If there is no type restriction, it matches
|
||||
if (empty($types)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($types as $type) {
|
||||
|
||||
if ($type instanceof \ReflectionIntersectionType) {
|
||||
foreach ($type->getTypes() as $typeToMatch) {
|
||||
assert($typeToMatch instanceof \ReflectionNamedType);
|
||||
$name = $typeToMatch->getName();
|
||||
if (!($matches = (!$typeToMatch->isBuiltin() && $reason instanceof $name))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(isset($matches));
|
||||
} else {
|
||||
assert($type instanceof \ReflectionNamedType);
|
||||
$name = $type->getName();
|
||||
$matches = !$type->isBuiltin() && $reason instanceof $name;
|
||||
}
|
||||
|
||||
// If we look for a single match (union), we can return early on match
|
||||
// If we look for a full match (intersection), we can return early on mismatch
|
||||
if ($matches) {
|
||||
if ($isTypeUnion) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (!$isTypeUnion) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we look for a single match (union) and did not return early, we matched no type and are false
|
||||
// If we look for a full match (intersection) and did not return early, we matched all types and are true
|
||||
return $isTypeUnion ? false : true;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
if (!\function_exists('React\Promise\resolve')) {
|
||||
require __DIR__.'/functions.php';
|
||||
}
|
||||
Reference in New Issue
Block a user