@@ -11,7 +11,6 @@ class Promise implements ExtendedPromiseInterface, CancellablePromiseInterface
1111 private $ progressHandlers = [];
1212
1313 private $ requiredCancelRequests = 0 ;
14- private $ cancelRequests = 0 ;
1514
1615 public function __construct (callable $ resolver , callable $ canceller = null )
1716 {
@@ -32,11 +31,11 @@ public function then(callable $onFulfilled = null, callable $onRejected = null,
3231 $ this ->requiredCancelRequests ++;
3332
3433 return new static ($ this ->resolver ($ onFulfilled , $ onRejected , $ onProgress ), function () {
35- if (++$ this ->cancelRequests < $ this ->requiredCancelRequests ) {
36- return ;
37- }
34+ $ this ->requiredCancelRequests --;
3835
39- $ this ->cancel ();
36+ if ($ this ->requiredCancelRequests <= 0 ) {
37+ $ this ->cancel ();
38+ }
4039 });
4140 }
4241
@@ -87,14 +86,37 @@ public function progress(callable $onProgress)
8786
8887 public function cancel ()
8988 {
90- if (null === $ this ->canceller || null !== $ this ->result ) {
91- return ;
92- }
93-
9489 $ canceller = $ this ->canceller ;
9590 $ this ->canceller = null ;
9691
97- $ this ->call ($ canceller );
92+ $ parentCanceller = null ;
93+
94+ if (null !== $ this ->result ) {
95+ // Go up the promise chain and reach the top most promise which is
96+ // itself not following another promise
97+ $ root = $ this ->unwrap ($ this ->result );
98+
99+ // Return if the root promise is already resolved or a
100+ // FulfilledPromise or RejectedPromise
101+ if (!$ root instanceof self || null !== $ root ->result ) {
102+ return ;
103+ }
104+
105+ $ root ->requiredCancelRequests --;
106+
107+ if ($ root ->requiredCancelRequests <= 0 ) {
108+ $ parentCanceller = [$ root , 'cancel ' ];
109+ }
110+ }
111+
112+ if (null !== $ canceller ) {
113+ $ this ->call ($ canceller );
114+ }
115+
116+ // For BC, we call the parent canceller after our own canceller
117+ if ($ parentCanceller ) {
118+ $ parentCanceller ();
119+ }
98120 }
99121
100122 private function resolver (callable $ onFulfilled = null , callable $ onRejected = null , callable $ onProgress = null )
@@ -157,6 +179,16 @@ private function settle(ExtendedPromiseInterface $promise)
157179 {
158180 $ promise = $ this ->unwrap ($ promise );
159181
182+ if ($ promise === $ this ) {
183+ $ promise = new RejectedPromise (
184+ new \LogicException ('Cannot resolve a promise with itself. ' )
185+ );
186+ }
187+
188+ if ($ promise instanceof self) {
189+ $ promise ->requiredCancelRequests ++;
190+ }
191+
160192 $ handlers = $ this ->handlers ;
161193
162194 $ this ->progressHandlers = $ this ->handlers = [];
@@ -184,12 +216,6 @@ private function extract($promise)
184216 $ promise = $ promise ->promise ();
185217 }
186218
187- if ($ promise === $ this ) {
188- return new RejectedPromise (
189- new \LogicException ('Cannot resolve a promise with itself. ' )
190- );
191- }
192-
193219 return $ promise ;
194220 }
195221
0 commit comments