Skip to content

Commit 72087fd

Browse files
committed
Use static internal callbacks without binding to parent promise
1 parent 5e60e55 commit 72087fd

2 files changed

Lines changed: 72 additions & 6 deletions

File tree

src/Promise.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public function done(callable $onFulfilled = null, callable $onRejected = null,
6161
return $this->result->done($onFulfilled, $onRejected, $onProgress);
6262
}
6363

64-
$this->handlers[] = function (ExtendedPromiseInterface $promise) use ($onFulfilled, $onRejected) {
64+
$this->handlers[] = static function (ExtendedPromiseInterface $promise) use ($onFulfilled, $onRejected) {
6565
$promise
6666
->done($onFulfilled, $onRejected);
6767
};
@@ -73,7 +73,7 @@ public function done(callable $onFulfilled = null, callable $onRejected = null,
7373

7474
public function otherwise(callable $onRejected)
7575
{
76-
return $this->then(null, function ($reason) use ($onRejected) {
76+
return $this->then(null, static function ($reason) use ($onRejected) {
7777
if (!_checkTypehint($onRejected, $reason)) {
7878
return new RejectedPromise($reason);
7979
}
@@ -84,11 +84,11 @@ public function otherwise(callable $onRejected)
8484

8585
public function always(callable $onFulfilledOrRejected)
8686
{
87-
return $this->then(function ($value) use ($onFulfilledOrRejected) {
87+
return $this->then(static function ($value) use ($onFulfilledOrRejected) {
8888
return resolve($onFulfilledOrRejected())->then(function () use ($value) {
8989
return $value;
9090
});
91-
}, function ($reason) use ($onFulfilledOrRejected) {
91+
}, static function ($reason) use ($onFulfilledOrRejected) {
9292
return resolve($onFulfilledOrRejected())->then(function () use ($reason) {
9393
return new RejectedPromise($reason);
9494
});
@@ -116,7 +116,7 @@ private function resolver(callable $onFulfilled = null, callable $onRejected = n
116116
{
117117
return function ($resolve, $reject, $notify) use ($onFulfilled, $onRejected, $onProgress) {
118118
if ($onProgress) {
119-
$progressHandler = function ($update) use ($notify, $onProgress) {
119+
$progressHandler = static function ($update) use ($notify, $onProgress) {
120120
try {
121121
$notify($onProgress($update));
122122
} catch (\Throwable $e) {
@@ -129,7 +129,7 @@ private function resolver(callable $onFulfilled = null, callable $onRejected = n
129129
$progressHandler = $notify;
130130
}
131131

132-
$this->handlers[] = function (ExtendedPromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject, $progressHandler) {
132+
$this->handlers[] = static function (ExtendedPromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject, $progressHandler) {
133133
$promise
134134
->then($onFulfilled, $onRejected)
135135
->done($resolve, $reject, $progressHandler);

tests/PromiseTest.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,72 @@ public function shouldIgnoreNotifyAfterReject()
191191
$promise->cancel();
192192
}
193193

194+
195+
/** @test */
196+
public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromise()
197+
{
198+
gc_collect_cycles();
199+
$promise = new Promise(function () { });
200+
unset($promise);
201+
202+
$this->assertSame(0, gc_collect_cycles());
203+
}
204+
205+
/** @test */
206+
public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithThenFollowers()
207+
{
208+
gc_collect_cycles();
209+
$promise = new Promise(function () { });
210+
$promise->then()->then()->then();
211+
unset($promise);
212+
213+
$this->assertSame(0, gc_collect_cycles());
214+
}
215+
216+
/** @test */
217+
public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithDoneFollowers()
218+
{
219+
gc_collect_cycles();
220+
$promise = new Promise(function () { });
221+
$promise->done();
222+
unset($promise);
223+
224+
$this->assertSame(0, gc_collect_cycles());
225+
}
226+
227+
/** @test */
228+
public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithOtherwiseFollowers()
229+
{
230+
gc_collect_cycles();
231+
$promise = new Promise(function () { });
232+
$promise->otherwise(function () { });
233+
unset($promise);
234+
235+
$this->assertSame(0, gc_collect_cycles());
236+
}
237+
238+
/** @test */
239+
public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithAlwaysFollowers()
240+
{
241+
gc_collect_cycles();
242+
$promise = new Promise(function () { });
243+
$promise->always(function () { });
244+
unset($promise);
245+
246+
$this->assertSame(0, gc_collect_cycles());
247+
}
248+
249+
/** @test */
250+
public function shouldNotLeaveGarbageCyclesWhenRemovingLastReferenceToPendingPromiseWithProgressFollowers()
251+
{
252+
gc_collect_cycles();
253+
$promise = new Promise(function () { });
254+
$promise->then(null, null, function () { });
255+
unset($promise);
256+
257+
$this->assertSame(0, gc_collect_cycles());
258+
}
259+
194260
/** @test */
195261
public function shouldFulfillIfFullfilledWithSimplePromise()
196262
{

0 commit comments

Comments
 (0)