From fd4f120699fafcdb70e50e5c7d5a482ef5b71b7c Mon Sep 17 00:00:00 2001 From: Liran Nuna Date: Mon, 14 Apr 2014 10:48:04 -0700 Subject: [PATCH] ArrayIterator casted to array should result to the storage array ArrayIterator was not correctly casted to array. This diff corrects the issue by overriding the array conversion method. Fixes #2214 Reviewed By: @ptarjan Differential Revision: D1270947 --- hphp/runtime/base/object-data.cpp | 16 +++++++++++++--- hphp/runtime/ext/ext_array.h | 2 -- hphp/system/systemlib.h | 1 + hphp/test/slow/array_iterator/cast_to_array.php | 4 ++++ .../slow/array_iterator/cast_to_array.php.expect | 21 +++++++++++++++++++++ 5 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 hphp/test/slow/array_iterator/cast_to_array.php create mode 100644 hphp/test/slow/array_iterator/cast_to_array.php.expect diff --git a/hphp/runtime/base/object-data.cpp b/hphp/runtime/base/object-data.cpp index e55709ca55e..4cc0e5de25d 100644 --- a/hphp/runtime/base/object-data.cpp +++ b/hphp/runtime/base/object-data.cpp @@ -64,10 +64,10 @@ const StaticString s_serialize("serialize"), s_clone("__clone"); -static Array ArrayObject_toArray(const ObjectData* obj) { +static Array convert_to_array(const ObjectData* obj, HPHP::Class* cls) { bool visible, accessible, unset; auto prop = obj->getProp( - SystemLib::s_ArrayObjectClass, s_storage.get(), + cls, s_storage.get(), visible, accessible, unset ); assert(visible && accessible && !unset); @@ -410,7 +410,9 @@ Array ObjectData::o_toArray(bool pubOnly /* = false */) const { assert(instanceof(c_SimpleXMLElement::classof())); return c_SimpleXMLElement::ToArray(this); } else if (UNLIKELY(instanceof(SystemLib::s_ArrayObjectClass))) { - return ArrayObject_toArray(this); + return convert_to_array(this, SystemLib::s_ArrayObjectClass); + } else if (UNLIKELY(instanceof(SystemLib::s_ArrayIteratorClass))) { + return convert_to_array(this, SystemLib::s_ArrayIteratorClass); } else { Array ret(ArrayData::Create()); o_getArray(ret, pubOnly); @@ -605,6 +607,14 @@ inline Array getSerializeProps(const ObjectData* obj, auto cls = obj->getVMClass(); auto debuginfo = cls->lookupMethod(s_debugInfo.get()); if (!debuginfo) { + // When ArrayIterator is casted to an array, it return it's array object, + // however when it's being var_dump'd or print_r'd, it shows it's properties + if (UNLIKELY(obj->instanceof(SystemLib::s_ArrayIteratorClass))) { + Array ret(ArrayData::Create()); + obj->o_getArray(ret); + return ret; + } + return obj->o_toArray(); } if (debuginfo->attrs() & (AttrPrivate|AttrProtected| diff --git a/hphp/runtime/ext/ext_array.h b/hphp/runtime/ext/ext_array.h index 64e3f2a0150..76592c94b26 100644 --- a/hphp/runtime/ext/ext_array.h +++ b/hphp/runtime/ext/ext_array.h @@ -176,8 +176,6 @@ Variant f_i18n_loc_get_error_code(); Variant f_hphp_array_idx(const Variant& search, const Variant& key, const Variant& def); -Array ArrayObject_toArray(const ObjectData* obj); - /////////////////////////////////////////////////////////////////////////////// } diff --git a/hphp/system/systemlib.h b/hphp/system/systemlib.h index 11144f21695..1ae68245ccd 100644 --- a/hphp/system/systemlib.h +++ b/hphp/system/systemlib.h @@ -54,6 +54,7 @@ namespace Eval { x(Serializable) \ x(ArrayAccess) \ x(ArrayObject) \ + x(ArrayIterator) \ x(Iterator) \ x(IteratorAggregate) \ x(Traversable) \ diff --git a/hphp/test/slow/array_iterator/cast_to_array.php b/hphp/test/slow/array_iterator/cast_to_array.php new file mode 100644 index 00000000000..4c26911ba4b --- /dev/null +++ b/hphp/test/slow/array_iterator/cast_to_array.php @@ -0,0 +1,4 @@ + 1, "b" => 2, "c" => 3)); +var_dump($ao->getIterator()); +var_dump((array)$ao->getIterator()); diff --git a/hphp/test/slow/array_iterator/cast_to_array.php.expect b/hphp/test/slow/array_iterator/cast_to_array.php.expect new file mode 100644 index 00000000000..6a4d8330c4a --- /dev/null +++ b/hphp/test/slow/array_iterator/cast_to_array.php.expect @@ -0,0 +1,21 @@ +object(ArrayIterator)#2 (2) { + ["storage":"ArrayIterator":private]=> + array(3) { + ["a"]=> + int(1) + ["b"]=> + int(2) + ["c"]=> + int(3) + } + ["flags":"ArrayIterator":private]=> + int(0) +} +array(3) { + ["a"]=> + int(1) + ["b"]=> + int(2) + ["c"]=> + int(3) +} -- 2.11.4.GIT