Fix bin/publish: copy docs.dist from project root

Fix bin/publish: use correct .env path for rspade_system
Fix bin/publish script: prevent grep exit code 1 from terminating script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-10-21 02:08:33 +00:00
commit f6fac6c4bc
79758 changed files with 10547827 additions and 0 deletions

52
vendor/react/promise/src/Deferred.php vendored Executable file
View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,7 @@
<?php
namespace React\Promise\Exception;
class LengthException extends \LengthException
{
}

View File

@@ -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 = [];
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

304
vendor/react/promise/src/Promise.php vendored Executable file
View File

@@ -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
vendor/react/promise/src/PromiseInterface.php vendored Executable file
View File

@@ -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
vendor/react/promise/src/functions.php vendored Executable file
View File

@@ -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;
}

View File

@@ -0,0 +1,5 @@
<?php
if (!\function_exists('React\Promise\resolve')) {
require __DIR__.'/functions.php';
}