From: Nikita Popov Date: Mon, 8 Jul 2019 13:50:21 +0000 (+0200) Subject: Add ReflectionReference::getRefcount() X-Git-Tag: php-7.4.0alpha3~7 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=428cfdd1810b17f0064b7691276f0eb92dc963b6;p=php Add ReflectionReference::getRefcount() And don't return null for rc=1 references. Leave it to the user to decide whether or not they want to consider these as references or not. Fixes bug #78263. --- diff --git a/NEWS b/NEWS index 5b8968475e..e87cd934c5 100644 --- a/NEWS +++ b/NEWS @@ -33,6 +33,10 @@ PHP NEWS . Fixed #78192 (SegFault when reuse statement after schema has changed). (Vincent Quatrevieux) +- Reflection: + . Fixed bug #78263 (\ReflectionReference::fromArrayElement() returns null + while item is a reference). (Nikita) + - Standard: . Implemented FR #78177 (Make proc_open accept command array). (Nikita) . Fixed #78208 (password_needs_rehash() with an unknown algo should always diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index ecdec41e03..6aa4d4a24d 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -6190,7 +6190,7 @@ ZEND_METHOD(reflection_reference, fromArrayElement) } /* Treat singleton reference as non-reference. */ - if (Z_TYPE_P(item) != IS_REFERENCE || Z_REFCOUNT_P(item) == 1) { + if (Z_TYPE_P(item) != IS_REFERENCE) { RETURN_NULL(); } @@ -6238,6 +6238,30 @@ ZEND_METHOD(reflection_reference, getId) } /* }}} */ +/* {{{ proto public int ReflectionReference::getRefcount() + * Returns reference count of the held reference. + * ReflectionReference itself increases the refcount, as such: + * * Refcount 1 indicates that the reference is only held by this ReflectionReference. + * * Refcount 2 indicates that it is a singleton reference (often not treated as a reference). + * * Refcount 3 or higher is an ordinary shared reference. */ +ZEND_METHOD(reflection_reference, getRefcount) +{ + reflection_object *intern; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + intern = Z_REFLECTION_P(getThis()); + if (Z_TYPE(intern->obj) != IS_REFERENCE) { + _DO_THROW("Corrupted ReflectionReference object"); + return; + } + + RETURN_LONG(Z_REFCOUNT(intern->obj)); +} +/* }}} */ + /* {{{ method tables */ static const zend_function_entry reflection_exception_functions[] = { PHP_FE_END @@ -6727,6 +6751,7 @@ ZEND_END_ARG_INFO() static const zend_function_entry reflection_reference_functions[] = { ZEND_ME(reflection_reference, fromArrayElement, arginfo_reflection_reference_fromArrayElement, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_ME(reflection_reference, getId, arginfo_reflection__void, ZEND_ACC_PUBLIC) + ZEND_ME(reflection_reference, getRefcount, arginfo_reflection__void, ZEND_ACC_PUBLIC) /* Always throwing dummy methods */ ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE) diff --git a/ext/reflection/tests/ReflectionReference.phpt b/ext/reflection/tests/ReflectionReference.phpt index 2963c30232..ff933063be 100644 --- a/ext/reflection/tests/ReflectionReference.phpt +++ b/ext/reflection/tests/ReflectionReference.phpt @@ -13,12 +13,20 @@ echo "fromArrayElement():\n"; $r0 = ReflectionReference::fromArrayElement($ary, 0); var_dump($r0 === null); $r1 = ReflectionReference::fromArrayElement($ary, 1); -var_dump($r1 === null); +var_dump($r1 instanceof ReflectionReference); $r2 = ReflectionReference::fromArrayElement($ary, 2); var_dump($r2 instanceof ReflectionReference); $r3 = ReflectionReference::fromArrayElement($ary, 3); var_dump($r2 instanceof ReflectionReference); +echo "getRefcount():\n"; +var_dump($r1->getRefcount()); +var_dump($r2->getRefcount()); +var_dump($r3->getRefcount()); + +unset($ary[1]); +var_dump($r1->getRefcount()); + echo "getId() #1:\n"; var_dump($r2->getId() === $r2->getId()); var_dump($r3->getId() === $r3->getId()); @@ -47,6 +55,11 @@ bool(true) bool(true) bool(true) bool(true) +getRefcount(): +int(2) +int(3) +int(3) +int(1) getId() #1: bool(true) bool(true)