Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a26eb01

Browse files
[VarExporter] Fix lazy-proxying readonly classes on PHP 8.3
1 parent 88399c7 commit a26eb01

20 files changed

+1065
-1045
lines changed

src/Symfony/Component/Cache/Tests/Traits/RedisProxiesTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public function testRedis5Proxy($class)
4242
$return = $method->getReturnType() instanceof \ReflectionNamedType && 'void' === (string) $method->getReturnType() ? '' : 'return ';
4343
$methods[] = "\n ".ProxyHelper::exportSignature($method, false)."\n".<<<EOPHP
4444
{
45-
{$return}\$this->lazyObjectReal->{$method->name}({$args});
45+
{$return}(\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args});
4646
}
4747
4848
EOPHP;
@@ -84,7 +84,7 @@ public function testRedis6Proxy($class, $stub)
8484
$return = $method->getReturnType() instanceof \ReflectionNamedType && 'void' === (string) $method->getReturnType() ? '' : 'return ';
8585
$methods[] = "\n ".ProxyHelper::exportSignature($method, false)."\n".<<<EOPHP
8686
{
87-
{$return}\$this->lazyObjectReal->{$method->name}({$args});
87+
{$return}(\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args});
8888
}
8989
9090
EOPHP;

src/Symfony/Component/Cache/Traits/Redis5Proxy.php

Lines changed: 240 additions & 243 deletions
Large diffs are not rendered by default.

src/Symfony/Component/Cache/Traits/Redis6Proxy.php

Lines changed: 253 additions & 256 deletions
Large diffs are not rendered by default.

src/Symfony/Component/Cache/Traits/RedisCluster5Proxy.php

Lines changed: 191 additions & 194 deletions
Large diffs are not rendered by default.

src/Symfony/Component/Cache/Traits/RedisCluster6Proxy.php

Lines changed: 223 additions & 226 deletions
Large diffs are not rendered by default.

src/Symfony/Component/Cache/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"psr/log": "^1.1|^2|^3",
2727
"symfony/cache-contracts": "^1.1.7|^2|^3",
2828
"symfony/service-contracts": "^1.1|^2|^3",
29-
"symfony/var-exporter": "^6.2"
29+
"symfony/var-exporter": "^6.2.7"
3030
},
3131
"require-dev": {
3232
"cache/integration-tests": "dev-master",

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dedup_lazy.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,7 @@ class stdClassProxy5a8a5eb extends \stdClass implements \Symfony\Component\VarEx
117117
{
118118
use \Symfony\Component\VarExporter\LazyProxyTrait;
119119

120-
private const LAZY_OBJECT_PROPERTY_SCOPES = [
121-
'lazyObjectReal' => [self::class, 'lazyObjectReal', null],
122-
"\0".self::class."\0lazyObjectReal" => [self::class, 'lazyObjectReal', null],
123-
];
120+
private const LAZY_OBJECT_PROPERTY_SCOPES = [];
124121
}
125122

126123
// Help opcache.preload discover always-needed symbols

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_wither_lazy.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,6 @@ class WitherProxy94fa281 extends \Symfony\Component\DependencyInjection\Tests\Co
7676
use \Symfony\Component\VarExporter\LazyProxyTrait;
7777

7878
private const LAZY_OBJECT_PROPERTY_SCOPES = [
79-
'lazyObjectReal' => [self::class, 'lazyObjectReal', null],
80-
"\0".self::class."\0lazyObjectReal" => [self::class, 'lazyObjectReal', null],
8179
'foo' => [parent::class, 'foo', null],
8280
];
8381
}

