]> granicus.if.org Git - php/commitdiff
Add ReflectionReference::getRefcount()
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 8 Jul 2019 13:50:21 +0000 (15:50 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 8 Jul 2019 14:54:03 +0000 (16:54 +0200)
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.

NEWS
ext/reflection/php_reflection.c
ext/reflection/tests/ReflectionReference.phpt

diff --git a/NEWS b/NEWS
index 5b8968475efb93523ee64e4c01d3fefefcd89972..e87cd934c541d0c4eec1a063ce9c1fbddb32c798 100644 (file)
--- 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
index ecdec41e036348722fec1452bf47810d366372eb..6aa4d4a24d385bc19cc5a2b3036fc95d8787bb7d 100644 (file)
@@ -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)
index 2963c3023284d5edf7b3b08d8de810fb4577b069..ff933063befaeaa16cf69ee1adf025c90e7c1d4e 100644 (file)
@@ -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)