From 925f3c00e8e3701328a360c88562ef5b954937c4 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 31 May 2024 20:42:13 +0100 Subject: [PATCH] ext/spl: [WIP] Convert ArrayObject to new API --- ...rrayAccess_container_offset_behaviour.phpt | 2 +- ...rrayObject_container_offset_behaviour.phpt | 45 --- Zend/tests/offsets/appending_containers.phpt | 3 +- .../appending_containers_in_fetch.phpt | 28 +- .../reference_containers_appended.phpt | 21 +- Zend/zend_execute.c | 8 +- ext/spl/spl_array.c | 353 +++++++++--------- ext/spl/spl_array.stub.php | 14 +- ext/spl/spl_array_arginfo.h | 27 +- .../indirect_assign_reference_to_offset.phpt | 51 +++ ext/spl/tests/arrayIterator_count_basic1.phpt | 38 ++ ext/spl/tests/arrayObject_count_basic1.phpt | 36 +- ext/spl/tests/array_010.phpt | 2 +- ext/spl/tests/bug33136.phpt | 10 +- ext/spl/tests/bug34548.phpt | 9 +- ext/spl/tests/bug52861.phpt | 2 +- ext/spl/tests/bug66834.phpt | 16 +- ext/spl/tests/bug70852.phpt | 2 - ext/spl/tests/bug74058.phpt | 5 - ext/spl/tests/iterator_035.phpt | 19 +- 20 files changed, 374 insertions(+), 317 deletions(-) create mode 100644 ext/spl/tests/ArrayObject/indirect_assign_reference_to_offset.phpt create mode 100644 ext/spl/tests/arrayIterator_count_basic1.phpt diff --git a/Zend/tests/offsets/ArrayAccess_container_offset_behaviour.phpt b/Zend/tests/offsets/ArrayAccess_container_offset_behaviour.phpt index dca1ae2a33664..dc3ea812e0517 100644 --- a/Zend/tests/offsets/ArrayAccess_container_offset_behaviour.phpt +++ b/Zend/tests/offsets/ArrayAccess_container_offset_behaviour.phpt @@ -102,7 +102,7 @@ Cannot unset offset in a non-array variable OUTPUT; ob_start(); -foreach (['A', 'B'] as $class) { +foreach (['A'] as $class) { foreach ($offsets as $dimension) { $container = new $class(); $error = "(new $class())[" . zend_test_var_export($dimension) . '] has different outputs' . "\n"; diff --git a/Zend/tests/offsets/ArrayObject_container_offset_behaviour.phpt b/Zend/tests/offsets/ArrayObject_container_offset_behaviour.phpt index de995f608419b..1e0053d81297d 100644 --- a/Zend/tests/offsets/ArrayObject_container_offset_behaviour.phpt +++ b/Zend/tests/offsets/ArrayObject_container_offset_behaviour.phpt @@ -183,49 +183,6 @@ OUTPUT; $EXPECTED_OUTPUT_INVALID_OFFSETS_REGEX = '/^' . expectf_to_regex(EXPECTED_OUTPUT_INVALID_OFFSETS) . '$/s'; -const EXPECTED_OUTPUT_NULL_OFFSET = << diff --git a/Zend/tests/offsets/appending_containers_in_fetch.phpt b/Zend/tests/offsets/appending_containers_in_fetch.phpt index a598d9334c8fa..e3cf028a9e3cd 100644 --- a/Zend/tests/offsets/appending_containers_in_fetch.phpt +++ b/Zend/tests/offsets/appending_containers_in_fetch.phpt @@ -60,9 +60,16 @@ Error: Cannot use a scalar value as an array new stdClass() container: Error: Cannot use object of type stdClass as array new ArrayObject() container: - -Notice: Indirect modification of overloaded element of ArrayObject has no effect in %s on line %d -Error: ArrayObject::fetchAppend() must return a reference type +object(ArrayObject)#2 (1) { + ["storage":"ArrayObject":private]=> + array(1) { + [0]=> + array(1) { + [5]=> + string(5) "value" + } + } +} new A() container: string(12) "A::offsetGet" NULL @@ -70,8 +77,13 @@ NULL Notice: Indirect modification of overloaded element of A has no effect in %s on line %d Error: Cannot use a scalar value as an array new B() container: -string(12) "B::offsetGet" -NULL - -Notice: Indirect modification of overloaded element of B has no effect in %s on line %d -Error: Cannot use a scalar value as an array +object(B)#4 (1) { + ["storage":"ArrayObject":private]=> + array(1) { + [0]=> + array(1) { + [5]=> + string(5) "value" + } + } +} diff --git a/Zend/tests/offsets/reference_containers_appended.phpt b/Zend/tests/offsets/reference_containers_appended.phpt index fc8aa99dd313d..bcca4f4f47582 100644 --- a/Zend/tests/offsets/reference_containers_appended.phpt +++ b/Zend/tests/offsets/reference_containers_appended.phpt @@ -54,9 +54,14 @@ Error: Cannot use a scalar value as an array new stdClass() container: Error: Cannot use object of type stdClass as array new ArrayObject() container: - -Notice: Indirect modification of overloaded element of ArrayObject has no effect in %s on line %d -Error: ArrayObject::fetchAppend() must return a reference type +object(ArrayObject)#2 (1) { + ["storage":"ArrayObject":private]=> + array(1) { + [0]=> + &NULL + } +} +NULL new A() container: string(12) "A::offsetGet" NULL @@ -66,13 +71,11 @@ object(A)#3 (0) { } int(5) new B() container: -string(12) "B::offsetGet" -NULL - -Notice: Indirect modification of overloaded element of B has no effect in %s on line %d object(B)#4 (1) { ["storage":"ArrayObject":private]=> - array(0) { + array(1) { + [0]=> + &NULL } } -int(5) +NULL diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 570fef7f955d1..252fe2deb5b8e 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2765,13 +2765,19 @@ static zend_never_inline void zend_fetch_object_dimension_address(zval *result, ZVAL_UNDEF(result); goto clean_up; } - if (!Z_ISREF_P(retval) && Z_TYPE_P(retval) != IS_OBJECT) { + if ( + !Z_ISREF_P(retval) + && Z_TYPE_P(retval) != IS_OBJECT + ) { zend_class_entry *ce = obj->ce; zend_throw_error(NULL, "%s::%s() must return a reference type", ZSTR_VAL(ce->name), offset ? "offsetFetch" : "fetchAppend"); ZVAL_UNDEF(result); goto clean_up; } + if (result != retval) { + ZVAL_INDIRECT(result, retval); + } } else { zend_use_object_as_array(obj); ZVAL_UNDEF(result); diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 6c3782ba51e2e..e74a49e4825ec 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -51,9 +51,6 @@ typedef struct _spl_array_object { bool is_child; Bucket *bucket; zend_function *fptr_offset_get; - zend_function *fptr_offset_set; - zend_function *fptr_offset_has; - zend_function *fptr_offset_del; zend_function *fptr_count; zend_class_entry* ce_get_iterator; zend_object std; @@ -197,18 +194,7 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zend_o if (intern->fptr_offset_get->common.scope == parent) { intern->fptr_offset_get = NULL; } - intern->fptr_offset_set = zend_hash_str_find_ptr(&class_type->function_table, "offsetset", sizeof("offsetset") - 1); - if (intern->fptr_offset_set->common.scope == parent) { - intern->fptr_offset_set = NULL; - } - intern->fptr_offset_has = zend_hash_str_find_ptr(&class_type->function_table, "offsetexists", sizeof("offsetexists") - 1); - if (intern->fptr_offset_has->common.scope == parent) { - intern->fptr_offset_has = NULL; - } - intern->fptr_offset_del = zend_hash_str_find_ptr(&class_type->function_table, "offsetunset", sizeof("offsetunset") - 1); - if (intern->fptr_offset_del->common.scope == parent) { - intern->fptr_offset_del = NULL; - } + /* Find count() method */ intern->fptr_count = zend_hash_find_ptr(&class_type->function_table, ZSTR_KNOWN(ZEND_STR_COUNT)); if (intern->fptr_count->common.scope == parent) { @@ -305,16 +291,17 @@ static zend_result get_hash_key(spl_hash_key *key, spl_array_object *intern, zva return SUCCESS; } -static zval *spl_array_get_dimension_ptr(bool check_inherited, spl_array_object *intern, const zend_string *ce_name, - zval *offset, int type) /* {{{ */ -{ +static zval *spl_array_get_dimension_ptr( + spl_array_object *intern, + const zend_string *ce_name, + zval *offset, + int type +) { zval *retval; spl_hash_key key; HashTable *ht = spl_array_get_hash_table(intern); - if (!offset || Z_ISUNDEF_P(offset) || !ht) { - return &EG(uninitialized_zval); - } + ZEND_ASSERT(ht); if ((type == BP_VAR_W || type == BP_VAR_RW) && intern->nApplyCount > 0) { zend_throw_error(NULL, "Modification of ArrayObject during sorting is prohibited"); @@ -392,59 +379,38 @@ static zval *spl_array_get_dimension_ptr(bool check_inherited, spl_array_object } } return retval; -} /* }}} */ - -static int spl_array_has_dimension(zend_object *object, zval *offset, int check_empty); +} -static zval *spl_array_read_dimension_ex(int check_inherited, zend_object *object, zval *offset, int type, zval *rv) /* {{{ */ +static zval *spl_array_read_dimension_ex(zend_object *object, zval *offset, int type, zval *rv) /* {{{ */ { spl_array_object *intern = spl_array_from_obj(object); - zval *ret; + zval *ret = spl_array_get_dimension_ptr(intern, object->ce->name, offset, type); - if (check_inherited && - (intern->fptr_offset_get || (type == BP_VAR_IS && intern->fptr_offset_has))) { - if (type == BP_VAR_IS) { - if (!spl_array_has_dimension(object, offset, 0)) { - return &EG(uninitialized_zval); - } - } - - if (intern->fptr_offset_get) { - zval tmp; - if (!offset) { - ZVAL_UNDEF(&tmp); - offset = &tmp; - } - zend_call_method_with_1_params(object, object->ce, &intern->fptr_offset_get, "offsetGet", rv, offset); - - if (!Z_ISUNDEF_P(rv)) { - return rv; - } - return &EG(uninitialized_zval); - } + if (ret == &EG(error_zval) || EG(exception)) { + return NULL; } - ret = spl_array_get_dimension_ptr(check_inherited, intern, object->ce->name, offset, type); - - /* When in a write context, - * ZE has to be fooled into thinking this is in a reference set - * by separating (if necessary) and returning as IS_REFERENCE (with refcount == 1) - */ - - if ((type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) && - !Z_ISREF_P(ret) && - EXPECTED(ret != &EG(uninitialized_zval))) { - ZVAL_NEW_REF(ret, ret); + if (type == BP_VAR_W) { + ZVAL_MAKE_REF(ret); + //ZVAL_COPY(rv, ret); + return ret; + } else { + ZVAL_COPY_DEREF(rv, ret); + return rv; } - return ret; } /* }}} */ -static zval *spl_array_read_dimension(zend_object *object, zval *offset, int type, zval *rv) /* {{{ */ +static zval *spl_array_read_dimension(zend_object *object, zval *offset, zval *rv) /* {{{ */ { - return spl_array_read_dimension_ex(1, object, offset, type, rv); + return spl_array_read_dimension_ex(object, offset, BP_VAR_R, rv); } /* }}} */ +static zval *spl_array_fetch_dimension(zend_object *object, zval *offset, zval *rv) +{ + return spl_array_read_dimension_ex(object, offset, BP_VAR_W, rv); +} + /* * The assertion(HT_ASSERT_RC1(ht)) failed because the refcount was increased manually when intern->is_child is true. * We have to set the refcount to 1 to make assertion success and restore the refcount to the original value after @@ -461,23 +427,11 @@ static uint32_t spl_array_set_refcount(bool is_child, HashTable *ht, uint32_t re return old_refcount; } /* }}} */ -static void spl_array_write_dimension_ex(int check_inherited, zend_object *object, zval *offset, zval *value) /* {{{ */ +static void spl_array_write_dimension(zend_object *object, zval *offset, zval *value) /* {{{ */ { spl_array_object *intern = spl_array_from_obj(object); - HashTable *ht; spl_hash_key key; - if (check_inherited && intern->fptr_offset_set) { - zval tmp; - - if (!offset) { - ZVAL_NULL(&tmp); - offset = &tmp; - } - zend_call_method_with_2_params(object, object->ce, &intern->fptr_offset_set, "offsetSet", NULL, offset, value); - return; - } - if (intern->nApplyCount > 0) { zend_throw_error(NULL, "Modification of ArrayObject during sorting is prohibited"); return; @@ -486,16 +440,7 @@ static void spl_array_write_dimension_ex(int check_inherited, zend_object *objec Z_TRY_ADDREF_P(value); uint32_t refcount = 0; - if (!offset || Z_TYPE_P(offset) == IS_NULL) { - ht = spl_array_get_hash_table(intern); - refcount = spl_array_set_refcount(intern->is_child, ht, 1); - zend_hash_next_index_insert(ht, value); - - if (refcount) { - spl_array_set_refcount(intern->is_child, ht, refcount); - } - return; - } + HashTable *ht = spl_array_get_hash_table(intern); if (get_hash_key(&key, intern, offset) == FAILURE) { zend_illegal_container_offset(object->ce->name, offset, BP_VAR_W); @@ -503,7 +448,6 @@ static void spl_array_write_dimension_ex(int check_inherited, zend_object *objec return; } - ht = spl_array_get_hash_table(intern); refcount = spl_array_set_refcount(intern->is_child, ht, 1); if (key.key) { zend_hash_update_ind(ht, key.key, value); @@ -517,22 +461,61 @@ static void spl_array_write_dimension_ex(int check_inherited, zend_object *objec } } /* }}} */ -static void spl_array_write_dimension(zend_object *object, zval *offset, zval *value) /* {{{ */ +static void spl_array_append(zend_object *object, zval *value) { - spl_array_write_dimension_ex(1, object, offset, value); -} /* }}} */ + spl_array_object *intern = spl_array_from_obj(object); + + if (spl_array_is_object(intern)) { + zend_throw_error(NULL, "Cannot append properties to objects, use %s::offsetSet() instead", ZSTR_VAL(object->ce->name)); + return; + } + if (intern->nApplyCount > 0) { + zend_throw_error(NULL, "Modification of ArrayObject during sorting is prohibited"); + return; + } + + Z_TRY_ADDREF_P(value); + HashTable *ht = spl_array_get_hash_table(intern); + uint32_t refcount = spl_array_set_refcount(intern->is_child, ht, 1); + zend_hash_next_index_insert(ht, value); -static void spl_array_unset_dimension_ex(int check_inherited, zend_object *object, zval *offset) /* {{{ */ + if (refcount) { + spl_array_set_refcount(intern->is_child, ht, refcount); + } +} + +static zval* spl_array_fetch_append(zend_object *object, zval *rv) { - HashTable *ht; spl_array_object *intern = spl_array_from_obj(object); - spl_hash_key key; - if (check_inherited && intern->fptr_offset_del) { - zend_call_method_with_1_params(object, object->ce, &intern->fptr_offset_del, "offsetUnset", NULL, offset); - return; + if (spl_array_is_object(intern)) { + zend_throw_error(NULL, "Cannot append properties to objects, use %s::offsetSet() instead", ZSTR_VAL(object->ce->name)); + return NULL; + } + + HashTable *ht = spl_array_get_hash_table(intern); + uint32_t refcount = spl_array_set_refcount(intern->is_child, ht, 1); + + zval dummy; + ZVAL_NULL(&dummy); + zval *ret = zend_hash_next_index_insert(ht, &dummy); + + if (refcount) { + spl_array_set_refcount(intern->is_child, ht, refcount); } + // TODO Use indirect to fix "Cannot assign by reference to an array dimension of an object" Error being thrown? + ZVAL_MAKE_REF(ret); + ZVAL_COPY(rv, ret); + + return rv; +} + +static void spl_array_unset_dimension(zend_object *object, zval *offset) /* {{{ */ +{ + spl_array_object *intern = spl_array_from_obj(object); + spl_hash_key key; + if (intern->nApplyCount > 0) { zend_throw_error(NULL, "Modification of ArrayObject during sorting is prohibited"); return; @@ -543,7 +526,7 @@ static void spl_array_unset_dimension_ex(int check_inherited, zend_object *objec return; } - ht = spl_array_get_hash_table(intern); + HashTable *ht = spl_array_get_hash_table(intern); uint32_t refcount = spl_array_set_refcount(intern->is_child, ht, 1); if (key.key) { @@ -574,80 +557,27 @@ static void spl_array_unset_dimension_ex(int check_inherited, zend_object *objec } } /* }}} */ -static void spl_array_unset_dimension(zend_object *object, zval *offset) /* {{{ */ -{ - spl_array_unset_dimension_ex(1, object, offset); -} /* }}} */ - -/* check_empty can take value 0, 1, or 2 - * 0/1 are used as normal boolean, but 2 is used for the case when this function is called from - * the offsetExists() method, in which case it needs to report the offset exist even if the value is null */ -static bool spl_array_has_dimension_ex(bool check_inherited, zend_object *object, zval *offset, int check_empty) /* {{{ */ +static bool spl_array_has_dimension(zend_object *object, zval *offset) /* {{{ */ { spl_array_object *intern = spl_array_from_obj(object); - zval rv, *value = NULL, *tmp; - - if (check_inherited && intern->fptr_offset_has) { - zend_call_method_with_1_params(object, object->ce, &intern->fptr_offset_has, "offsetExists", &rv, offset); - - if (!zend_is_true(&rv)) { - zval_ptr_dtor(&rv); - return 0; - } - zval_ptr_dtor(&rv); - - /* For isset calls we don't need to check the value, so return early */ - if (!check_empty) { - return 1; - } else if (intern->fptr_offset_get) { - value = spl_array_read_dimension_ex(1, object, offset, BP_VAR_R, &rv); - } - } + zval *tmp = NULL; - if (!value) { - HashTable *ht = spl_array_get_hash_table(intern); - spl_hash_key key; - - if (get_hash_key(&key, intern, offset) == FAILURE) { - zend_illegal_container_offset(object->ce->name, offset, BP_VAR_IS); - return 0; - } - - if (key.key) { - tmp = zend_hash_find(ht, key.key); - spl_hash_key_release(&key); - } else { - tmp = zend_hash_index_find(ht, key.h); - } - - if (!tmp) { - return 0; - } - - /* check_empty is only equal to 2 if it is called from offsetExists on this class, - * where it needs to report an offset exists even if the value is null */ - if (check_empty == 2) { - return 1; - } + const HashTable *ht = spl_array_get_hash_table(intern); + spl_hash_key key; - if (check_empty && check_inherited && intern->fptr_offset_get) { - value = spl_array_read_dimension_ex(1, object, offset, BP_VAR_R, &rv); - } else { - value = tmp; - } + if (get_hash_key(&key, intern, offset) == FAILURE) { + zend_illegal_container_offset(object->ce->name, offset, BP_VAR_IS); + return false; } - if (value == &rv) { - zval_ptr_dtor(&rv); + if (key.key) { + tmp = zend_hash_find(ht, key.key); + spl_hash_key_release(&key); + } else { + tmp = zend_hash_index_find(ht, key.h); } - /* empty() check the value is not falsy, isset() only check it is not null */ - return check_empty ? zend_is_true(value) : Z_TYPE_P(value) != IS_NULL; -} /* }}} */ - -static int spl_array_has_dimension(zend_object *object, zval *offset, int check_empty) /* {{{ */ -{ - return spl_array_has_dimension_ex(/* check_inherited */ true, object, offset, check_empty); + return tmp != NULL; } /* }}} */ /* {{{ Returns whether the requested $index exists. */ @@ -657,22 +587,40 @@ PHP_METHOD(ArrayObject, offsetExists) if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &index) == FAILURE) { RETURN_THROWS(); } - RETURN_BOOL(spl_array_has_dimension_ex(/* check_inherited */ false, Z_OBJ_P(ZEND_THIS), index, 2)); + RETURN_BOOL(spl_array_has_dimension(Z_OBJ_P(ZEND_THIS), index)); } /* }}} */ /* {{{ Returns the value at the specified $index. */ PHP_METHOD(ArrayObject, offsetGet) { - zval *value, *index; + zval *index; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &index) == FAILURE) { RETURN_THROWS(); } - value = spl_array_read_dimension_ex(0, Z_OBJ_P(ZEND_THIS), index, BP_VAR_R, return_value); - if (value != return_value) { - RETURN_COPY_DEREF(value); + + zval *value = spl_array_read_dimension(Z_OBJ_P(ZEND_THIS), index, return_value); + if (value == NULL) { + RETURN_THROWS(); } } /* }}} */ + +PHP_METHOD(ArrayObject, offsetFetch) +{ + zval *index = NULL; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &index) == FAILURE) { + RETURN_THROWS(); + } + + zval *value = spl_array_fetch_dimension(Z_OBJ_P(ZEND_THIS), index, return_value); + if (value == NULL) { + RETURN_THROWS(); + } + ZVAL_COPY(return_value, value); + ZEND_ASSERT(Z_ISREF_P(return_value)); + ZEND_ASSERT(Z_ISREF_P(value)); +} + /* {{{ Sets the value at the specified $index to $newval. */ PHP_METHOD(ArrayObject, offsetSet) { @@ -680,19 +628,14 @@ PHP_METHOD(ArrayObject, offsetSet) if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &index, &value) == FAILURE) { RETURN_THROWS(); } - spl_array_write_dimension_ex(0, Z_OBJ_P(ZEND_THIS), index, value); + spl_array_write_dimension(Z_OBJ_P(ZEND_THIS), index, value); } /* }}} */ + +// TODO Remove to just use spl_array_append() void spl_array_iterator_append(zval *object, zval *append_value) /* {{{ */ { - spl_array_object *intern = Z_SPLARRAY_P(object); - - if (spl_array_is_object(intern)) { - zend_throw_error(NULL, "Cannot append properties to objects, use %s::offsetSet() instead", ZSTR_VAL(Z_OBJCE_P(object)->name)); - return; - } - - spl_array_write_dimension(Z_OBJ_P(object), NULL, append_value); + spl_array_append(Z_OBJ_P(object), append_value); } /* }}} */ /* {{{ Appends the value (cannot be called for objects). */ @@ -703,9 +646,17 @@ PHP_METHOD(ArrayObject, append) if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &value) == FAILURE) { RETURN_THROWS(); } - spl_array_iterator_append(ZEND_THIS, value); + spl_array_append(Z_OBJ_P(ZEND_THIS), value); } /* }}} */ +PHP_METHOD(ArrayObject, fetchAppend) +{ + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + spl_array_fetch_append(Z_OBJ_P(ZEND_THIS), return_value); +} + /* {{{ Unsets the value at the specified $index. */ PHP_METHOD(ArrayObject, offsetUnset) { @@ -713,7 +664,7 @@ PHP_METHOD(ArrayObject, offsetUnset) if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &index) == FAILURE) { RETURN_THROWS(); } - spl_array_unset_dimension_ex(0, Z_OBJ_P(ZEND_THIS), index); + spl_array_unset_dimension(Z_OBJ_P(ZEND_THIS), index); } /* }}} */ /* {{{ Return a copy of the contained array */ @@ -815,7 +766,7 @@ static zval *spl_array_read_property(zend_object *object, zend_string *name, int && !zend_std_has_property(object, name, ZEND_PROPERTY_EXISTS, NULL)) { zval member; ZVAL_STR(&member, name); - return spl_array_read_dimension(object, &member, type, rv); + return spl_array_read_dimension_ex(object, &member, type, rv); } return zend_std_read_property(object, name, type, cache_slot, rv); } /* }}} */ @@ -847,7 +798,8 @@ static zval *spl_array_get_property_ptr_ptr(zend_object *object, zend_string *na return NULL; } ZVAL_STR(&member, name); - return spl_array_get_dimension_ptr(1, intern, object->ce->name, &member, type); + + return spl_array_get_dimension_ptr(intern, object->ce->name, &member, type); } return zend_std_get_property_ptr_ptr(object, name, type, cache_slot); } /* }}} */ @@ -860,7 +812,8 @@ static int spl_array_has_property(zend_object *object, zend_string *name, int ha && !zend_std_has_property(object, name, ZEND_PROPERTY_EXISTS, NULL)) { zval member; ZVAL_STR(&member, name); - return spl_array_has_dimension(object, &member, has_set_exists); + // TODO Need fixing with empty? + return spl_array_has_dimension(object, &member); } return zend_std_has_property(object, name, has_set_exists, cache_slot); } /* }}} */ @@ -1875,19 +1828,31 @@ PHP_METHOD(RecursiveArrayIterator, getChildren) /* {{{ PHP_MINIT_FUNCTION(spl_array) */ PHP_MINIT_FUNCTION(spl_array) { - spl_ce_ArrayObject = register_class_ArrayObject(zend_ce_aggregate, zend_ce_arrayaccess, zend_ce_serializable, zend_ce_countable); + spl_ce_ArrayObject = register_class_ArrayObject( + zend_ce_aggregate, + zend_ce_dimension_fetch, + zend_ce_dimension_write, + zend_ce_dimension_fetch_append, + zend_ce_dimension_unset, + zend_ce_serializable, + zend_ce_countable + ); spl_ce_ArrayObject->create_object = spl_array_object_new; spl_ce_ArrayObject->default_object_handlers = &spl_handler_ArrayObject; + /* The dimension_handlers struct is allocated during the implementation of zend_ce_dimension_fetch */ + spl_ce_ArrayObject->dimension_handlers->read_dimension = spl_array_read_dimension; + spl_ce_ArrayObject->dimension_handlers->has_dimension = spl_array_has_dimension; + spl_ce_ArrayObject->dimension_handlers->fetch_dimension = spl_array_fetch_dimension; + spl_ce_ArrayObject->dimension_handlers->write_dimension = spl_array_write_dimension; + spl_ce_ArrayObject->dimension_handlers->append = spl_array_append; + spl_ce_ArrayObject->dimension_handlers->fetch_append = spl_array_fetch_append; + spl_ce_ArrayObject->dimension_handlers->unset_dimension = spl_array_unset_dimension; memcpy(&spl_handler_ArrayObject, &std_object_handlers, sizeof(zend_object_handlers)); spl_handler_ArrayObject.offset = XtOffsetOf(spl_array_object, std); spl_handler_ArrayObject.clone_obj = spl_array_object_clone; - spl_handler_ArrayObject.read_dimension = spl_array_read_dimension; - spl_handler_ArrayObject.write_dimension = spl_array_write_dimension; - spl_handler_ArrayObject.unset_dimension = spl_array_unset_dimension; - spl_handler_ArrayObject.has_dimension = spl_array_has_dimension; spl_handler_ArrayObject.count_elements = spl_array_object_count_elements; spl_handler_ArrayObject.get_properties_for = spl_array_get_properties_for; @@ -1901,10 +1866,26 @@ PHP_MINIT_FUNCTION(spl_array) spl_handler_ArrayObject.compare = spl_array_compare_objects; spl_handler_ArrayObject.free_obj = spl_array_object_free_storage; - spl_ce_ArrayIterator = register_class_ArrayIterator(spl_ce_SeekableIterator, zend_ce_arrayaccess, zend_ce_serializable, zend_ce_countable); + spl_ce_ArrayIterator = register_class_ArrayIterator( + spl_ce_SeekableIterator, + zend_ce_dimension_fetch, + zend_ce_dimension_write, + zend_ce_dimension_fetch_append, + zend_ce_dimension_unset, + zend_ce_serializable, + zend_ce_countable + ); spl_ce_ArrayIterator->create_object = spl_array_object_new; spl_ce_ArrayIterator->default_object_handlers = &spl_handler_ArrayIterator; spl_ce_ArrayIterator->get_iterator = spl_array_get_iterator; + /* The dimension_handlers struct is allocated during the implementation of zend_ce_dimension_fetch */ + spl_ce_ArrayIterator->dimension_handlers->read_dimension = spl_array_read_dimension; + spl_ce_ArrayIterator->dimension_handlers->has_dimension = spl_array_has_dimension; + spl_ce_ArrayIterator->dimension_handlers->fetch_dimension = spl_array_fetch_dimension; + spl_ce_ArrayIterator->dimension_handlers->write_dimension = spl_array_write_dimension; + spl_ce_ArrayIterator->dimension_handlers->append = spl_array_append; + spl_ce_ArrayIterator->dimension_handlers->fetch_append = spl_array_fetch_append; + spl_ce_ArrayIterator->dimension_handlers->unset_dimension = spl_array_unset_dimension; memcpy(&spl_handler_ArrayIterator, &spl_handler_ArrayObject, sizeof(zend_object_handlers)); diff --git a/ext/spl/spl_array.stub.php b/ext/spl/spl_array.stub.php index 1f4c81057dcbc..ffb99fb5a8b27 100644 --- a/ext/spl/spl_array.stub.php +++ b/ext/spl/spl_array.stub.php @@ -2,7 +2,7 @@ /** @generate-class-entries */ -class ArrayObject implements IteratorAggregate, ArrayAccess, Serializable, Countable +class ArrayObject implements IteratorAggregate, DimensionFetchable, DimensionWritable, FetchAppendable, DimensionUnsetable, Serializable, Countable { /** @cvalue SPL_ARRAY_STD_PROP_LIST */ public const int STD_PROP_LIST = UNKNOWN; @@ -17,6 +17,8 @@ public function offsetExists(mixed $key): bool {} /** @tentative-return-type */ public function offsetGet(mixed $key): mixed {} + public function &offsetFetch(mixed $offset): mixed {} + /** @tentative-return-type */ public function offsetSet(mixed $key, mixed $value): void {} @@ -26,6 +28,8 @@ public function offsetUnset(mixed $key): void {} /** @tentative-return-type */ public function append(mixed $value): void {} + public function &fetchAppend(): mixed {} + /** @tentative-return-type */ public function getArrayCopy(): array {} @@ -84,7 +88,7 @@ public function getIteratorClass(): string {} public function __debugInfo(): array {} } -class ArrayIterator implements SeekableIterator, ArrayAccess, Serializable, Countable +class ArrayIterator implements SeekableIterator, DimensionFetchable, DimensionWritable, FetchAppendable, DimensionUnsetable, Serializable, Countable { /** @cvalue SPL_ARRAY_STD_PROP_LIST */ public const int STD_PROP_LIST = UNKNOWN; @@ -105,6 +109,9 @@ public function offsetExists(mixed $key): bool {} */ public function offsetGet(mixed $key): mixed {} + /** @implementation-alias ArrayObject::offsetFetch */ + public function &offsetFetch(mixed $offset): mixed {} + /** * @tentative-return-type * @implementation-alias ArrayObject::offsetSet @@ -123,6 +130,9 @@ public function offsetUnset(mixed $key): void {} */ public function append(mixed $value): void {} + /** @implementation-alias ArrayObject::fetchAppend */ + public function &fetchAppend(): mixed {} + /** * @tentative-return-type * @implementation-alias ArrayObject::getArrayCopy diff --git a/ext/spl/spl_array_arginfo.h b/ext/spl/spl_array_arginfo.h index e846943c3cbfe..6e9c2db354d5b 100644 --- a/ext/spl/spl_array_arginfo.h +++ b/ext/spl/spl_array_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: c52e89992bd3c04877daab47f4328af0b6ce619e */ + * Stub hash: f063d5aafc6624d9b3e15ac572d2f6c68d205919 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ArrayObject___construct, 0, 0, 0) ZEND_ARG_TYPE_MASK(0, array, MAY_BE_ARRAY|MAY_BE_OBJECT, "[]") @@ -15,6 +15,10 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ArrayObject_offs ZEND_ARG_TYPE_INFO(0, key, IS_MIXED, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ArrayObject_offsetFetch, 1, 1, IS_MIXED, 0) + ZEND_ARG_TYPE_INFO(0, offset, IS_MIXED, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ArrayObject_offsetSet, 0, 2, IS_VOID, 0) ZEND_ARG_TYPE_INFO(0, key, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) @@ -28,6 +32,9 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ArrayObject_appe ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ArrayObject_fetchAppend, 1, 0, IS_MIXED, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ArrayObject_getArrayCopy, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -94,12 +101,16 @@ ZEND_END_ARG_INFO() #define arginfo_class_ArrayIterator_offsetGet arginfo_class_ArrayObject_offsetGet +#define arginfo_class_ArrayIterator_offsetFetch arginfo_class_ArrayObject_offsetFetch + #define arginfo_class_ArrayIterator_offsetSet arginfo_class_ArrayObject_offsetSet #define arginfo_class_ArrayIterator_offsetUnset arginfo_class_ArrayObject_offsetUnset #define arginfo_class_ArrayIterator_append arginfo_class_ArrayObject_append +#define arginfo_class_ArrayIterator_fetchAppend arginfo_class_ArrayObject_fetchAppend + #define arginfo_class_ArrayIterator_getArrayCopy arginfo_class_ArrayObject_getArrayCopy #define arginfo_class_ArrayIterator_count arginfo_class_ArrayObject_count @@ -156,9 +167,11 @@ ZEND_END_ARG_INFO() ZEND_METHOD(ArrayObject, __construct); ZEND_METHOD(ArrayObject, offsetExists); ZEND_METHOD(ArrayObject, offsetGet); +ZEND_METHOD(ArrayObject, offsetFetch); ZEND_METHOD(ArrayObject, offsetSet); ZEND_METHOD(ArrayObject, offsetUnset); ZEND_METHOD(ArrayObject, append); +ZEND_METHOD(ArrayObject, fetchAppend); ZEND_METHOD(ArrayObject, getArrayCopy); ZEND_METHOD(ArrayObject, count); ZEND_METHOD(ArrayObject, getFlags); @@ -192,9 +205,11 @@ static const zend_function_entry class_ArrayObject_methods[] = { ZEND_ME(ArrayObject, __construct, arginfo_class_ArrayObject___construct, ZEND_ACC_PUBLIC) ZEND_ME(ArrayObject, offsetExists, arginfo_class_ArrayObject_offsetExists, ZEND_ACC_PUBLIC) ZEND_ME(ArrayObject, offsetGet, arginfo_class_ArrayObject_offsetGet, ZEND_ACC_PUBLIC) + ZEND_ME(ArrayObject, offsetFetch, arginfo_class_ArrayObject_offsetFetch, ZEND_ACC_PUBLIC) ZEND_ME(ArrayObject, offsetSet, arginfo_class_ArrayObject_offsetSet, ZEND_ACC_PUBLIC) ZEND_ME(ArrayObject, offsetUnset, arginfo_class_ArrayObject_offsetUnset, ZEND_ACC_PUBLIC) ZEND_ME(ArrayObject, append, arginfo_class_ArrayObject_append, ZEND_ACC_PUBLIC) + ZEND_ME(ArrayObject, fetchAppend, arginfo_class_ArrayObject_fetchAppend, ZEND_ACC_PUBLIC) ZEND_ME(ArrayObject, getArrayCopy, arginfo_class_ArrayObject_getArrayCopy, ZEND_ACC_PUBLIC) ZEND_ME(ArrayObject, count, arginfo_class_ArrayObject_count, ZEND_ACC_PUBLIC) ZEND_ME(ArrayObject, getFlags, arginfo_class_ArrayObject_getFlags, ZEND_ACC_PUBLIC) @@ -221,9 +236,11 @@ static const zend_function_entry class_ArrayIterator_methods[] = { ZEND_ME(ArrayIterator, __construct, arginfo_class_ArrayIterator___construct, ZEND_ACC_PUBLIC) ZEND_RAW_FENTRY("offsetExists", zim_ArrayObject_offsetExists, arginfo_class_ArrayIterator_offsetExists, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("offsetGet", zim_ArrayObject_offsetGet, arginfo_class_ArrayIterator_offsetGet, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_RAW_FENTRY("offsetFetch", zim_ArrayObject_offsetFetch, arginfo_class_ArrayIterator_offsetFetch, ZEND_ACC_PUBLIC|ZEND_ACC_RETURN_REFERENCE, NULL, NULL) ZEND_RAW_FENTRY("offsetSet", zim_ArrayObject_offsetSet, arginfo_class_ArrayIterator_offsetSet, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("offsetUnset", zim_ArrayObject_offsetUnset, arginfo_class_ArrayIterator_offsetUnset, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("append", zim_ArrayObject_append, arginfo_class_ArrayIterator_append, ZEND_ACC_PUBLIC, NULL, NULL) + ZEND_RAW_FENTRY("fetchAppend", zim_ArrayObject_fetchAppend, arginfo_class_ArrayIterator_fetchAppend, ZEND_ACC_PUBLIC|ZEND_ACC_RETURN_REFERENCE, NULL, NULL) ZEND_RAW_FENTRY("getArrayCopy", zim_ArrayObject_getArrayCopy, arginfo_class_ArrayIterator_getArrayCopy, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("count", zim_ArrayObject_count, arginfo_class_ArrayIterator_count, ZEND_ACC_PUBLIC, NULL, NULL) ZEND_RAW_FENTRY("getFlags", zim_ArrayObject_getFlags, arginfo_class_ArrayIterator_getFlags, ZEND_ACC_PUBLIC, NULL, NULL) @@ -254,13 +271,13 @@ static const zend_function_entry class_RecursiveArrayIterator_methods[] = { ZEND_FE_END }; -static zend_class_entry *register_class_ArrayObject(zend_class_entry *class_entry_IteratorAggregate, zend_class_entry *class_entry_ArrayAccess, zend_class_entry *class_entry_Serializable, zend_class_entry *class_entry_Countable) +static zend_class_entry *register_class_ArrayObject(zend_class_entry *class_entry_IteratorAggregate, zend_class_entry *class_entry_DimensionFetchable, zend_class_entry *class_entry_DimensionWritable, zend_class_entry *class_entry_FetchAppendable, zend_class_entry *class_entry_DimensionUnsetable, zend_class_entry *class_entry_Serializable, zend_class_entry *class_entry_Countable) { zend_class_entry ce, *class_entry; INIT_CLASS_ENTRY(ce, "ArrayObject", class_ArrayObject_methods); class_entry = zend_register_internal_class_ex(&ce, NULL); - zend_class_implements(class_entry, 4, class_entry_IteratorAggregate, class_entry_ArrayAccess, class_entry_Serializable, class_entry_Countable); + zend_class_implements(class_entry, 7, class_entry_IteratorAggregate, class_entry_DimensionFetchable, class_entry_DimensionWritable, class_entry_FetchAppendable, class_entry_DimensionUnsetable, class_entry_Serializable, class_entry_Countable); zval const_STD_PROP_LIST_value; ZVAL_LONG(&const_STD_PROP_LIST_value, SPL_ARRAY_STD_PROP_LIST); @@ -277,13 +294,13 @@ static zend_class_entry *register_class_ArrayObject(zend_class_entry *class_entr return class_entry; } -static zend_class_entry *register_class_ArrayIterator(zend_class_entry *class_entry_SeekableIterator, zend_class_entry *class_entry_ArrayAccess, zend_class_entry *class_entry_Serializable, zend_class_entry *class_entry_Countable) +static zend_class_entry *register_class_ArrayIterator(zend_class_entry *class_entry_SeekableIterator, zend_class_entry *class_entry_DimensionFetchable, zend_class_entry *class_entry_DimensionWritable, zend_class_entry *class_entry_FetchAppendable, zend_class_entry *class_entry_DimensionUnsetable, zend_class_entry *class_entry_Serializable, zend_class_entry *class_entry_Countable) { zend_class_entry ce, *class_entry; INIT_CLASS_ENTRY(ce, "ArrayIterator", class_ArrayIterator_methods); class_entry = zend_register_internal_class_ex(&ce, NULL); - zend_class_implements(class_entry, 4, class_entry_SeekableIterator, class_entry_ArrayAccess, class_entry_Serializable, class_entry_Countable); + zend_class_implements(class_entry, 7, class_entry_SeekableIterator, class_entry_DimensionFetchable, class_entry_DimensionWritable, class_entry_FetchAppendable, class_entry_DimensionUnsetable, class_entry_Serializable, class_entry_Countable); zval const_STD_PROP_LIST_value; ZVAL_LONG(&const_STD_PROP_LIST_value, SPL_ARRAY_STD_PROP_LIST); diff --git a/ext/spl/tests/ArrayObject/indirect_assign_reference_to_offset.phpt b/ext/spl/tests/ArrayObject/indirect_assign_reference_to_offset.phpt new file mode 100644 index 0000000000000..f3b932a866523 --- /dev/null +++ b/ext/spl/tests/ArrayObject/indirect_assign_reference_to_offset.phpt @@ -0,0 +1,51 @@ +--TEST-- +Setting indirections must work for ArrayObject +--FILE-- + $var) +{ + $a[$i] = &$var; +} +$a[] = &$var; +var_dump($a); + +echo "Using ArrayObject\n"; +$ao = new ArrayObject; +foreach ([1, 2, 3] as $i => $var) +{ + $ao[$i] = &$var; +} +$ao[] = &$var; +var_dump($ao); +?> +--EXPECT-- +Using array +array(4) { + [0]=> + &int(3) + [1]=> + &int(3) + [2]=> + &int(3) + [3]=> + &int(3) +} +Using ArrayObject +object(ArrayObject)#1 (1) { + ["storage":"ArrayObject":private]=> + array(4) { + [0]=> + &int(3) + [1]=> + &int(3) + [2]=> + &int(3) + [3]=> + &int(3) + } +} diff --git a/ext/spl/tests/arrayIterator_count_basic1.phpt b/ext/spl/tests/arrayIterator_count_basic1.phpt new file mode 100644 index 0000000000000..a987e18523c31 --- /dev/null +++ b/ext/spl/tests/arrayIterator_count_basic1.phpt @@ -0,0 +1,38 @@ +--TEST-- +SPL: ArrayIterator::count() basic functionality. +--FILE-- +==ArrayIterator== +count(), $ao->count()); +?> +--EXPECT-- +==ArrayIterator== +int(99) +int(0) +int(99) +int(1) +int(99) +int(2) +int(99) +int(1) diff --git a/ext/spl/tests/arrayObject_count_basic1.phpt b/ext/spl/tests/arrayObject_count_basic1.phpt index 0554616b5f82e..4d8db69e96e34 100644 --- a/ext/spl/tests/arrayObject_count_basic1.phpt +++ b/ext/spl/tests/arrayObject_count_basic1.phpt @@ -1,5 +1,5 @@ --TEST-- -SPL: ArrayObject::count() and ArrayIterator::count() basic functionality. +SPL: ArrayObject::count() basic functionality. --FILE-- ==ArrayObject== count(), $ao->count()); -?> -==ArrayIterator== -count(), $ao->count()); @@ -61,12 +36,3 @@ int(99) int(2) int(99) int(1) -==ArrayIterator== -int(99) -int(0) -int(99) -int(1) -int(99) -int(2) -int(99) -int(1) diff --git a/ext/spl/tests/array_010.phpt b/ext/spl/tests/array_010.phpt index ce59dcaf0b6a9..dac943e084643 100644 --- a/ext/spl/tests/array_010.phpt +++ b/ext/spl/tests/array_010.phpt @@ -1,5 +1,5 @@ --TEST-- -SPL: ArrayIterator implements ArrayAccess +SPL: ArrayObject implements ArrayAccess --FILE-- append($value); + foreach($dataArray as $value) { + $this->append($value); + } } public function offsetSet($index, $value): void { parent::offsetSet($index, $value); } + // TODO This should work even with old version + //public function append($value): void + //{ + // parent::append($value); + //} } $data1=array('one', 'two', 'three'); diff --git a/ext/spl/tests/bug52861.phpt b/ext/spl/tests/bug52861.phpt index 1213a1e1bc6bc..e1d1fb3bd5c7a 100644 --- a/ext/spl/tests/bug52861.phpt +++ b/ext/spl/tests/bug52861.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #52861 (unset failes with ArrayObject and deep arrays) +Bug #52861 (unset fails with ArrayObject and deep arrays) --FILE-- array('bar' => array('baz' => 'boo')))); diff --git a/ext/spl/tests/bug66834.phpt b/ext/spl/tests/bug66834.phpt index 864ac3725c29e..a0d48c8da1aaf 100644 --- a/ext/spl/tests/bug66834.phpt +++ b/ext/spl/tests/bug66834.phpt @@ -1,5 +1,5 @@ --TEST-- -SPL: Bug #66834 +SPL: Bug #66834 empty() does not work on classes that extend ArrayObject --FILE-- offsetExists('foo'), $object->offsetExists('sbb'), isset($obje ==== class with offsetExists() and offsetGet() ==== string(37) "Called: ArrayObjectBoth::offsetExists" string(37) "Called: ArrayObjectBoth::offsetExists" +string(34) "Called: ArrayObjectBoth::offsetGet" string(37) "Called: ArrayObjectBoth::offsetExists" string(34) "Called: ArrayObjectBoth::offsetGet" bool(true) @@ -89,13 +90,15 @@ bool(true) bool(true) string(37) "Called: ArrayObjectBoth::offsetExists" string(37) "Called: ArrayObjectBoth::offsetExists" +string(34) "Called: ArrayObjectBoth::offsetGet" string(37) "Called: ArrayObjectBoth::offsetExists" string(34) "Called: ArrayObjectBoth::offsetGet" bool(true) -bool(true) +bool(false) bool(true) string(37) "Called: ArrayObjectBoth::offsetExists" string(37) "Called: ArrayObjectBoth::offsetExists" +string(34) "Called: ArrayObjectBoth::offsetGet" string(37) "Called: ArrayObjectBoth::offsetExists" string(34) "Called: ArrayObjectBoth::offsetGet" bool(true) @@ -118,7 +121,7 @@ string(39) "Called: ArrayObjectExists::offsetExists" string(39) "Called: ArrayObjectExists::offsetExists" string(39) "Called: ArrayObjectExists::offsetExists" bool(true) -bool(true) +bool(false) bool(true) string(39) "Called: ArrayObjectExists::offsetExists" string(39) "Called: ArrayObjectExists::offsetExists" @@ -134,14 +137,17 @@ bool(false) bool(true) ==== class with offsetGet() ==== string(33) "Called: ArrayObjectGet::offsetGet" +string(33) "Called: ArrayObjectGet::offsetGet" bool(true) bool(true) bool(true) string(33) "Called: ArrayObjectGet::offsetGet" +string(33) "Called: ArrayObjectGet::offsetGet" bool(true) bool(false) bool(true) string(33) "Called: ArrayObjectGet::offsetGet" +string(33) "Called: ArrayObjectGet::offsetGet" bool(true) bool(true) bool(false) @@ -150,9 +156,11 @@ bool(false) bool(true) ==== class with offsetGet() and offsetSet() ==== +Warning: Undefined array key "foo" in %s on line %d + Warning: Undefined array key "foo" in %s on line %d bool(false) bool(true) bool(false) -bool(true) +bool(false) bool(true) diff --git a/ext/spl/tests/bug70852.phpt b/ext/spl/tests/bug70852.phpt index 44168f990320a..41f0854ab7f1a 100644 --- a/ext/spl/tests/bug70852.phpt +++ b/ext/spl/tests/bug70852.phpt @@ -10,6 +10,4 @@ var_dump($y[NULL]++); --EXPECTF-- Warning: Undefined array key "" in %s on line %d NULL - -Warning: Undefined array key "" in %s on line %d NULL diff --git a/ext/spl/tests/bug74058.phpt b/ext/spl/tests/bug74058.phpt index 32c57153ec100..e1f3454d8792b 100644 --- a/ext/spl/tests/bug74058.phpt +++ b/ext/spl/tests/bug74058.phpt @@ -59,12 +59,8 @@ var_dump($y['a2']); ?> --EXPECTF-- -offsetSet('a1') -offsetGet('a1') object(stdClass)#%s (0) { } -offsetGet('a1') -offsetGet('a1') object(stdClass)#%s (1) { ["b"]=> string(10) "some value" @@ -74,7 +70,6 @@ offsetGet('a2') object(stdClass)#%s (0) { } offsetGet('a2') -offsetGet('a2') object(stdClass)#%s (1) { ["b"]=> string(10) "some value" diff --git a/ext/spl/tests/iterator_035.phpt b/ext/spl/tests/iterator_035.phpt index 0688635450367..9f82a1b6b7046 100644 --- a/ext/spl/tests/iterator_035.phpt +++ b/ext/spl/tests/iterator_035.phpt @@ -9,12 +9,17 @@ $a = new ArrayIterator(); $a[] = $tmp; $a[] = &$tmp; +var_dump($a); echo "Done\n"; ?> ---EXPECTF-- -Notice: Indirect modification of overloaded element of ArrayIterator has no effect in %s on line %d - -Fatal error: Uncaught Error: Cannot assign by reference to an array dimension of an object in %s:%d -Stack trace: -#0 {main} - thrown in %s on line %d +--EXPECT-- +object(ArrayIterator)#1 (1) { + ["storage":"ArrayIterator":private]=> + array(2) { + [0]=> + int(1) + [1]=> + &int(1) + } +} +Done