Skip to content

Commit 17572d7

Browse files
authored
Fix leaking PHP iterator (#966)
1 parent 6ca86cd commit 17572d7

File tree

1 file changed

+10
-13
lines changed

1 file changed

+10
-13
lines changed

src/Persistence/Array_/Action.php

+10-13
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ class Action
1717
/** @var \Iterator */
1818
public $generator;
1919

20+
/** @var \Closure[] hack for GC for PHP 8.1.3 or older */
21+
private $_filterFxs = [];
22+
2023
public function __construct(array $data)
2124
{
2225
$this->generator = new \ArrayIterator($data);
@@ -30,18 +33,19 @@ public function __construct(array $data)
3033
public function filter(Model\Scope\AbstractScope $condition)
3134
{
3235
if (!$condition->isEmpty()) {
33-
// CallbackFilterIterator with circular reference (bound function) is not GCed in PHP 7.4, see
36+
// CallbackFilterIterator with circular reference (bound function) is not GCed
3437
// https://github.com/php/php-src/commit/afab9eb48c883766b7870f76f2e2b0a4bd575786
35-
// remove the if below once PHP 7.4 is no longer supported
36-
$filterFx = function ($row) use ($condition) {
38+
// https://github.com/php/php-src/commit/fb70460d8e7593e32abdaaf8ae8849345d49c8fd
39+
// remove the if below once PHP 8.1.3 (or older) is no longer supported
40+
$filterFx = function (array $row) use ($condition): bool {
3741
return $this->match($row, $condition);
3842
};
39-
if (\PHP_MAJOR_VERSION === 7 && \PHP_MINOR_VERSION === 4) {
43+
if (\PHP_VERSION_ID < 80104 && count($this->_filterFxs) !== \PHP_INT_MAX) {
44+
$this->_filterFxs[] = $filterFx; // prevent filter function to be GCed
4045
$filterFxWeakRef = \WeakReference::create($filterFx);
4146
$this->generator = new \CallbackFilterIterator($this->generator, static function (array $row) use ($filterFxWeakRef) {
4247
return $filterFxWeakRef->get()($row);
4348
});
44-
$this->generator->filterFx = $filterFx; // @phpstan-ignore-line prevent filter function to be GCed
4549
} else {
4650
$this->generator = new \CallbackFilterIterator($this->generator, $filterFx);
4751
}
@@ -253,14 +257,7 @@ public function order(array $fields)
253257
*/
254258
public function limit(?int $limit, int $offset = 0)
255259
{
256-
// LimitIterator with circular reference is not GCed in PHP 7.4 - ???, see
257-
// https://github.com/php/php-src/issues/7958
258-
if (\PHP_MAJOR_VERSION < 20) { // TODO update condition once fixed in php-src
259-
$data = array_slice($this->getRows(), $offset, $limit, true);
260-
$this->generator = new \ArrayIterator($data);
261-
} else {
262-
$this->generator = new \LimitIterator($this->generator, $offset, $limit ?? -1);
263-
}
260+
$this->generator = new \LimitIterator($this->generator, $offset, $limit ?? -1);
264261

265262
return $this;
266263
}

0 commit comments

Comments
 (0)