mirror of
https://github.com/danog/amp.git
synced 2024-11-30 04:29:08 +01:00
Minor coroutine refactoring/optimization; add makeGeneratorError()
This commit is contained in:
parent
1d777c7e3e
commit
40fbb6e16d
@ -527,7 +527,7 @@ function wait(Promise $promise, Reactor $reactor = null) {
|
|||||||
*/
|
*/
|
||||||
function coroutine(callable $func, Reactor $reactor = null) {
|
function coroutine(callable $func, Reactor $reactor = null) {
|
||||||
return function() use ($func, $reactor) {
|
return function() use ($func, $reactor) {
|
||||||
$result = \call_user_func_array($func, func_get_args());
|
$result = \call_user_func_array($func, \func_get_args());
|
||||||
return ($result instanceof \Generator)
|
return ($result instanceof \Generator)
|
||||||
? resolve($result, $reactor)
|
? resolve($result, $reactor)
|
||||||
: $result;
|
: $result;
|
||||||
@ -550,7 +550,6 @@ function resolve(\Generator $generator, Reactor $reactor = null) {
|
|||||||
$cs->generator = $generator;
|
$cs->generator = $generator;
|
||||||
$cs->returnValue = null;
|
$cs->returnValue = null;
|
||||||
$cs->currentPromise = null;
|
$cs->currentPromise = null;
|
||||||
$cs->isResolved = false;
|
|
||||||
|
|
||||||
__coroutineAdvance($cs);
|
__coroutineAdvance($cs);
|
||||||
|
|
||||||
@ -572,28 +571,30 @@ function __coroutineAdvance($cs) {
|
|||||||
}
|
}
|
||||||
} elseif (($key = $cs->generator->key()) === "return") {
|
} elseif (($key = $cs->generator->key()) === "return") {
|
||||||
$cs->returnValue = $yielded;
|
$cs->returnValue = $yielded;
|
||||||
$cs->reactor->immediately("Amp\__coroutineNextTick", ["cb_data" => $cs]);
|
__coroutineSend(null, null, $cs);
|
||||||
} elseif ($yielded instanceof Promise) {
|
} elseif ($yielded instanceof Promise) {
|
||||||
$cs->currentPromise = $yielded;
|
$cs->currentPromise = $yielded;
|
||||||
$cs->reactor->immediately("Amp\__coroutineNextTick", ["cb_data" => $cs]);
|
$cs->reactor->immediately("Amp\__coroutineNextTick", ["cb_data" => $cs]);
|
||||||
} else {
|
} else {
|
||||||
$cs->isResolved = true;
|
$error = makeGeneratorError($cs->generator, sprintf(
|
||||||
$cs->promisor->fail(new \DomainException(
|
'Unexpected yield (Promise|null|"return" expected); %s yielded at key %s',
|
||||||
__coroutineYieldError($cs->generator, $key, $yielded)
|
is_object($yielded) ? get_class($yielded) : gettype($yielded),
|
||||||
|
$key
|
||||||
));
|
));
|
||||||
|
$cs->reactor->immediately(function() use ($cs, $error) {
|
||||||
|
$cs->promisor->fail(new \DomainException($error));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (\Exception $uncaught) {
|
} catch (\Exception $uncaught) {
|
||||||
if ($cs->isResolved) {
|
$cs->reactor->immediately(function() use ($cs, $uncaught) {
|
||||||
throw new \RuntimeException("", 0, $uncaught);
|
|
||||||
} else {
|
|
||||||
$cs->isResolved = true;
|
|
||||||
$cs->promisor->fail($uncaught);
|
$cs->promisor->fail($uncaught);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function __coroutineNextTick($reactor, $watcherId, $cs) {
|
function __coroutineNextTick($reactor, $watcherId, $cs) {
|
||||||
if ($promise = $cs->currentPromise) {
|
if ($cs->currentPromise) {
|
||||||
|
$promise = $cs->currentPromise;
|
||||||
$cs->currentPromise = null;
|
$cs->currentPromise = null;
|
||||||
$promise->when("Amp\__coroutineSend", $cs);
|
$promise->when("Amp\__coroutineSend", $cs);
|
||||||
} else {
|
} else {
|
||||||
@ -610,32 +611,32 @@ function __coroutineSend($error, $result, $cs) {
|
|||||||
}
|
}
|
||||||
__coroutineAdvance($cs);
|
__coroutineAdvance($cs);
|
||||||
} catch (\Exception $uncaught) {
|
} catch (\Exception $uncaught) {
|
||||||
if ($cs->isResolved) {
|
$cs->reactor->immediately(function() use ($cs, $uncaught) {
|
||||||
throw new \RuntimeException("", 0, $uncaught);
|
|
||||||
} else {
|
|
||||||
$cs->isResolved = true;
|
|
||||||
$cs->promisor->fail($uncaught);
|
$cs->promisor->fail($uncaught);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function __coroutineYieldError($generator, $key, $yielded) {
|
/**
|
||||||
$type = is_object($yielded) ? get_class($yielded) : gettype($yielded);
|
* A general purpose function for creating error messages from generator yields
|
||||||
$msg = "Unexpected Generator yield (Promise|\"return\"|null expected); {$type} yielded at key {$key}";
|
*
|
||||||
if (PHP_MAJOR_VERSION < 7) {
|
* @param \Generator $generator
|
||||||
return $msg;
|
* @param string $prefix
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function makeGeneratorError(\Generator $generator, $prefix = "Generator error") {
|
||||||
|
if (PHP_MAJOR_VERSION < 7 || !$generator->valid()) {
|
||||||
|
return $prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
$reflGen = new \ReflectionGenerator($generator);
|
$reflGen = new \ReflectionGenerator($generator);
|
||||||
$exeGen = $reflGen->getExecutingGenerator();
|
$exeGen = $reflGen->getExecutingGenerator();
|
||||||
if ($exeGen !== $generator) {
|
if ($isSubgenerator = ($exeGen !== $generator)) {
|
||||||
// We're executing a subgenerator; use the correct reflection
|
|
||||||
$reflGen = new \ReflectionGenerator($exeGen);
|
$reflGen = new \ReflectionGenerator($exeGen);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sprintf(
|
return sprintf(
|
||||||
"%s on line %s in %s",
|
"{$prefix} on line %s in %s",
|
||||||
$msg,
|
|
||||||
$reflGen->getExecutingLine(),
|
$reflGen->getExecutingLine(),
|
||||||
$reflGen->getExecutingFile()
|
$reflGen->getExecutingFile()
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user