Fix coroutine executor when using with promise

This commit is contained in:
Jeremiah VALERIE 2019-06-02 20:25:22 +02:00
parent 0b4b1485e0
commit 08d9493b2c
No known key found for this signature in database
GPG Key ID: 668676FD50ADF244
2 changed files with 19 additions and 5 deletions

View File

@ -293,13 +293,17 @@ class CoroutineExecutor implements Runtime, ExecutorImplementation
$strand->stack[$strand->depth++] = $strand->current; $strand->stack[$strand->depth++] = $strand->current;
$strand->current = $value; $strand->current = $value;
goto START; goto START;
} elseif ($this->promiseAdapter->isThenable($value)) { } elseif ($this->isPromise($value)) {
// !!! increment pending before calling ->then() as it may invoke the callback right away // !!! increment pending before calling ->then() as it may invoke the callback right away
++$this->pending; ++$this->pending;
if (! $value instanceof Promise) {
$value = $this->promiseAdapter->convertThenable($value);
}
$this->promiseAdapter $this->promiseAdapter
->convertThenable($value)
->then( ->then(
$value,
function ($value) use ($strand) { function ($value) use ($strand) {
$strand->success = true; $strand->success = true;
$strand->value = $value; $strand->value = $value;
@ -478,7 +482,7 @@ class CoroutineExecutor implements Runtime, ExecutorImplementation
private function completeValueFast(CoroutineContext $ctx, Type $type, $value, array $path, &$returnValue) : bool private function completeValueFast(CoroutineContext $ctx, Type $type, $value, array $path, &$returnValue) : bool
{ {
// special handling of Throwable inherited from JS reference implementation, but makes no sense in this PHP // special handling of Throwable inherited from JS reference implementation, but makes no sense in this PHP
if ($this->promiseAdapter->isThenable($value) || $value instanceof Throwable) { if ($this->isPromise($value) || $value instanceof Throwable) {
return false; return false;
} }
@ -574,7 +578,7 @@ class CoroutineExecutor implements Runtime, ExecutorImplementation
// !!! $value might be promise, yield to resolve // !!! $value might be promise, yield to resolve
try { try {
if ($this->promiseAdapter->isThenable($value)) { if ($this->isPromise($value)) {
$value = yield $value; $value = yield $value;
} }
} catch (Throwable $reason) { } catch (Throwable $reason) {
@ -931,4 +935,14 @@ class CoroutineExecutor implements Runtime, ExecutorImplementation
return $selectedType; return $selectedType;
} }
/**
* @param mixed $value
*
* @return bool
*/
private function isPromise($value)
{
return $value instanceof Promise || $this->promiseAdapter->isThenable($value);
}
} }

View File

@ -42,6 +42,6 @@ class GraphQLTest extends TestCase
$promise = GraphQL::promiseToExecute($promiseAdapter, $schema, '{ sayHi(name: "John") }'); $promise = GraphQL::promiseToExecute($promiseAdapter, $schema, '{ sayHi(name: "John") }');
$result = $promiseAdapter->wait($promise); $result = $promiseAdapter->wait($promise);
$this->assertSame(['data' => ['sayHi' => 'Hi John!']], $result->toArray()); self::assertSame(['data' => ['sayHi' => 'Hi John!']], $result->toArray());
} }
} }