src/Symfony/Component/DependencyInjection/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"psr/container": "^1.1|^2.0",
2121
"symfony/deprecation-contracts": "^2.1|^3",
2222
"symfony/service-contracts": "^1.1.6|^2.0|^3.0",
23-
"symfony/var-exporter": "^6.2"
23+
"symfony/var-exporter": "^6.2.7"
2424
},
2525
"require-dev": {
2626
"symfony/yaml": "^5.4|^6.0",

src/Symfony/Component/VarDumper/Caster/SymfonyCaster.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,21 @@ public static function castLazyObjectState($state, array $a, Stub $stub, bool $i
7676

7777
$stub->cut += \count($a) - 1;
7878

79-
return ['status' => new ConstStub(match ($a['status']) {
79+
$instance = $a['realInstance'] ?? null;
80+
81+
$a = ['status' => new ConstStub(match ($a['status']) {
8082
LazyObjectState::STATUS_INITIALIZED_FULL => 'INITIALIZED_FULL',
8183
LazyObjectState::STATUS_INITIALIZED_PARTIAL => 'INITIALIZED_PARTIAL',
8284
LazyObjectState::STATUS_UNINITIALIZED_FULL => 'UNINITIALIZED_FULL',
8385
LazyObjectState::STATUS_UNINITIALIZED_PARTIAL => 'UNINITIALIZED_PARTIAL',
8486
}, $a['status'])];
87+
88+
if ($instance) {
89+
$a['realInstance'] = $instance;
90+
--$stub->cut;
91+
}
92+
93+
return $a;
8594
}
8695

8796
public static function castUuid(Uuid $uuid, array $a, Stub $stub, bool $isNested)

src/Symfony/Component/VarExporter/Internal/LazyObjectRegistry.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,7 @@ class LazyObjectRegistry
4545
*/
4646
public static $parentMethods = [];
4747

48-
/**
49-
* @var LazyObjectState
50-
*/
51-
public static $noInitializerState;
48+
public static ?\Closure $noInitializerState = null;
5249

5350
public static function getClassResetters($class)
5451
{

src/Symfony/Component/VarExporter/Internal/LazyObjectState.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class LazyObjectState
3737
*/
3838
public int $status = 0;
3939

40+
public object $realInstance;
41+
4042
public function __construct(public readonly \Closure|array $initializer, $skippedProperties = [])
4143
{
4244
$this->skippedProperties = $skippedProperties;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\VarExporter\Internal;
13+
14+
if (\PHP_VERSION_ID >= 80300) {
15+
/**
16+
* @internal
17+
*/
18+
trait LazyObjectTrait
19+
{
20+
private readonly LazyObjectState $lazyObjectState;
21+
}
22+
} else {
23+
/**
24+
* @internal
25+
*/
26+
trait LazyObjectTrait
27+
{
28+
private LazyObjectState $lazyObjectState;
29+
}
30+
}

src/Symfony/Component/VarExporter/LazyGhostTrait.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@
1414
use Symfony\Component\VarExporter\Internal\Hydrator;
1515
use Symfony\Component\VarExporter\Internal\LazyObjectRegistry as Registry;
1616
use Symfony\Component\VarExporter\Internal\LazyObjectState;
17+
use Symfony\Component\VarExporter\Internal\LazyObjectTrait;
1718

1819
trait LazyGhostTrait
1920
{
20-
private LazyObjectState $lazyObjectState;
21+
use LazyObjectTrait;
2122

2223
/**
2324
* Creates a lazy-loading ghost instance.

src/Symfony/Component/VarExporter/LazyProxyTrait.php

Lines changed: 41 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,17 @@
1515
use Symfony\Component\VarExporter\Internal\Hydrator;
1616
use Symfony\Component\VarExporter\Internal\LazyObjectRegistry as Registry;
1717
use Symfony\Component\VarExporter\Internal\LazyObjectState;
18+
use Symfony\Component\VarExporter\Internal\LazyObjectTrait;
1819

1920
trait LazyProxyTrait
2021
{
21-
private LazyObjectState $lazyObjectState;
22-
private object $lazyObjectReal;
22+
use LazyObjectTrait;
2323

2424
/**
2525
* Creates a lazy-loading virtual proxy.
2626
*
2727
* @param \Closure():object $initializer Returns the proxied object
28-
* @param static|null $instance
28+
* @param static|null $instance
2929
*/
3030
public static function createLazyProxy(\Closure $initializer, object $instance = null): static
3131
{
@@ -52,20 +52,16 @@ public static function createLazyProxy(\Closure $initializer, object $instance =
5252
*/
5353
public function isLazyObjectInitialized(bool $partial = false): bool
5454
{
55-
if (!isset($this->lazyObjectState) || Registry::$noInitializerState === $this->lazyObjectState) {
56-
return true;
57-
}
58-
59-
return \array_key_exists("\0".self::class."\0lazyObjectReal", (array) $this);
55+
return !isset($this->lazyObjectState) || isset($this->lazyObjectState->realInstance) || Registry::$noInitializerState === $this->lazyObjectState->initializer;
6056
}
6157

6258
/**
6359
* Forces initialization of a lazy object and returns it.
6460
*/
6561
public function initializeLazyObject(): parent
6662
{
67-
if (isset($this->lazyObjectReal)) {
68-
return $this->lazyObjectReal;
63+
if ($state = $this->lazyObjectState ?? null) {
64+
return $state->realInstance ??= ($state->initializer)();
6965
}
7066

7167
return $this;
@@ -76,13 +72,11 @@ public function initializeLazyObject(): parent
7672
*/
7773
public function resetLazyObject(): bool
7874
{
79-
if (!isset($this->lazyObjectState) || Registry::$noInitializerState === $this->lazyObjectState) {
75+
if (!isset($this->lazyObjectState) || Registry::$noInitializerState === $this->lazyObjectState->initializer) {
8076
return false;
8177
}
8278

83-
if (\array_key_exists("\0".self::class."\0lazyObjectReal", (array) $this)) {
84-
unset($this->lazyObjectReal);
85-
}
79+
unset($this->lazyObjectState->realInstance);
8680

8781
return true;
8882
}
@@ -98,23 +92,16 @@ public function &__get($name): mixed
9892

9993
if (null === $scope || isset($propertyScopes["\0$scope\0$name"])) {
10094
if ($state = $this->lazyObjectState ?? null) {
101-
if ('lazyObjectReal' === $name && self::class === $scope) {
102-
$this->lazyObjectReal = ($state->initializer)();
103-
104-
return $this->lazyObjectReal;
105-
}
106-
if (isset($this->lazyObjectReal)) {
107-
$instance = $this->lazyObjectReal;
108-
}
95+
$instance = $state->realInstance ??= ($state->initializer)();
10996
}
11097
$parent = 2;
11198
goto get_in_scope;
11299
}
113100
}
114101
$parent = (Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['get'];
115102

116-
if (isset($this->lazyObjectReal)) {
117-
$instance = $this->lazyObjectReal;
103+
if ($state = $this->lazyObjectState ?? null) {
104+
$instance = $state->realInstance ??= ($state->initializer)();
118105
} else {
119106
if (2 === $parent) {
120107
return parent::__get($name);
@@ -174,22 +161,15 @@ public function __set($name, $value): void
174161
$scope = Registry::getScope($propertyScopes, $class, $name, $readonlyScope);
175162

176163
if ($readonlyScope === $scope || isset($propertyScopes["\0$scope\0$name"])) {
177-
if (isset($this->lazyObjectState)) {
178-
if ('lazyObjectReal' === $name && self::class === $scope) {
179-
$this->lazyObjectReal = $value;
180-
181-
return;
182-
}
183-
if (isset($this->lazyObjectReal)) {
184-
$instance = $this->lazyObjectReal;
185-
}
164+
if ($state = $this->lazyObjectState ?? null) {
165+
$instance = $state->realInstance ??= ($state->initializer)();
186166
}
187167
goto set_in_scope;
188168
}
189169
}
190170

191-
if (isset($this->lazyObjectReal)) {
192-
$instance = $this->lazyObjectReal;
171+
if ($state = $this->lazyObjectState ?? null) {
172+
$instance = $state->realInstance ??= ($state->initializer)();
193173
} elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['set']) {
194174
parent::__set($name, $value);
195175

@@ -216,22 +196,15 @@ public function __isset($name): bool
216196
$scope = Registry::getScope($propertyScopes, $class, $name);
217197

218198
if (null === $scope || isset($propertyScopes["\0$scope\0$name"])) {
219-
if (isset($this->lazyObjectState)) {
220-
if ('lazyObjectReal' === $name && self::class === $scope) {
221-
$state = $this->lazyObjectState ?? null;
222-
223-
return null !== $this->lazyObjectReal = $state ? ($state->initializer)() : null;
224-
}
225-
if (isset($this->lazyObjectReal)) {
226-
$instance = $this->lazyObjectReal;
227-
}
199+
if ($state = $this->lazyObjectState ?? null) {
200+
$instance = $state->realInstance ??= ($state->initializer)();
228201
}
229202
goto isset_in_scope;
230203
}
231204
}
232205

233-
if (isset($this->lazyObjectReal)) {
234-
$instance = $this->lazyObjectReal;
206+
if ($state = $this->lazyObjectState ?? null) {
207+
$instance = $state->realInstance ??= ($state->initializer)();
235208
} elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['isset']) {
236209
return parent::__isset($name);
237210
}
@@ -256,22 +229,15 @@ public function __unset($name): void
256229
$scope = Registry::getScope($propertyScopes, $class, $name, $readonlyScope);
257230

258231
if ($readonlyScope === $scope || isset($propertyScopes["\0$scope\0$name"])) {
259-
if (isset($this->lazyObjectState)) {
260-
if ('lazyObjectReal' === $name && self::class === $scope) {
261-
unset($this->lazyObjectReal);
262-
263-
return;
264-
}
265-
if (isset($this->lazyObjectReal)) {
266-
$instance = $this->lazyObjectReal;
267-
}
232+
if ($state = $this->lazyObjectState ?? null) {
233+
$instance = $state->realInstance ??= ($state->initializer)();
268234
}
269235
goto unset_in_scope;
270236
}
271237
}
272238

273-
if (isset($this->lazyObjectReal)) {
274-
$instance = $this->lazyObjectReal;
239+
if ($state = $this->lazyObjectState ?? null) {
240+
$instance = $state->realInstance ??= ($state->initializer)();
275241
} elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['unset']) {
276242
parent::__unset($name);
277243

@@ -298,26 +264,30 @@ public function __clone(): void
298264
return;
299265
}
300266

301-
if (\array_key_exists("\0".self::class."\0lazyObjectReal", (array) $this)) {
302-
$this->lazyObjectReal = clone $this->lazyObjectReal;
303-
}
304-
if ($state = $this->lazyObjectState ?? null) {
305-
$this->lazyObjectState = clone $state;
267+
$this->lazyObjectState = clone $this->lazyObjectState;
268+
269+
if (isset($this->lazyObjectState->realInstance)) {
270+
$this->lazyObjectState->realInstance = clone $this->lazyObjectState->realInstance;
306271
}
307272
}
308273

309274
public function __serialize(): array
310275
{
311276
$class = self::class;
277+
$state = $this->lazyObjectState ?? null;
312278

313-
if (!isset($this->lazyObjectReal) && (Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['serialize']) {
279+
if (!$state && (Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['serialize']) {
314280
$properties = parent::__serialize();
315281
} else {
316282
$properties = (array) $this;
283+
284+
if ($state) {
285+
unset($properties["\0$class\0lazyObjectState"]);
286+
$properties["\0$class\0lazyObjectReal"] = $state->realInstance ??= ($state->initializer)();
287+
}
317288
}
318-
unset($properties["\0$class\0lazyObjectState"]);
319289

320-
if (isset($this->lazyObjectReal) || Registry::$parentMethods[$class]['serialize'] || !Registry::$parentMethods[$class]['sleep']) {
290+
if ($state || Registry::$parentMethods[$class]['serialize'] || !Registry::$parentMethods[$class]['sleep']) {
321291
return $properties;
322292
}
323293

@@ -341,17 +311,18 @@ public function __unserialize(array $data): void
341311
{
342312
$class = self::class;
343313

344-
if (isset($data["\0$class\0lazyObjectReal"])) {
314+
if ($instance = $data["\0$class\0lazyObjectReal"] ?? null) {
315+
unset($data["\0$class\0lazyObjectReal"]);
316+
345317
foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) {
346318
$reset($this, $data);
347319
}
348320

349-
if (1 < \count($data)) {
321+
if ($data) {
350322
PublicHydrator::hydrate($this, $data);
351-
} else {
352-
$this->lazyObjectReal = $data["\0$class\0lazyObjectReal"];
353323
}
354-
$this->lazyObjectState = Registry::$noInitializerState ??= new LazyObjectState(static fn () => throw new \LogicException('Lazy proxy has no initializer.'));
324+
$this->lazyObjectState = new LazyObjectState(Registry::$noInitializerState ??= static fn () => throw new \LogicException('Lazy proxy has no initializer.'));
325+
$this->lazyObjectState->realInstance = $instance;
355326
} elseif ((Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['unserialize']) {
356327
parent::__unserialize($data);
357328
} else {

0 commit comments

Comments
 (0)