Skip to content

Commit 9852544

Browse files
[VarExporter] Leverage native lazy objects
1 parent 6c0058a commit 9852544

21 files changed

+908
-245
lines changed

.github/expected-missing-return-types.diff

+5-5
Original file line numberDiff line numberDiff line change
@@ -593,17 +593,17 @@ diff --git a/src/Symfony/Component/VarDumper/Dumper/DataDumperInterface.php b/sr
593593
- public function dump(Data $data);
594594
+ public function dump(Data $data): ?string;
595595
}
596-
diff --git a/src/Symfony/Component/VarExporter/Tests/ProxyHelperTest.php b/src/Symfony/Component/VarExporter/Tests/ProxyHelperTest.php
597-
--- a/src/Symfony/Component/VarExporter/Tests/ProxyHelperTest.php
598-
+++ b/src/Symfony/Component/VarExporter/Tests/ProxyHelperTest.php
599-
@@ -172,5 +172,5 @@ class ProxyHelperTest extends TestCase
596+
diff --git a/src/Symfony/Component/VarExporter/Tests/LegacyProxyHelperTest.php b/src/Symfony/Component/VarExporter/Tests/LegacyProxyHelperTest.php
597+
--- a/src/Symfony/Component/VarExporter/Tests/LegacyProxyHelperTest.php
598+
+++ b/src/Symfony/Component/VarExporter/Tests/LegacyProxyHelperTest.php
599+
@@ -134,5 +134,5 @@ class LegacyProxyHelperTest extends ProxyHelperTest
600600
{
601601
yield 'not type hinted __unserialize method' => [new class {
602602
- public function __unserialize($array)
603603
+ public function __unserialize($array): void
604604
{
605605
}
606-
@@ -192,5 +192,5 @@ class ProxyHelperTest extends TestCase
606+
@@ -154,5 +154,5 @@ class LegacyProxyHelperTest extends ProxyHelperTest
607607

608608
yield 'type hinted __unserialize method' => [new class {
609609
- public function __unserialize(array $array)

UPGRADE-7.3.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ Read more about this in the [Symfony documentation](https://symfony.com/doc/7.3/
88

99
If you're upgrading from a version below 7.2, follow the [7.2 upgrade guide](UPGRADE-7.2.md) first.
1010

11+
AssetMapper
12+
-----------
13+
14+
* `ImportMapRequireCommand` now takes `projectDir` as a required third constructor argument
15+
1116
Ldap
1217
----
1318

@@ -192,7 +197,8 @@ VarDumper
192197
* Deprecate `ResourceCaster::castCurl()`, `ResourceCaster::castGd()` and `ResourceCaster::castOpensslX509()`
193198
* Mark all casters as `@internal`
194199

195-
AssetMapper
200+
VarExporter
196201
-----------
197202

198-
* `ImportMapRequireCommand` now takes `projectDir` as a required third constructor argument
203+
* Deprecate `LazyGhostTrait` and `LazyProxyTrait`, use native lazy objects instead
204+
* Deprecate `ProxyHelper::generateLazyGhost()`, use native lazy objects instead

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

+3-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
use Symfony\Component\Cache\Traits\RedisProxyTrait;
1818
use Symfony\Component\Cache\Traits\RelayClusterProxy;
1919
use Symfony\Component\Cache\Traits\RelayProxy;
20-
use Symfony\Component\VarExporter\LazyProxyTrait;
2120
use Symfony\Component\VarExporter\ProxyHelper;
2221

2322
class RedisProxiesTest extends TestCase
@@ -37,7 +36,7 @@ public function testRedisProxy($class)
3736
$methods = [];
3837

3938
foreach ((new \ReflectionClass(\sprintf('Symfony\Component\Cache\Traits\\%s%dProxy', $class, $version)))->getMethods() as $method) {
40-
if ('reset' === $method->name || method_exists(LazyProxyTrait::class, $method->name)) {
39+
if ('reset' === $method->name || method_exists(RedisProxyTrait::class, $method->name)) {
4140
continue;
4241
}
4342
$return = '__construct' === $method->name || $method->getReturnType() instanceof \ReflectionNamedType && 'void' === (string) $method->getReturnType() ? '' : 'return ';
@@ -89,7 +88,7 @@ public function testRelayProxy()
8988
$expectedMethods = [];
9089

9190
foreach ((new \ReflectionClass(RelayProxy::class))->getMethods() as $method) {
92-
if ('reset' === $method->name || method_exists(LazyProxyTrait::class, $method->name) || $method->isStatic()) {
91+
if ('reset' === $method->name || method_exists(RedisProxyTrait::class, $method->name) || $method->isStatic()) {
9392
continue;
9493
}
9594

@@ -136,7 +135,7 @@ public function testRelayClusterProxy()
136135
$expectedMethods = [];
137136

138137
foreach ((new \ReflectionClass(RelayClusterProxy::class))->getMethods() as $method) {
139-
if ('reset' === $method->name || method_exists(LazyProxyTrait::class, $method->name) || $method->isStatic()) {
138+
if ('reset' === $method->name || method_exists(RedisProxyTrait::class, $method->name) || $method->isStatic()) {
140139
continue;
141140
}
142141

src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

+5-1
Original file line numberDiff line numberDiff line change
@@ -2036,7 +2036,11 @@ public function testLazyAutowireAttributeWithIntersection()
20362036

20372037
$dumper = new PhpDumper($container);
20382038

2039-
$this->assertStringEqualsFile(self::$fixturesPath.'/php/lazy_autowire_attribute_with_intersection.php', $dumper->dump());
2039+
if (\PHP_VERSION_ID >= 80400) {
2040+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/lazy_autowire_attribute_with_intersection.php', $dumper->dump());
2041+
} else {
2042+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/legacy_lazy_autowire_attribute_with_intersection.php', $dumper->dump());
2043+
}
20402044
}
20412045

20422046
public function testCallableAdapterConsumer()

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

+4-6
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,15 @@ protected static function get_Lazy_Foo_QFdMZVKService($container, $lazyLoad = tr
7474

7575
class objectProxy1fd6daa implements \Symfony\Component\DependencyInjection\Tests\Compiler\AInterface, \Symfony\Component\DependencyInjection\Tests\Compiler\IInterface, \Symfony\Component\VarExporter\LazyObjectInterface
7676
{
77-
use \Symfony\Component\VarExporter\LazyProxyTrait;
77+
use \Symfony\Component\VarExporter\Internal\LazyDecoratorTrait {
78+
doCreateLazyProxy as public createLazyProxy;
79+
}
7880

7981
private const LAZY_OBJECT_PROPERTY_SCOPES = [];
8082

8183
public function initializeLazyObject(): \Symfony\Component\DependencyInjection\Tests\Compiler\AInterface&\Symfony\Component\DependencyInjection\Tests\Compiler\IInterface
8284
{
83-
if ($state = $this->lazyObjectState ?? null) {
84-
return $state->realInstance ??= ($state->initializer)();
85-
}
86-
87-
return $this;
85+
return $this->lazyObjectState->realInstance;
8886
}
8987
}
9088

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
4+
use Symfony\Component\DependencyInjection\ContainerInterface;
5+
use Symfony\Component\DependencyInjection\Container;
6+
use Symfony\Component\DependencyInjection\Exception\LogicException;
7+
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
8+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
9+
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
10+
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
11+
12+
/**
13+
* @internal This class has been auto-generated by the Symfony Dependency Injection Component.
14+
*/
15+
class ProjectServiceContainer extends Container
16+
{
17+
protected $parameters = [];
18+
19+
public function __construct()
20+
{
21+
$this->services = $this->privates = [];
22+
$this->methodMap = [
23+
'foo' => 'getFooService',
24+
];
25+
26+
$this->aliases = [];
27+
}
28+
29+
public function compile(): void
30+
{
31+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
32+
}
33+
34+
public function isCompiled(): bool
35+
{
36+
return true;
37+
}
38+
39+
protected function createProxy($class, \Closure $factory)
40+
{
41+
return $factory();
42+
}
43+
44+
/**
45+
* Gets the public 'foo' shared autowired service.
46+
*
47+
* @return \Symfony\Component\DependencyInjection\Tests\Compiler\AAndIInterfaceConsumer
48+
*/
49+
protected static function getFooService($container)
50+
{
51+
$a = ($container->privates['.lazy.foo.qFdMZVK'] ?? self::get_Lazy_Foo_QFdMZVKService($container));
52+
53+
if (isset($container->services['foo'])) {
54+
return $container->services['foo'];
55+
}
56+
57+
return $container->services['foo'] = new \Symfony\Component\DependencyInjection\Tests\Compiler\AAndIInterfaceConsumer($a);
58+
}
59+
60+
/**
61+
* Gets the private '.lazy.foo.qFdMZVK' shared service.
62+
*
63+
* @return \object
64+
*/
65+
protected static function get_Lazy_Foo_QFdMZVKService($container, $lazyLoad = true)
66+
{
67+
if (true === $lazyLoad) {
68+
return $container->privates['.lazy.foo.qFdMZVK'] = $container->createProxy('objectProxy1fd6daa', static fn () => \objectProxy1fd6daa::createLazyProxy(static fn () => self::get_Lazy_Foo_QFdMZVKService($container, false)));
69+
}
70+
71+
return ($container->services['foo'] ?? self::getFooService($container));
72+
}
73+
}
74+
75+
class objectProxy1fd6daa implements \Symfony\Component\DependencyInjection\Tests\Compiler\AInterface, \Symfony\Component\DependencyInjection\Tests\Compiler\IInterface, \Symfony\Component\VarExporter\LazyObjectInterface
76+
{
77+
use \Symfony\Component\VarExporter\LazyProxyTrait;
78+
79+
private const LAZY_OBJECT_PROPERTY_SCOPES = [];
80+
81+
public function initializeLazyObject(): \Symfony\Component\DependencyInjection\Tests\Compiler\AInterface&\Symfony\Component\DependencyInjection\Tests\Compiler\IInterface
82+
{
83+
if ($state = $this->lazyObjectState ?? null) {
84+
return $state->realInstance ??= ($state->initializer)();
85+
}
86+
87+
return $this;
88+
}
89+
}
90+
91+
// Help opcache.preload discover always-needed symbols
92+
class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class);
93+
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
94+
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class);

src/Symfony/Component/HttpKernel/DependencyInjection/ServicesResetter.php

+4
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ public function reset(): void
4646
continue;
4747
}
4848

49+
if (\PHP_VERSION_ID >= 80400 && (new \ReflectionClass($service))->isUninitializedLazyObject($service)) {
50+
continue;
51+
}
52+
4953
foreach ((array) $this->resetMethods[$id] as $resetMethod) {
5054
if ('?' === $resetMethod[0] && !method_exists($service, $resetMethod = substr($resetMethod, 1))) {
5155
continue;

src/Symfony/Component/JsonStreamer/CacheWarmer/LazyGhostCacheWarmer.php

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
*
2323
* @author Mathias Arlaud <mathias.arlaud@gmail.com>
2424
*
25+
* @deprecated since Symfony 7.3, native lazy objects will be used instead
26+
*
2527
* @internal
2628
*/
2729
final class LazyGhostCacheWarmer extends CacheWarmer

src/Symfony/Component/JsonStreamer/Tests/CacheWarmer/LazyGhostCacheWarmerTest.php

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
use Symfony\Component\JsonStreamer\CacheWarmer\LazyGhostCacheWarmer;
1616
use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\ClassicDummy;
1717

18+
/**
19+
* @group legacy
20+
*/
1821
class LazyGhostCacheWarmerTest extends TestCase
1922
{
2023
private string $lazyGhostsDir;

src/Symfony/Component/VarExporter/CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Leverage native lazy objects in `ProxyHelper::generateLazyProxy()` on PHP 8.4+
8+
* Deprecate `LazyGhostTrait` and `LazyProxyTrait`, use native lazy objects instead
9+
* Deprecate `ProxyHelper::generateLazyGhost()`, use native lazy objects instead
10+
411
7.2
512
---
613

0 commit comments

Comments
 (0)