5151function await (PromiseInterface $ promise )
5252{
5353 $ wait = true ;
54- $ resolved = null ;
55- $ exception = null ;
54+ $ resolved = false ;
5655 $ rejected = false ;
56+ $ resolvedValue = null ;
57+ $ rejectedThrowable = null ;
5758
5859 $ promise ->then (
59- function ($ c ) use (&$ resolved , &$ wait ) {
60- $ resolved = $ c ;
60+ function ($ c ) use (&$ resolved , &$ resolvedValue , &$ wait ) {
61+ $ resolvedValue = $ c ;
62+ $ resolved = true ;
6163 $ wait = false ;
6264 Loop::stop ();
6365 },
64- function ($ error ) use (&$ exception , &$ rejected , &$ wait ) {
65- $ exception = $ error ;
66+ function ($ error ) use (&$ rejected , &$ rejectedThrowable , &$ wait ) {
67+ // promise is rejected with an unexpected value (Promise API v1 or v2 only)
68+ if (!$ error instanceof \Exception && !$ error instanceof \Throwable) {
69+ $ error = new \UnexpectedValueException (
70+ 'Promise rejected with unexpected value of type ' . (is_object ($ error ) ? get_class ($ error ) : gettype ($ error ))
71+ );
72+
73+ // avoid garbage references by replacing all closures in call stack.
74+ // what a lovely piece of code!
75+ $ r = new \ReflectionProperty ('Exception ' , 'trace ' );
76+ $ r ->setAccessible (true );
77+ $ trace = $ r ->getValue ($ error );
78+
79+ // Exception trace arguments only available when zend.exception_ignore_args is not set
80+ // @codeCoverageIgnoreStart
81+ foreach ($ trace as $ ti => $ one ) {
82+ if (isset ($ one ['args ' ])) {
83+ foreach ($ one ['args ' ] as $ ai => $ arg ) {
84+ if ($ arg instanceof \Closure) {
85+ $ trace [$ ti ]['args ' ][$ ai ] = 'Object( ' . \get_class ($ arg ) . ') ' ;
86+ }
87+ }
88+ }
89+ }
90+ // @codeCoverageIgnoreEnd
91+ $ r ->setValue ($ error , $ trace );
92+ }
93+
94+ $ rejectedThrowable = $ error ;
6695 $ rejected = true ;
6796 $ wait = false ;
6897 Loop::stop ();
@@ -73,22 +102,23 @@ function ($error) use (&$exception, &$rejected, &$wait) {
73102 // argument does not show up in the stack trace in PHP 7+ only.
74103 $ promise = null ;
75104
105+ if ($ rejected ) {
106+ throw $ rejectedThrowable ;
107+ }
108+
109+ if ($ resolved ) {
110+ return $ resolvedValue ;
111+ }
112+
76113 while ($ wait ) {
77114 Loop::run ();
78115 }
79116
80117 if ($ rejected ) {
81- // promise is rejected with an unexpected value (Promise API v1 or v2 only)
82- if (!$ exception instanceof \Exception && !$ exception instanceof \Throwable) {
83- $ exception = new \UnexpectedValueException (
84- 'Promise rejected with unexpected value of type ' . (is_object ($ exception ) ? get_class ($ exception ) : gettype ($ exception ))
85- );
86- }
87-
88- throw $ exception ;
118+ throw $ rejectedThrowable ;
89119 }
90120
91- return $ resolved ;
121+ return $ resolvedValue ;
92122}
93123
94124/**
0 commit comments