@@ -143,4 +143,99 @@ public function testCoroutineWillCancelAllPendingPromisesWhenFunctionContinuesTo
143143
144144 $ promise ->then (null , $ this ->expectCallableOnceWith (new \RuntimeException ('Second operation cancelled ' , 42 )));
145145 }
146+
147+ public function testCoroutineShouldNotCreateAnyGarbageReferencesWhenGeneratorReturns ()
148+ {
149+ if (class_exists ('React\Promise\When ' )) {
150+ $ this ->markTestSkipped ('Not supported on legacy Promise v1 API ' );
151+ }
152+
153+ gc_collect_cycles ();
154+ gc_collect_cycles ();
155+
156+ $ promise = coroutine (function () {
157+ if (false ) {
158+ yield ;
159+ }
160+ return 42 ;
161+ });
162+
163+ unset($ promise );
164+
165+ $ this ->assertEquals (0 , gc_collect_cycles ());
166+ }
167+
168+ public function testCoroutineShouldNotCreateAnyGarbageReferencesForPromiseRejectedWithExceptionImmediately ()
169+ {
170+ if (class_exists ('React\Promise\When ' )) {
171+ $ this ->markTestSkipped ('Not supported on legacy Promise v1 API ' );
172+ }
173+
174+ gc_collect_cycles ();
175+
176+ $ promise = coroutine (function () {
177+ yield new Promise (function () {
178+ throw new \RuntimeException ('Failed ' , 42 );
179+ });
180+ });
181+
182+ unset($ promise );
183+
184+ $ this ->assertEquals (0 , gc_collect_cycles ());
185+ }
186+
187+ public function testCoroutineShouldNotCreateAnyGarbageReferencesForPromiseRejectedWithExceptionOnCancellation ()
188+ {
189+ if (class_exists ('React\Promise\When ' )) {
190+ $ this ->markTestSkipped ('Not supported on legacy Promise v1 API ' );
191+ }
192+
193+ gc_collect_cycles ();
194+
195+ $ promise = coroutine (function () {
196+ yield new Promise (function () { }, function () {
197+ throw new \RuntimeException ('Operation cancelled ' , 42 );
198+ });
199+ });
200+
201+ $ promise ->cancel ();
202+ unset($ promise );
203+
204+ $ this ->assertEquals (0 , gc_collect_cycles ());
205+ }
206+
207+ public function testCoroutineShouldNotCreateAnyGarbageReferencesWhenGeneratorThrowsBeforeFirstYield ()
208+ {
209+ if (class_exists ('React\Promise\When ' )) {
210+ $ this ->markTestSkipped ('Not supported on legacy Promise v1 API ' );
211+ }
212+
213+ gc_collect_cycles ();
214+
215+ $ promise = coroutine (function () {
216+ throw new \RuntimeException ('Failed ' , 42 );
217+ yield ;
218+ });
219+
220+ unset($ promise );
221+
222+ $ this ->assertEquals (0 , gc_collect_cycles ());
223+ }
224+
225+ public function testCoroutineShouldNotCreateAnyGarbageReferencesWhenGeneratorYieldsInvalidValue ()
226+ {
227+ if (class_exists ('React\Promise\When ' )) {
228+ $ this ->markTestSkipped ('Not supported on legacy Promise v1 API ' );
229+ }
230+
231+ gc_collect_cycles ();
232+
233+ $ promise = coroutine (function () {
234+ yield 42 ;
235+ });
236+
237+ unset($ promise );
238+
239+ $ this ->assertEquals (0 , gc_collect_cycles ());
240+ }
146241}
0 commit comments