|
5 | 5 | use React\EventLoop\Loop; |
6 | 6 | use React\Promise\CancellablePromiseInterface; |
7 | 7 | use React\Promise\Deferred; |
| 8 | +use React\Promise\Promise; |
8 | 9 | use React\Promise\PromiseInterface; |
9 | 10 | use function React\Promise\reject; |
10 | 11 | use function React\Promise\resolve; |
|
52 | 53 | */ |
53 | 54 | function await(PromiseInterface $promise): mixed |
54 | 55 | { |
55 | | - $wait = true; |
56 | | - $resolved = null; |
57 | | - $exception = null; |
58 | | - $rejected = false; |
| 56 | + $fiber = FiberFactory::create(); |
59 | 57 |
|
60 | 58 | $promise->then( |
61 | | - function ($c) use (&$resolved, &$wait) { |
62 | | - $resolved = $c; |
63 | | - $wait = false; |
64 | | - Loop::stop(); |
| 59 | + function (mixed $value) use (&$resolved, $fiber): void { |
| 60 | + $fiber->resume($value); |
65 | 61 | }, |
66 | | - function ($error) use (&$exception, &$rejected, &$wait) { |
67 | | - $exception = $error; |
68 | | - $rejected = true; |
69 | | - $wait = false; |
70 | | - Loop::stop(); |
| 62 | + function (mixed $throwable) use (&$resolved, $fiber): void { |
| 63 | + $fiber->throw($throwable); |
71 | 64 | } |
72 | 65 | ); |
73 | 66 |
|
74 | | - // Explicitly overwrite argument with null value. This ensure that this |
75 | | - // argument does not show up in the stack trace in PHP 7+ only. |
76 | | - $promise = null; |
77 | | - |
78 | | - while ($wait) { |
79 | | - Loop::run(); |
80 | | - } |
81 | | - |
82 | | - if ($rejected) { |
83 | | - // promise is rejected with an unexpected value (Promise API v1 or v2 only) |
84 | | - if (!$exception instanceof \Throwable) { |
85 | | - $exception = new \UnexpectedValueException( |
86 | | - 'Promise rejected with unexpected value of type ' . (is_object($exception) ? get_class($exception) : gettype($exception)) |
87 | | - ); |
88 | | - } |
| 67 | + return $fiber->suspend(); |
| 68 | +} |
89 | 69 |
|
90 | | - throw $exception; |
| 70 | +/** |
| 71 | + * @internal |
| 72 | + */ |
| 73 | +function fiber(callable $callable): \Fiber |
| 74 | +{ |
| 75 | + static $scheduler = null; |
| 76 | + |
| 77 | + if ($scheduler === null || $scheduler->isTerminated()) { |
| 78 | + $scheduler = new \Fiber($callable); |
| 79 | + // Run event loop to completion on shutdown. |
| 80 | + \register_shutdown_function(static function () use ($scheduler): void { |
| 81 | + if ($scheduler->isSuspended()) { |
| 82 | + $scheduler->resume(); |
| 83 | + } |
| 84 | + }); |
91 | 85 | } |
92 | 86 |
|
93 | | - return $resolved; |
| 87 | + return $scheduler; |
94 | 88 | } |
95 | 89 |
|
96 | | - |
97 | 90 | /** |
98 | 91 | * Execute a Generator-based coroutine to "await" promises. |
99 | 92 | * |
|
0 commit comments