Skip to content

Instantly share code, notes, and snippets.

@dstogov
Created February 18, 2019 12:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dstogov/db4d092eff324167c36394bdc26ac5b9 to your computer and use it in GitHub Desktop.
Save dstogov/db4d092eff324167c36394bdc26ac5b9 to your computer and use it in GitHub Desktop.
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index a80838666b..dfb04ab732 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -263,6 +263,9 @@ typedef struct _zend_oparray_context {
/* Whether all property types are resolved to CEs | | | */
#define ZEND_ACC_PROPERTY_TYPES_RESOLVED (1 << 16) /* X | | | */
/* | | | */
+/* Children must reuse parent get_iterator() | | | */
+#define ZEND_ACC_REUSE_GET_ITERATOR (1 << 17) /* X | | | */
+/* | | | */
/* Function Flags (unused: 28...30) | | | */
/* ============== | | | */
/* | | | */
diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c
index e5b6251d17..c86aee1082 100644
--- a/Zend/zend_interfaces.c
+++ b/Zend/zend_interfaces.c
@@ -381,7 +381,13 @@ static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry
return FAILURE;
}
}
- class_type->get_iterator = zend_user_it_get_iterator;
+ if (class_type->parent
+ && (class_type->parent->ce_flags & ZEND_ACC_REUSE_GET_ITERATOR)) {
+ class_type->get_iterator = class_type->parent->get_iterator;
+ class_type->ce_flags |= ZEND_ACC_REUSE_GET_ITERATOR;
+ } else {
+ class_type->get_iterator = zend_user_it_get_iterator;
+ }
funcs_ptr = class_type->iterator_funcs_ptr;
if (class_type->type == ZEND_INTERNAL_CLASS) {
if (!funcs_ptr) {
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index 1198885505..ab488726df 100644
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -206,7 +206,6 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zval *
while (parent) {
if (parent == spl_ce_ArrayIterator || parent == spl_ce_RecursiveArrayIterator) {
intern->std.handlers = &spl_handler_ArrayIterator;
- class_type->get_iterator = spl_array_get_iterator;
break;
} else if (parent == spl_ce_ArrayObject) {
intern->std.handlers = &spl_handler_ArrayObject;
@@ -1969,6 +1968,8 @@ PHP_MINIT_FUNCTION(spl_array)
REGISTER_SPL_IMPLEMENTS(ArrayIterator, Countable);
memcpy(&spl_handler_ArrayIterator, &spl_handler_ArrayObject, sizeof(zend_object_handlers));
spl_ce_ArrayIterator->get_iterator = spl_array_get_iterator;
+ spl_ce_ArrayIterator->ce_flags |= ZEND_ACC_REUSE_GET_ITERATOR;
+
REGISTER_SPL_CLASS_CONST_LONG(ArrayObject, "STD_PROP_LIST", SPL_ARRAY_STD_PROP_LIST);
REGISTER_SPL_CLASS_CONST_LONG(ArrayObject, "ARRAY_AS_PROPS", SPL_ARRAY_ARRAY_AS_PROPS);
@@ -1979,6 +1980,7 @@ PHP_MINIT_FUNCTION(spl_array)
REGISTER_SPL_SUB_CLASS_EX(RecursiveArrayIterator, ArrayIterator, spl_array_object_new, spl_funcs_RecursiveArrayIterator);
REGISTER_SPL_IMPLEMENTS(RecursiveArrayIterator, RecursiveIterator);
spl_ce_RecursiveArrayIterator->get_iterator = spl_array_get_iterator;
+ spl_ce_RecursiveArrayIterator->ce_flags |= ZEND_ACC_REUSE_GET_ITERATOR;
REGISTER_SPL_CLASS_CONST_LONG(RecursiveArrayIterator, "CHILD_ARRAYS_ONLY", SPL_ARRAY_CHILD_ARRAYS_ONLY);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment