3333use GraphQL \Type \Introspection ;
3434use GraphQL \Type \Schema ;
3535use GraphQL \Utils \AST ;
36+ use GraphQL \Utils \TypeInfo ;
3637use GraphQL \Utils \Utils ;
3738use SplQueue ;
3839use stdClass ;
3940use Throwable ;
4041use function is_array ;
4142use function is_string ;
43+ use function json_decode ;
44+ use function json_encode ;
4245use function sprintf ;
4346
4447class CoroutineExecutor implements Runtime, ExecutorImplementation
@@ -73,10 +76,10 @@ class CoroutineExecutor implements Runtime, ExecutorImplementation
7376 /** @var string|null */
7477 private $ operationName ;
7578
76- /** @var Collector */
79+ /** @var Collector|null */
7780 private $ collector ;
7881
79- /** @var Error[] */
82+ /** @var array< Error> */
8083 private $ errors ;
8184
8285 /** @var SplQueue */
@@ -85,10 +88,10 @@ class CoroutineExecutor implements Runtime, ExecutorImplementation
8588 /** @var SplQueue */
8689 private $ schedule ;
8790
88- /** @var stdClass */
91+ /** @var stdClass|null */
8992 private $ rootResult ;
9093
91- /** @var int */
94+ /** @var int|null */
9295 private $ pending ;
9396
9497 /** @var callable */
@@ -108,6 +111,9 @@ public function __construct(
108111 self ::$ undefined = Utils::undefined ();
109112 }
110113
114+ $ this ->errors = [];
115+ $ this ->queue = new SplQueue ();
116+ $ this ->schedule = new SplQueue ();
111117 $ this ->schema = $ schema ;
112118 $ this ->fieldResolver = $ fieldResolver ;
113119 $ this ->promiseAdapter = $ promiseAdapter ;
@@ -143,10 +149,11 @@ public static function create(
143149 private static function resultToArray ($ value , $ emptyObjectAsStdClass = true )
144150 {
145151 if ($ value instanceof stdClass) {
146- $ array = [] ;
147- foreach ($ value as $ propertyName => $ propertyValue ) {
152+ $ array = ( array ) $ value ;
153+ foreach ($ array as $ propertyName => $ propertyValue ) {
148154 $ array [$ propertyName ] = self ::resultToArray ($ propertyValue );
149155 }
156+
150157 if ($ emptyObjectAsStdClass && empty ($ array )) {
151158 return new stdClass ();
152159 }
@@ -237,9 +244,9 @@ public function doExecute() : Promise
237244 private function finishExecute ($ value , array $ errors ) : ExecutionResult
238245 {
239246 $ this ->rootResult = null ;
240- $ this ->errors = null ;
241- $ this ->queue = null ;
242- $ this ->schedule = null ;
247+ $ this ->errors = [] ;
248+ $ this ->queue = new SplQueue () ;
249+ $ this ->schedule = new SplQueue () ;
243250 $ this ->pending = null ;
244251 $ this ->collector = null ;
245252 $ this ->variableValues = null ;
@@ -825,11 +832,16 @@ private function completeValue(CoroutineContext $ctx, Type $type, $value, array
825832 } else {
826833 $ childContexts = [];
827834
835+ $ fields = [];
836+ if ($ this ->collector !== null ) {
837+ $ fields = $ this ->collector ->collectFields (
838+ $ objectType ,
839+ $ ctx ->shared ->mergedSelectionSet ?? $ this ->mergeSelectionSets ($ ctx )
840+ );
841+ }
842+
828843 /** @var CoroutineContextShared $childShared */
829- foreach ($ this ->collector ->collectFields (
830- $ objectType ,
831- $ ctx ->shared ->mergedSelectionSet ?? $ this ->mergeSelectionSets ($ ctx )
832- ) as $ childShared ) {
844+ foreach ($ fields as $ childShared ) {
833845 $ childPath = $ path ;
834846 $ childPath [] = $ childShared ->resultName ; // !!! uses array COW semantics
835847 $ childCtx = new CoroutineContext (
@@ -938,7 +950,7 @@ private function resolveTypeSlow(CoroutineContext $ctx, $value, AbstractType $ab
938950 $ selectedType = null ;
939951 foreach ($ possibleTypes as $ type ) {
940952 $ typeCheck = yield $ type ->isTypeOf ($ value , $ this ->contextValue , $ ctx ->resolveInfo );
941- if ($ selectedType !== null || $ typeCheck !== true ) {
953+ if ($ selectedType !== null || ! $ typeCheck ) {
942954 continue ;
943955 }
944956
0 commit comments