Skip to content

Commit 58aa6fc

Browse files
committed
1 parent e12188f commit 58aa6fc

File tree

209 files changed

+13063
-115
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

209 files changed

+13063
-115
lines changed

NEWS

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ PHP NEWS
55
- Core:
66
. Fixed bug GH-15330 (Do not scan generator frames more than once). (Arnaud)
77
. Fixed bug GH-15644 (Asymmetric visibility doesn't work with hooks). (ilutov)
8+
. Implemented lazy objects RFC. (Arnaud)
89

910
- DOM:
1011
. Fixed bug GH-13988 (Storing DOMElement consume 4 times more memory in

UPGRADING

+44
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,20 @@ PHP 8.4 UPGRADE NOTES
164164
. The DSN's credentials, when set, are given priority over their PDO
165165
constructor counterparts, being closer to the documentation states.
166166

167+
- Reflection:
168+
. Added methods ReflectionClass::newLazyGhost(),
169+
ReflectionClass::newLazyProxy(), ReflectionClass::resetAsLazyGhost(),
170+
ReflectionClass::resetAsLazyProxy(),
171+
ReflectionClass::isUninitializedLazyObject(),
172+
ReflectionClass::initializeLazyObject(),
173+
ReflectionClass::markLazyObjectAsInitialized(),
174+
ReflectionClass::getLazyInitializer(),
175+
ReflectionProperty::skipLazyInitialization(),
176+
ReflectionProperty::setRawValueWithoutLazyInitialization() and constants
177+
ReflectionClass::SKIP_*.
178+
If you have a method or constant with the same name, you might encounter
179+
errors if the declaration is incompatible.
180+
167181
- SimpleXML:
168182
. Get methods called, or casting to a string on a SimpleXMLElement will no
169183
longer implicitly reset the iterator data, unless explicitly rewound.
@@ -269,6 +283,8 @@ PHP 8.4 UPGRADE NOTES
269283
See Zend/tests/use_function/ns_end_resets_seen_symbols_1.phpt.
270284
. Implemented asymmetric property visibility.
271285
RFC: https://wiki.php.net/rfc/asymmetric-visibility-v2
286+
. Implemented lazy objects.
287+
RFC: https://wiki.php.net/rfc/lazy-objects
272288

273289
- Curl:
274290
. curl_version() returns an additional feature_list value, which is an
@@ -393,6 +409,20 @@ PHP 8.4 UPGRADE NOTES
393409
. ReflectionConstant was introduced.
394410
. ReflectionClassConstant::isDeprecated() was introduced.
395411
. ReflectionGenerator::isClosed() was introduced.
412+
. Multiple methods and constants related to lazy objects were introduced:
413+
- ReflectionClass::newLazyGhost()
414+
- ReflectionClass::newLazyProxy()
415+
- ReflectionClass::resetAsLazyGhost()
416+
- ReflectionClass::resetAsLazyProxy()
417+
- ReflectionClass::isUninitializedLazyObject()
418+
- ReflectionClass::initializeLazyObject()
419+
- ReflectionClass::markLazyObjectAsInitialized()
420+
- ReflectionClass::getLazyInitializer()
421+
- ReflectionProperty::skipLazyInitialization()
422+
- ReflectionProperty::setRawValueWithoutLazyInitialization()
423+
- ReflectionClass::SKIP_INITIALIZATION_ON_SERIALIZE
424+
- ReflectionClass::SKIP_DESTRUCTOR
425+
RFC: https://wiki.php.net/rfc/lazy-objects
396426

397427
- Standard:
398428
. stream_bucket_make_writeable() and stream_bucket_new() will now return a
@@ -780,6 +810,20 @@ PHP 8.4 UPGRADE NOTES
780810
. Added pg_set_chunked_rows_size to allow to fetch results in chunk of
781811
max N rows.
782812

813+
- Reflection:
814+
. Multiple methods related to lazy objects were introduced:
815+
- ReflectionClass::newLazyGhost()
816+
- ReflectionClass::newLazyProxy()
817+
- ReflectionClass::resetAsLazyGhost()
818+
- ReflectionClass::resetAsLazyProxy()
819+
- ReflectionClass::isUninitializedLazyObject()
820+
- ReflectionClass::initializeLazyObject()
821+
- ReflectionClass::markLazyObjectAsInitialized()
822+
- ReflectionClass::getLazyInitializer()
823+
- ReflectionProperty::skipLazyInitialization()
824+
- ReflectionProperty::setRawValueWithoutLazyInitialization()
825+
RFC: https://wiki.php.net/rfc/lazy-objects
826+
783827
- Sodium:
784828
. Added the sodium_crypto_aead_aegis128l_*() and sodium_crypto_aead_aegis256l_*()
785829
functions to support the AEGIS family of authenticated encryption algorithms,

UPGRADING.INTERNALS

+3
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ PHP 8.4 INTERNALS UPGRADE NOTES
9999
zend_std_get_properties(). Use zend_std_get_properties_ex() or
100100
zend_std_get_properties() instead.
101101

102+
* zend_object.properties must not be accessed directly. Use
103+
zend_std_get_properties_ex() instead.
104+
102105
* Removed IS_STATIC_VAR_UNINITIALIZED constant. Check for IS_NULL in the
103106
static_variables array instead.
104107

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
--TEST--
2+
Lazy objects: clone calls __clone() once
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public $a = 1;
8+
9+
public function __construct() {
10+
}
11+
12+
public function __clone() {
13+
var_dump("clone");
14+
}
15+
}
16+
17+
function test(string $name, object $obj) {
18+
printf("# %s:\n", $name);
19+
20+
$reflector = new ReflectionClass($obj::class);
21+
$clone = clone $obj;
22+
23+
var_dump($reflector->isUninitializedLazyObject($obj));
24+
var_dump($obj);
25+
var_dump($reflector->isUninitializedLazyObject($clone));
26+
var_dump($clone);
27+
}
28+
29+
$reflector = new ReflectionClass(C::class);
30+
31+
$obj = $reflector->newLazyGhost(function ($obj) {
32+
var_dump("initializer");
33+
$obj->__construct();
34+
});
35+
36+
test('Ghost', $obj);
37+
38+
$obj = $reflector->newLazyProxy(function ($obj) {
39+
var_dump("initializer");
40+
return new C();
41+
});
42+
43+
test('Proxy', $obj);
44+
45+
--EXPECTF--
46+
# Ghost:
47+
string(11) "initializer"
48+
string(5) "clone"
49+
bool(false)
50+
object(C)#%d (1) {
51+
["a"]=>
52+
int(1)
53+
}
54+
bool(false)
55+
object(C)#%d (1) {
56+
["a"]=>
57+
int(1)
58+
}
59+
# Proxy:
60+
string(11) "initializer"
61+
string(5) "clone"
62+
bool(false)
63+
lazy proxy object(C)#%d (1) {
64+
["instance"]=>
65+
object(C)#%d (1) {
66+
["a"]=>
67+
int(1)
68+
}
69+
}
70+
bool(false)
71+
lazy proxy object(C)#%d (1) {
72+
["instance"]=>
73+
object(C)#%d (1) {
74+
["a"]=>
75+
int(1)
76+
}
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
Lazy objects: clone is independant of the original object
3+
--FILE--
4+
<?php
5+
6+
class SomeObj {
7+
public string $foo = 'A';
8+
public string $dummy;
9+
}
10+
11+
$reflector = new ReflectionClass(SomeObj::class);
12+
13+
$predefinedObject = new SomeObj();
14+
$initializer = function () use ($predefinedObject) {
15+
return $predefinedObject;
16+
};
17+
18+
$myProxy = $reflector->newLazyProxy($initializer);
19+
$reflector->getProperty('foo')->skipLazyInitialization($myProxy);
20+
21+
$clonedProxy = clone $myProxy;
22+
var_dump($clonedProxy->foo);
23+
24+
$reflector->initializeLazyObject($myProxy);
25+
$myProxy->foo = 'B';
26+
27+
$reflector->initializeLazyObject($clonedProxy);
28+
29+
var_dump($myProxy->foo);
30+
var_dump($clonedProxy->foo);
31+
32+
--EXPECT--
33+
string(1) "A"
34+
string(1) "B"
35+
string(1) "A"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
--TEST--
2+
Lazy objects: clone is independant of the original object
3+
--FILE--
4+
<?php
5+
6+
class SomeObj {
7+
public Value $value;
8+
public function __construct() {
9+
$this->value = new Value();
10+
}
11+
public function __clone() {
12+
$this->value = clone $this->value;
13+
}
14+
}
15+
16+
class Value {
17+
public string $value = 'A';
18+
}
19+
20+
function test(string $name, object $obj) {
21+
printf("# %s:\n", $name);
22+
23+
$reflector = new ReflectionClass(SomeObj::class);
24+
25+
$clonedObj = clone $obj;
26+
var_dump($clonedObj->value->value);
27+
28+
$reflector->initializeLazyObject($obj);
29+
$obj->value->value = 'B';
30+
31+
$reflector->initializeLazyObject($clonedObj);
32+
33+
var_dump($obj->value->value);
34+
var_dump($clonedObj->value->value);
35+
}
36+
37+
$reflector = new ReflectionClass(SomeObj::class);
38+
39+
test('Ghost', $reflector->newLazyGhost(function ($obj) {
40+
$obj->__construct();
41+
}));
42+
43+
test('Proxy', $reflector->newLazyProxy(function () {
44+
return new SomeObj();
45+
}));
46+
47+
?>
48+
--EXPECT--
49+
# Ghost:
50+
string(1) "A"
51+
string(1) "B"
52+
string(1) "A"
53+
# Proxy:
54+
string(1) "A"
55+
string(1) "B"
56+
string(1) "A"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--TEST--
2+
Lazy objects: clone is independant of the original object
3+
--FILE--
4+
<?php
5+
6+
class SomeObj {
7+
public string $foo = 'X';
8+
public string $dummy;
9+
}
10+
11+
function test(string $name, object $obj) {
12+
printf("# %s:\n", $name);
13+
14+
$reflector = new ReflectionClass(SomeObj::class);
15+
16+
$clonedObj = clone $obj;
17+
18+
$reflector->initializeLazyObject($obj);
19+
$reflector->getProperty('foo')->setRawValueWithoutLazyInitialization($clonedObj, 'Y');
20+
21+
$reflector->initializeLazyObject($clonedObj);
22+
23+
var_dump($clonedObj->foo);
24+
}
25+
26+
$reflector = new ReflectionClass(SomeObj::class);
27+
28+
test('Ghost', $reflector->newLazyGhost(function ($obj) {
29+
}));
30+
31+
test('Proxy', $reflector->newLazyProxy(function () {
32+
return new SomeObj();
33+
}));
34+
35+
?>
36+
--EXPECT--
37+
# Ghost:
38+
string(1) "Y"
39+
# Proxy:
40+
string(1) "Y"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
--TEST--
2+
Lazy objects: clone of initialized lazy object does not initialize twice
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public $a = 1;
8+
9+
public function __construct() {
10+
}
11+
}
12+
13+
function test(string $name, object $obj) {
14+
printf("# %s:\n", $name);
15+
16+
$reflector = new ReflectionClass($obj::class);
17+
$reflector->initializeLazyObject($obj);
18+
19+
$clone = clone $obj;
20+
21+
var_dump($reflector->isUninitializedLazyObject($obj));
22+
var_dump($obj);
23+
var_dump($reflector->isUninitializedLazyObject($clone));
24+
var_dump($clone);
25+
}
26+
27+
$reflector = new ReflectionClass(C::class);
28+
29+
$obj = $reflector->newLazyGhost(function ($obj) {
30+
var_dump("initializer");
31+
$obj->__construct();
32+
});
33+
34+
test('Ghost', $obj);
35+
36+
$obj = $reflector->newLazyProxy(function ($obj) {
37+
var_dump("initializer");
38+
return new C();
39+
});
40+
41+
test('Proxy', $obj);
42+
43+
--EXPECTF--
44+
# Ghost:
45+
string(11) "initializer"
46+
bool(false)
47+
object(C)#%d (1) {
48+
["a"]=>
49+
int(1)
50+
}
51+
bool(false)
52+
object(C)#%d (1) {
53+
["a"]=>
54+
int(1)
55+
}
56+
# Proxy:
57+
string(11) "initializer"
58+
bool(false)
59+
lazy proxy object(C)#%d (1) {
60+
["instance"]=>
61+
object(C)#%d (1) {
62+
["a"]=>
63+
int(1)
64+
}
65+
}
66+
bool(false)
67+
lazy proxy object(C)#%d (1) {
68+
["instance"]=>
69+
object(C)#%d (1) {
70+
["a"]=>
71+
int(1)
72+
}
73+
}

0 commit comments

Comments
 (0)