@@ -18,9 +18,6 @@ final class DeferredGenerator implements \Iterator
1818{
1919 private bool $ started = false ;
2020 private bool $ finished = false ;
21- private mixed $ key = null ;
22- private mixed $ value = null ;
23- private mixed $ result = null ;
2421 private \Generator $ generator ;
2522
2623 /** @var array<\Closure(\Throwable): mixed> */
@@ -50,7 +47,6 @@ public static function fromGenerator(\Generator $generator): self
5047 $ self = new self ();
5148 $ self ->generator = $ generator ;
5249 $ self ->started = true ;
53- $ self ->fill ();
5450 return $ self ;
5551 }
5652
@@ -67,7 +63,6 @@ public function throw(\Throwable $exception): void
6763 );
6864 try {
6965 $ this ->generator ->throw ($ exception );
70- $ this ->fill ();
7166 } catch (\Throwable $ e ) {
7267 $ this ->handleException ($ e );
7368 }
@@ -80,15 +75,12 @@ public function throw(\Throwable $exception): void
8075 */
8176 public function send (mixed $ value ): mixed
8277 {
83- $ this ->started or throw new \ LogicException ( ' Cannot send value to a generator that was not started. ' );
78+ $ this ->start ( );
8479 $ this ->finished and throw new \LogicException ('Cannot send value to a generator that was already finished. ' );
8580 try {
86- $ result = $ this ->generator ->send ($ value );
87- $ this ->fill ();
88- return $ result ;
81+ return $ this ->generator ->send ($ value );
8982 } catch (\Throwable $ e ) {
9083 $ this ->handleException ($ e );
91- return null ;
9284 }
9385 }
9486
@@ -97,8 +89,12 @@ public function send(mixed $value): mixed
9789 */
9890 public function getReturn (): mixed
9991 {
100- $ this ->finished or throw new \LogicException ('Cannot get return value of a generator that was not finished. ' );
101- return $ this ->result ;
92+ // $this->start();
93+ try {
94+ return $ this ->generator ->getReturn ();
95+ } catch (\Throwable $ e ) {
96+ $ this ->handleException ($ e );
97+ }
10298 }
10399
104100 /**
@@ -107,7 +103,11 @@ public function getReturn(): mixed
107103 public function current (): mixed
108104 {
109105 $ this ->start ();
110- return $ this ->value ;
106+ try {
107+ return $ this ->generator ->current ();
108+ } catch (\Throwable $ e ) {
109+ $ this ->handleException ($ e );
110+ }
111111 }
112112
113113 /**
@@ -116,7 +116,11 @@ public function current(): mixed
116116 public function key (): mixed
117117 {
118118 $ this ->start ();
119- return $ this ->key ;
119+ try {
120+ return $ this ->generator ->key ();
121+ } catch (\Throwable $ e ) {
122+ $ this ->handleException ($ e );
123+ }
120124 }
121125
122126 /**
@@ -131,7 +135,6 @@ public function next(): void
131135
132136 try {
133137 $ this ->generator ->next ();
134- $ this ->fill ();
135138 } catch (\Throwable $ e ) {
136139 $ this ->handleException ($ e );
137140 }
@@ -145,12 +148,16 @@ public function next(): void
145148 public function valid (): bool
146149 {
147150 $ this ->start ();
148- return !$ this ->finished ;
151+ try {
152+ return $ this ->generator ->valid ();
153+ } catch (\Throwable $ e ) {
154+ $ this ->handleException ($ e );
155+ }
149156 }
150157
151158 public function rewind (): void
152159 {
153- $ this ->started and throw new \ LogicException ( ' Cannot rewind a generator that was already run. ' );
160+ $ this ->generator -> rewind ( );
154161 }
155162
156163 /**
@@ -164,6 +171,20 @@ public function catch(callable $handler): self
164171 return $ this ;
165172 }
166173
174+ private static function getDummyGenerator (): \Generator
175+ {
176+ static $ generator ;
177+
178+ if ($ generator === null ) {
179+ $ generator = (static function (): \Generator {
180+ yield ;
181+ })();
182+ $ generator ->current ();
183+ }
184+
185+ return $ generator ;
186+ }
187+
167188 private function start (): void
168189 {
169190 if ($ this ->started ) {
@@ -176,33 +197,36 @@ private function start(): void
176197
177198 if ($ result instanceof \Generator) {
178199 $ this ->generator = $ result ;
179- $ this ->fill ();
180200 return ;
181201 }
182202
183- $ this ->result = $ result ;
203+ /** @psalm-suppress all */
204+ $ this ->generator = (static function (mixed $ result ): \Generator {
205+ return $ result ;
206+ yield ;
207+ })($ result );
184208 $ this ->finished = true ;
185209 } catch (\Throwable $ e ) {
210+ $ this ->generator = self ::getDummyGenerator ();
186211 $ this ->handleException ($ e );
187212 } finally {
188213 unset($ this ->handler , $ this ->values );
189214 }
190215 }
191216
192- private function fill ( ): void
217+ private function handleException ( \ Throwable $ e ): never
193218 {
194- $ this ->key = $ this ->generator ->key ();
195- $ this ->value = $ this ->generator ->current ();
196- $ this ->finished = !$ this ->generator ->valid () and $ this ->result = $ this ->generator ->getReturn ();
197- }
198-
199- private function handleException (\Throwable $ e ): void
200- {
201- $ this ->key = null ;
202- $ this ->value = null ;
219+ $ this ->finished and throw $ e ;
203220 $ this ->finished = true ;
204221 foreach ($ this ->catchers as $ catch ) {
205- $ catch ($ e );
222+ try {
223+ $ catch ($ e );
224+ } catch (\Throwable ) {
225+ // Do nothing.
226+ }
206227 }
228+
229+ $ this ->catchers = [];
230+ throw $ e ;
207231 }
208232}
0 commit comments