mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Add ReflectionProperty::isLazy()
Closes GH-16342
This commit is contained in:
1
NEWS
1
NEWS
@@ -8,6 +8,7 @@ PHP NEWS
|
||||
. Fixed bug GH-16577 (EG(strtod_state).freelist leaks with opcache.preload).
|
||||
(nielsdos)
|
||||
. Fixed bug GH-16615 (Assertion failure in zend_std_read_property). (Arnaud)
|
||||
. Fixed bug GH-16342 (Added ReflectionProperty::isLazy()). (Arnaud)
|
||||
|
||||
- DOM:
|
||||
. Fixed bug GH-16594 (Assertion failure in DOM -> before). (nielsdos)
|
||||
|
||||
140
Zend/tests/lazy_objects/isLazy.phpt
Normal file
140
Zend/tests/lazy_objects/isLazy.phpt
Normal file
@@ -0,0 +1,140 @@
|
||||
--TEST--
|
||||
Lazy Objects: ReflectionProperty::isLazy()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
#[AllowDynamicProperties]
|
||||
class C {
|
||||
public static $staticProp;
|
||||
public int $typed;
|
||||
public $untyped;
|
||||
public $virtual {
|
||||
get {}
|
||||
}
|
||||
}
|
||||
|
||||
function testProps(ReflectionClass $reflector, object $obj) {
|
||||
foreach (['staticProp', 'typed', 'untyped', 'virtual', 'dynamic'] as $name) {
|
||||
if ('dynamic' === $name) {
|
||||
$tmp = new C();
|
||||
$tmp->dynamic = 1;
|
||||
$pr = new ReflectionProperty($tmp, $name);
|
||||
} else {
|
||||
$pr = $reflector->getProperty($name);
|
||||
}
|
||||
printf("%s: %d\n", $name, $pr->isLazy($obj));
|
||||
}
|
||||
}
|
||||
|
||||
$reflector = new ReflectionClass(C::class);
|
||||
|
||||
print "# Ghost\n";
|
||||
|
||||
$obj = $reflector->newLazyGhost(function () { });
|
||||
|
||||
testProps($reflector, $obj);
|
||||
|
||||
$pr = $reflector->getProperty('typed');
|
||||
$pr->skipLazyInitialization($obj);
|
||||
printf("typed (skipped): %d\n", $pr->isLazy($obj));
|
||||
|
||||
print "# Initialized Ghost\n";
|
||||
|
||||
$reflector->initializeLazyObject($obj);
|
||||
|
||||
testProps($reflector, $obj);
|
||||
|
||||
print "# Proxy\n";
|
||||
|
||||
$obj = $reflector->newLazyProxy(function () {
|
||||
return new C();
|
||||
});
|
||||
|
||||
testProps($reflector, $obj);
|
||||
|
||||
$pr = $reflector->getProperty('typed');
|
||||
$pr->skipLazyInitialization($obj);
|
||||
printf("typed (skipped prop): %d\n", $pr->isLazy($obj));
|
||||
|
||||
print "# Initialized Proxy\n";
|
||||
|
||||
$reflector->initializeLazyObject($obj);
|
||||
|
||||
testProps($reflector, $obj);
|
||||
|
||||
print "# Nested Proxy\n";
|
||||
|
||||
$nested = new C();
|
||||
$obj = $reflector->newLazyProxy(function () use ($nested) {
|
||||
return $nested;
|
||||
});
|
||||
$reflector->initializeLazyObject($obj);
|
||||
$reflector->resetAsLazyProxy($nested, function () {
|
||||
return new C();
|
||||
});
|
||||
|
||||
testProps($reflector, $obj);
|
||||
|
||||
print "# Nested Proxy (nested initialized)\n";
|
||||
|
||||
$nested = new C();
|
||||
$obj = $reflector->newLazyProxy(function () use ($nested) {
|
||||
return $nested;
|
||||
});
|
||||
$reflector->initializeLazyObject($obj);
|
||||
$reflector->resetAsLazyProxy($nested, function () {
|
||||
return new C();
|
||||
});
|
||||
$reflector->initializeLazyObject($nested);
|
||||
|
||||
testProps($reflector, $obj);
|
||||
|
||||
print "# Internal\n";
|
||||
|
||||
$obj = (new DateTime())->diff(new DateTime());
|
||||
$reflector = new ReflectionClass(DateInterval::class);
|
||||
$pr = new ReflectionProperty($obj, 'y');
|
||||
printf("y: %d\n", $pr->isLazy($obj));
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
# Ghost
|
||||
staticProp: 0
|
||||
typed: 1
|
||||
untyped: 1
|
||||
virtual: 0
|
||||
dynamic: 0
|
||||
typed (skipped): 0
|
||||
# Initialized Ghost
|
||||
staticProp: 0
|
||||
typed: 0
|
||||
untyped: 0
|
||||
virtual: 0
|
||||
dynamic: 0
|
||||
# Proxy
|
||||
staticProp: 0
|
||||
typed: 1
|
||||
untyped: 1
|
||||
virtual: 0
|
||||
dynamic: 0
|
||||
typed (skipped prop): 0
|
||||
# Initialized Proxy
|
||||
staticProp: 0
|
||||
typed: 0
|
||||
untyped: 0
|
||||
virtual: 0
|
||||
dynamic: 0
|
||||
# Nested Proxy
|
||||
staticProp: 0
|
||||
typed: 1
|
||||
untyped: 1
|
||||
virtual: 0
|
||||
dynamic: 0
|
||||
# Nested Proxy (nested initialized)
|
||||
staticProp: 0
|
||||
typed: 0
|
||||
untyped: 0
|
||||
virtual: 0
|
||||
dynamic: 0
|
||||
# Internal
|
||||
y: 0
|
||||
@@ -6271,6 +6271,30 @@ ZEND_METHOD(ReflectionProperty, skipLazyInitialization)
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_METHOD(ReflectionProperty, isLazy)
|
||||
{
|
||||
reflection_object *intern;
|
||||
property_reference *ref;
|
||||
zend_object *object;
|
||||
|
||||
GET_REFLECTION_OBJECT_PTR(ref);
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, 1) {
|
||||
Z_PARAM_OBJ_OF_CLASS(object, intern->ce)
|
||||
} ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
if (!ref->prop || ref->prop->flags & (ZEND_ACC_STATIC | ZEND_ACC_VIRTUAL)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
while (zend_object_is_lazy_proxy(object)
|
||||
&& zend_lazy_object_initialized(object)) {
|
||||
object = zend_lazy_object_get_instance(object);
|
||||
}
|
||||
|
||||
RETURN_BOOL(Z_PROP_FLAG_P(OBJ_PROP(object, ref->prop->offset)) & IS_PROP_LAZY);
|
||||
}
|
||||
|
||||
/* {{{ Returns true if property was initialized */
|
||||
ZEND_METHOD(ReflectionProperty, isInitialized)
|
||||
{
|
||||
|
||||
@@ -502,6 +502,8 @@ class ReflectionProperty implements Reflector
|
||||
|
||||
public function skipLazyInitialization(object $object): void {}
|
||||
|
||||
public function isLazy(object $object): bool {}
|
||||
|
||||
/** @tentative-return-type */
|
||||
public function isInitialized(?object $object = null): bool {}
|
||||
|
||||
|
||||
6
ext/reflection/php_reflection_arginfo.h
generated
6
ext/reflection/php_reflection_arginfo.h
generated
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 273777e0bc50a3d5059bb2db7b0a1e293b26e338 */
|
||||
* Stub hash: 2620fb2d8fc950283bfc174372c72361b37e9d41 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0)
|
||||
@@ -399,6 +399,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionProperty_skipLaz
|
||||
ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_ReflectionProperty_isLazy arginfo_class_ReflectionClass_isUninitializedLazyObject
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionProperty_isInitialized, 0, 0, _IS_BOOL, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, object, IS_OBJECT, 1, "null")
|
||||
ZEND_END_ARG_INFO()
|
||||
@@ -843,6 +845,7 @@ ZEND_METHOD(ReflectionProperty, getRawValue);
|
||||
ZEND_METHOD(ReflectionProperty, setRawValue);
|
||||
ZEND_METHOD(ReflectionProperty, setRawValueWithoutLazyInitialization);
|
||||
ZEND_METHOD(ReflectionProperty, skipLazyInitialization);
|
||||
ZEND_METHOD(ReflectionProperty, isLazy);
|
||||
ZEND_METHOD(ReflectionProperty, isInitialized);
|
||||
ZEND_METHOD(ReflectionProperty, isPublic);
|
||||
ZEND_METHOD(ReflectionProperty, isPrivate);
|
||||
@@ -1140,6 +1143,7 @@ static const zend_function_entry class_ReflectionProperty_methods[] = {
|
||||
ZEND_ME(ReflectionProperty, setRawValue, arginfo_class_ReflectionProperty_setRawValue, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionProperty, setRawValueWithoutLazyInitialization, arginfo_class_ReflectionProperty_setRawValueWithoutLazyInitialization, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionProperty, skipLazyInitialization, arginfo_class_ReflectionProperty_skipLazyInitialization, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionProperty, isLazy, arginfo_class_ReflectionProperty_isLazy, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionProperty, isInitialized, arginfo_class_ReflectionProperty_isInitialized, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionProperty, isPublic, arginfo_class_ReflectionProperty_isPublic, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionProperty, isPrivate, arginfo_class_ReflectionProperty_isPrivate, ZEND_ACC_PUBLIC)
|
||||
|
||||
Reference in New Issue
Block a user