Skip to content

Commit 8b596a2

Browse files
committed
Merge branch 'PHP-8.5'
* PHP-8.5: Resolve the effective property in ReflectionProperty lazy APIs master takes the property info and scope directly in reflection_property_get_effective_prop() and reflection_property_check_lazy_compatible(), so both call sites are adapted to those signatures here.
2 parents 415a415 + dc87517 commit 8b596a2

3 files changed

Lines changed: 103 additions & 13 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
--TEST--
2+
Lazy Objects: ReflectionProperty::isLazy() with a hooked override
3+
--FILE--
4+
<?php
5+
6+
class B {
7+
public $plain = 1;
8+
public $virtual { get => 1; }
9+
private $priv = 1;
10+
public static $stat;
11+
}
12+
13+
class C extends B {
14+
public $plain { get => $this->plain; set => $this->plain = $value; }
15+
public $priv = 2;
16+
}
17+
18+
$reflector = new ReflectionClass(C::class);
19+
20+
foreach (['Ghost', 'Proxy'] as $kind) {
21+
printf("# %s:\n", $kind);
22+
23+
$obj = $kind === 'Ghost'
24+
? $reflector->newLazyGhost(function ($obj) { })
25+
: $reflector->newLazyProxy(function ($obj) { return new C(); });
26+
27+
foreach (['plain', 'virtual', 'stat'] as $name) {
28+
printf("%s: B scope %d, C scope %d\n", $name,
29+
(new ReflectionProperty(B::class, $name))->isLazy($obj),
30+
(new ReflectionProperty(C::class, $name))->isLazy($obj));
31+
}
32+
33+
printf("priv: B scope %d\n",
34+
(new ReflectionProperty(B::class, 'priv'))->isLazy($obj));
35+
}
36+
37+
?>
38+
--EXPECT--
39+
# Ghost:
40+
plain: B scope 1, C scope 1
41+
virtual: B scope 0, C scope 0
42+
stat: B scope 0, C scope 0
43+
priv: B scope 1
44+
# Proxy:
45+
plain: B scope 1, C scope 1
46+
virtual: B scope 0, C scope 0
47+
stat: B scope 0, C scope 0
48+
priv: B scope 1
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Lazy Objects: ReflectionProperty::skipLazyInitialization() with a hooked override
3+
--FILE--
4+
<?php
5+
6+
class B {
7+
public $b = 1;
8+
}
9+
10+
class C extends B {
11+
public $b { get => $this->b; set => $this->b = $value; }
12+
}
13+
14+
$reflector = new ReflectionClass(C::class);
15+
16+
foreach (['Ghost', 'Proxy'] as $kind) {
17+
printf("# %s:\n", $kind);
18+
19+
$obj = $kind === 'Ghost'
20+
? $reflector->newLazyGhost(function ($obj) { $obj->b = 9; })
21+
: $reflector->newLazyProxy(function ($obj) { $c = new C(); $c->b = 9; return $c; });
22+
23+
(new ReflectionProperty(B::class, 'b'))->skipLazyInitialization($obj);
24+
25+
printf("is lazy: %d\n", $reflector->isUninitializedLazyObject($obj));
26+
var_dump($obj->b);
27+
}
28+
29+
?>
30+
--EXPECT--
31+
# Ghost:
32+
is lazy: 0
33+
NULL
34+
# Proxy:
35+
is lazy: 0
36+
NULL

ext/reflection/php_reflection.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6150,19 +6150,22 @@ ZEND_METHOD(ReflectionProperty, skipLazyInitialization)
61506150
Z_PARAM_OBJ_OF_CLASS(object, intern->ce)
61516151
} ZEND_PARSE_PARAMETERS_END();
61526152

6153-
if (reflection_property_check_lazy_compatible(ref->prop,
6154-
ref->unmangled_name, intern->ce, object,
6155-
"skipLazyInitialization") == FAILURE) {
6156-
RETURN_THROWS();
6157-
}
6158-
61596153
while (zend_object_is_lazy_proxy(object)
61606154
&& zend_lazy_object_initialized(object)) {
61616155
object = zend_lazy_object_get_instance(object);
61626156
}
61636157

6164-
const zval *src = &object->ce->default_properties_table[OBJ_PROP_TO_NUM(ref->prop->offset)];
6165-
zval *dst = OBJ_PROP(object, ref->prop->offset);
6158+
const zend_property_info *prop = reflection_property_get_effective_prop(ref->prop,
6159+
ref->unmangled_name, intern->ce, object);
6160+
6161+
if (reflection_property_check_lazy_compatible(prop,
6162+
ref->unmangled_name, intern->ce, object,
6163+
"skipLazyInitialization") == FAILURE) {
6164+
RETURN_THROWS();
6165+
}
6166+
6167+
const zval *src = &object->ce->default_properties_table[OBJ_PROP_TO_NUM(prop->offset)];
6168+
zval *dst = OBJ_PROP(object, prop->offset);
61666169

61676170
if (!(Z_PROP_FLAG_P(dst) & IS_PROP_LAZY)) {
61686171
/* skipLazyInitialization has no effect on non-lazy properties */
@@ -6194,16 +6197,19 @@ ZEND_METHOD(ReflectionProperty, isLazy)
61946197
Z_PARAM_OBJ_OF_CLASS(object, intern->ce)
61956198
} ZEND_PARSE_PARAMETERS_END();
61966199

6197-
if (!ref->prop || ref->prop->flags & (ZEND_ACC_STATIC | ZEND_ACC_VIRTUAL)) {
6198-
RETURN_FALSE;
6199-
}
6200-
62016200
while (zend_object_is_lazy_proxy(object)
62026201
&& zend_lazy_object_initialized(object)) {
62036202
object = zend_lazy_object_get_instance(object);
62046203
}
62056204

6206-
RETURN_BOOL(Z_PROP_FLAG_P(OBJ_PROP(object, ref->prop->offset)) & IS_PROP_LAZY);
6205+
const zend_property_info *prop = reflection_property_get_effective_prop(ref->prop,
6206+
ref->unmangled_name, intern->ce, object);
6207+
6208+
if (!prop || prop->flags & (ZEND_ACC_STATIC | ZEND_ACC_VIRTUAL)) {
6209+
RETURN_FALSE;
6210+
}
6211+
6212+
RETURN_BOOL(Z_PROP_FLAG_P(OBJ_PROP(object, prop->offset)) & IS_PROP_LAZY);
62076213
}
62086214

62096215
/* {{{ Returns true if property was initialized */

0 commit comments

Comments
 (0)