File tree Expand file tree Collapse file tree 4 files changed +67
-11
lines changed Expand file tree Collapse file tree 4 files changed +67
-11
lines changed Original file line number Diff line number Diff line change @@ -17,7 +17,7 @@ interface FiberInterface
1717{
1818 public function resume (mixed $ value ): void ;
1919
20- public function throw (mixed $ throwable ): void ;
20+ public function throw (\ Throwable $ throwable ): void ;
2121
2222 public function suspend (): mixed ;
2323}
Original file line number Diff line number Diff line change @@ -27,14 +27,8 @@ public function resume(mixed $value): void
2727 Loop::futureTick (fn () => $ this ->fiber ->resume ($ value ));
2828 }
2929
30- public function throw (mixed $ throwable ): void
30+ public function throw (\ Throwable $ throwable ): void
3131 {
32- if (!$ throwable instanceof \Throwable) {
33- $ throwable = new \UnexpectedValueException (
34- 'Promise rejected with unexpected value of type ' . (is_object ($ throwable ) ? get_class ($ throwable ) : gettype ($ throwable ))
35- );
36- }
37-
3832 if ($ this ->fiber === null ) {
3933 Loop::futureTick (static fn () => \Fiber::suspend (static fn () => throw $ throwable ));
4034 return ;
Original file line number Diff line number Diff line change @@ -77,17 +77,49 @@ function async(callable $function): callable
7777 */
7878function await (PromiseInterface $ promise ): mixed
7979{
80- $ fiber = FiberFactory::create ();
80+ $ fiber = null ;
81+ $ resolved = false ;
82+ $ rejected = false ;
83+ $ resolvedValue = null ;
84+ $ rejectedThrowable = null ;
8185
8286 $ promise ->then (
83- function (mixed $ value ) use (&$ resolved , $ fiber ): void {
87+ function (mixed $ value ) use (&$ resolved , &$ resolvedValue , &$ fiber ): void {
88+ if ($ fiber === null ) {
89+ $ resolved = true ;
90+ $ resolvedValue = $ value ;
91+ return ;
92+ }
93+
8494 $ fiber ->resume ($ value );
8595 },
86- function (mixed $ throwable ) use (&$ resolved , $ fiber ): void {
96+ function (mixed $ throwable ) use (&$ rejected , &$ rejectedThrowable , &$ fiber ): void {
97+ if (!$ throwable instanceof \Throwable) {
98+ $ throwable = new \UnexpectedValueException (
99+ 'Promise rejected with unexpected value of type ' . (is_object ($ throwable ) ? get_class ($ throwable ) : gettype ($ throwable ))
100+ );
101+ }
102+
103+ if ($ fiber === null ) {
104+ $ rejected = true ;
105+ $ rejectedThrowable = $ throwable ;
106+ return ;
107+ }
108+
87109 $ fiber ->throw ($ throwable );
88110 }
89111 );
90112
113+ if ($ resolved ) {
114+ return $ resolvedValue ;
115+ }
116+
117+ if ($ rejected ) {
118+ throw $ rejectedThrowable ;
119+ }
120+
121+ $ fiber = FiberFactory::create ();
122+
91123 return $ fiber ->suspend ();
92124}
93125
Original file line number Diff line number Diff line change @@ -157,6 +157,36 @@ public function testAwaitShouldNotCreateAnyGarbageReferencesForPromiseRejectedWi
157157 $ this ->assertEquals (0 , gc_collect_cycles ());
158158 }
159159
160+ /**
161+ * @dataProvider provideAwaiters
162+ */
163+ public function testAlreadyFulfilledPromiseShouldNotSuspendFiber (callable $ await )
164+ {
165+ for ($ i = 0 ; $ i < 6 ; $ i ++) {
166+ $ this ->assertSame ($ i , $ await (React \Promise \resolve ($ i )));
167+ }
168+ }
169+
170+ /**
171+ * @dataProvider provideAwaiters
172+ */
173+ public function testNestedAwaits (callable $ await )
174+ {
175+ $ this ->assertTrue ($ await (new Promise (function ($ resolve ) use ($ await ) {
176+ $ resolve ($ await (new Promise (function ($ resolve ) use ($ await ) {
177+ $ resolve ($ await (new Promise (function ($ resolve ) use ($ await ) {
178+ $ resolve ($ await (new Promise (function ($ resolve ) use ($ await ) {
179+ $ resolve ($ await (new Promise (function ($ resolve ) use ($ await ) {
180+ Loop::addTimer (0.01 , function () use ($ resolve ) {
181+ $ resolve (true );
182+ });
183+ })));
184+ })));
185+ })));
186+ })));
187+ })));
188+ }
189+
160190 public function provideAwaiters (): iterable
161191 {
162192 yield 'await ' => [static fn (React \Promise \PromiseInterface $ promise ): mixed => React \Async \await ($ promise )];
You can’t perform that action at this time.
0 commit comments