5353function await (PromiseInterface $ promise )
5454{
5555 $ wait = true ;
56- $ resolved = null ;
57- $ exception = null ;
56+ $ resolved = false ;
5857 $ rejected = false ;
58+ $ resolvedValue = null ;
59+ $ rejectedThrowable = null ;
5960
6061 $ promise ->then (
61- function ($ c ) use (&$ resolved , &$ wait ) {
62- $ resolved = $ c ;
62+ function ($ c ) use (&$ resolved , &$ resolvedValue , &$ wait ) {
63+ $ resolvedValue = $ c ;
64+ $ resolved = true ;
6365 $ wait = false ;
6466 Loop::stop ();
6567 },
66- function ($ error ) use (&$ exception , &$ rejected , &$ wait ) {
67- $ exception = $ error ;
68+ function ($ error ) use (&$ rejected , &$ rejectedThrowable , &$ wait ) {
69+ // promise is rejected with an unexpected value (Promise API v1 or v2 only)
70+ if (!$ error instanceof \Exception && !$ error instanceof \Throwable) {
71+ $ error = new \UnexpectedValueException (
72+ 'Promise rejected with unexpected value of type ' . (is_object ($ error ) ? get_class ($ error ) : gettype ($ error ))
73+ );
74+
75+ // avoid garbage references by replacing all closures in call stack.
76+ // what a lovely piece of code!
77+ $ r = new \ReflectionProperty ('Exception ' , 'trace ' );
78+ $ trace = $ r ->getValue ($ error );
79+
80+ // Exception trace arguments only available when zend.exception_ignore_args is not set
81+ // @codeCoverageIgnoreStart
82+ foreach ($ trace as $ ti => $ one ) {
83+ if (isset ($ one ['args ' ])) {
84+ foreach ($ one ['args ' ] as $ ai => $ arg ) {
85+ if ($ arg instanceof \Closure) {
86+ $ trace [$ ti ]['args ' ][$ ai ] = 'Object( ' . \get_class ($ arg ) . ') ' ;
87+ }
88+ }
89+ }
90+ }
91+ // @codeCoverageIgnoreEnd
92+ $ r ->setValue ($ error , $ trace );
93+ }
94+
95+ $ rejectedThrowable = $ error ;
6896 $ rejected = true ;
6997 $ wait = false ;
7098 Loop::stop ();
@@ -75,25 +103,25 @@ function ($error) use (&$exception, &$rejected, &$wait) {
75103 // argument does not show up in the stack trace in PHP 7+ only.
76104 $ promise = null ;
77105
106+ if ($ rejected ) {
107+ throw $ rejectedThrowable ;
108+ }
109+
110+ if ($ resolved ) {
111+ return $ resolvedValue ;
112+ }
113+
78114 while ($ wait ) {
79115 Loop::run ();
80116 }
81117
82118 if ($ rejected ) {
83- // promise is rejected with an unexpected value (Promise API v1 or v2 only)
84- if (!$ exception instanceof \Throwable) {
85- $ exception = new \UnexpectedValueException (
86- 'Promise rejected with unexpected value of type ' . (is_object ($ exception ) ? get_class ($ exception ) : gettype ($ exception ))
87- );
88- }
89-
90- throw $ exception ;
119+ throw $ rejectedThrowable ;
91120 }
92121
93- return $ resolved ;
122+ return $ resolvedValue ;
94123}
95124
96-
97125/**
98126 * Execute a Generator-based coroutine to "await" promises.
99127 *
0 commit comments