/** * Handle resolving generators still running. * @param GeneratorContainer $gc * @return PromiseInterface */ private function processGeneratorContainerRunning(GeneratorContainer $gc) { // Check delay request yields if ($gc->key() === CoInterface::DELAY) { return $this->pool->addDelay($gc->current())->then(function () use($gc) { $gc->send(null); return $this->processGeneratorContainer($gc); }); } // Now we normalize yielded value $yielded = YieldableUtils::normalize($gc->current()); $yieldables = YieldableUtils::getYieldables($yielded, [], $this->runners); if (!$yieldables) { // If there are no yieldables, send yielded value back into generator $gc->send($yielded); // Continue return $this->processGeneratorContainer($gc); } // Chain resolver return $this->promiseAll($yieldables, $gc->key() !== CoInterface::SAFE)->then(YieldableUtils::getApplier($yielded, $yieldables, [$gc, 'send']), [$gc, 'throw_'])->then(function () use($gc, $yieldables) { // Continue $this->runners = array_diff_key($this->runners, $yieldables); return $this->processGeneratorContainer($gc); }); }
public function testExternalException() { $gen = (function () { $this->assertInstanceOf(\RuntimeException::class, (yield CoInterface::SAFE => null)); (yield null); })(); $con = new GeneratorContainer($gen); $con->key() === CoInterface::SAFE ? $con->send(new \RuntimeException()) : $con->throw_(new \RuntimeException()); $this->assertTrue($con->valid()); $this->assertFalse($con->thrown()); $gen = (function () { (yield null); (yield null); })(); $con = new GeneratorContainer($gen); $con->key() === CoInterface::SAFE ? $con->send(new \RuntimeException()) : $con->throw_(new \RuntimeException()); $this->assertFalse($con->valid()); $this->assertTrue($con->thrown()); $this->assertInstanceOf(\RuntimeException::class, $con->getReturnOrThrown()); }