diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fc837b..e89faf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,24 @@ ## Unreleased - Add schema validation: Input Objects must not contain non-nullable circular references (#492) +#### v0.13.5 +- Fix coroutine executor when using with promise (#486) + +#### v0.13.4 +- Force int when setting max query depth (#477) + +#### v0.13.3 +- Reverted minor possible breaking change (#476) + +#### v0.13.2 +- Added QueryPlan support (#436) +- Fixed an issue with NodeList iteration over missing keys (#475) + +#### v0.13.1 +- Better validation of field/directive arguments +- Support for apollo client/server persisted queries +- Minor tweaks and fixes + ## v0.13.0 This release brings several breaking changes. Please refer to [UPGRADE](UPGRADE.md) document for details. diff --git a/docs/index.md b/docs/index.md index 92a354e..a031a42 100644 --- a/docs/index.md +++ b/docs/index.md @@ -44,8 +44,8 @@ existing PHP frameworks, add support for Relay, etc. ## Current Status The first version of this library (v0.1) was released on August 10th 2015. -The current version (v0.10) supports all features described by GraphQL specification -(including April 2016 add-ons) as well as some experimental features like +The current version supports all features described by GraphQL specification +as well as some experimental features like [Schema Language parser](type-system/type-language.md) and [Schema printer](reference.md#graphqlutilsschemaprinter). diff --git a/src/Experimental/Executor/CoroutineExecutor.php b/src/Experimental/Executor/CoroutineExecutor.php index d985633..91091b4 100644 --- a/src/Experimental/Executor/CoroutineExecutor.php +++ b/src/Experimental/Executor/CoroutineExecutor.php @@ -293,13 +293,17 @@ class CoroutineExecutor implements Runtime, ExecutorImplementation $strand->stack[$strand->depth++] = $strand->current; $strand->current = $value; goto START; - } elseif ($this->promiseAdapter->isThenable($value)) { + } elseif ($this->isPromise($value)) { // !!! increment pending before calling ->then() as it may invoke the callback right away ++$this->pending; + if (! $value instanceof Promise) { + $value = $this->promiseAdapter->convertThenable($value); + } + $this->promiseAdapter - ->convertThenable($value) ->then( + $value, function ($value) use ($strand) { $strand->success = true; $strand->value = $value; @@ -478,7 +482,7 @@ class CoroutineExecutor implements Runtime, ExecutorImplementation 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 - if ($this->promiseAdapter->isThenable($value) || $value instanceof Throwable) { + if ($this->isPromise($value) || $value instanceof Throwable) { return false; } @@ -574,7 +578,7 @@ class CoroutineExecutor implements Runtime, ExecutorImplementation // !!! $value might be promise, yield to resolve try { - if ($this->promiseAdapter->isThenable($value)) { + if ($this->isPromise($value)) { $value = yield $value; } } catch (Throwable $reason) { @@ -931,4 +935,14 @@ class CoroutineExecutor implements Runtime, ExecutorImplementation return $selectedType; } + + /** + * @param mixed $value + * + * @return bool + */ + private function isPromise($value) + { + return $value instanceof Promise || $this->promiseAdapter->isThenable($value); + } } diff --git a/src/Validator/Rules/QueryDepth.php b/src/Validator/Rules/QueryDepth.php index c2fe7b0..cb01dd2 100644 --- a/src/Validator/Rules/QueryDepth.php +++ b/src/Validator/Rules/QueryDepth.php @@ -99,11 +99,11 @@ class QueryDepth extends QuerySecurityRule /** * Set max query depth. If equal to 0 no check is done. Must be greater or equal to 0. */ - public function setMaxQueryDepth(int $maxQueryDepth) + public function setMaxQueryDepth($maxQueryDepth) { $this->checkIfGreaterOrEqualToZero('maxQueryDepth', $maxQueryDepth); - $this->maxQueryDepth = $maxQueryDepth; + $this->maxQueryDepth = (int) $maxQueryDepth; } public static function maxQueryDepthErrorMessage($max, $count) diff --git a/tests/GraphQLTest.php b/tests/GraphQLTest.php new file mode 100644 index 0000000..13193b5 --- /dev/null +++ b/tests/GraphQLTest.php @@ -0,0 +1,47 @@ + new ObjectType( + [ + 'name' => 'Query', + 'fields' => [ + 'sayHi' => [ + 'type' => Type::nonNull(Type::string()), + 'args' => [ + 'name' => [ + 'type' => Type::nonNull(Type::string()), + ], + ], + 'resolve' => static function ($value, $args) use ($promiseAdapter) { + return $promiseAdapter->createFulfilled(sprintf('Hi %s!', $args['name'])); + }, + ], + ], + ] + ), + ] + ); + + $promise = GraphQL::promiseToExecute($promiseAdapter, $schema, '{ sayHi(name: "John") }'); + $result = $promiseAdapter->wait($promise); + self::assertSame(['data' => ['sayHi' => 'Hi John!']], $result->toArray()); + } +}