66
77use BadMethodCallException ;
88use Fiber ;
9+ use Generator ;
910use SplObjectStorage ;
1011use SplQueue ;
1112use Throwable ;
@@ -235,7 +236,7 @@ public function setInterval(callable $callback, float $interval): int
235236 /**
236237 * Cancel a scheduled timer.
237238 *
238- * @param int $timerId The timer ID returned by setTimeout or setInterval
239+ * @param int $timerId The timer's ID returned by setTimeout or setInterval
239240 * @return void
240241 */
241242 public function clearTimer (int $ timerId ): void
@@ -268,7 +269,29 @@ public function async(callable $callable, ?CancellationTokenInterface $cancellat
268269 $ cancellationToken ?->throwIfCancellationRequested();
269270
270271 $ result = $ callable ();
271- $ deferred ->resolve ($ result );
272+
273+ if ($ result instanceof Generator) {
274+ $ value = null ;
275+ while ($ result ->valid ()) {
276+ $ yielded = $ result ->current ();
277+
278+ // If the yielded value is a Fiber, resume it
279+ if ($ yielded instanceof Fiber) {
280+ $ value = $ yielded ->isTerminated ()
281+ ? $ yielded ->getReturn ()
282+ : ($ yielded ->isSuspended () ? $ yielded ->resume () : $ yielded ->start ());
283+ } else {
284+ $ value = $ yielded ;
285+ }
286+
287+ EventLoop::getInstance ()->yield ();
288+ $ result ->next ();
289+ }
290+
291+ $ deferred ->resolve ($ result ->getReturn () ?? $ value ?? null );
292+ } else {
293+ $ deferred ->resolve ($ result );
294+ }
272295 } catch (Throwable $ e ) {
273296 $ deferred ->reject ($ e );
274297 }
@@ -281,7 +304,7 @@ public function async(callable $callable, ?CancellationTokenInterface $cancellat
281304 'startTime ' => $ this ->getCurrentTime ()
282305 ];
283306
284- // Set up cancellation if token is provided
307+ // Set up cancellation if a token is provided
285308 $ cancellationToken ?->register(function () use ($ fiber , $ deferred ): void {
286309 if (isset ($ this ->fibers [$ fiber ])) {
287310 try {
0 commit comments