Skip to content

Commit

Permalink
SPL object not implementing Traversable is now a recoverable error
Browse files Browse the repository at this point in the history
Summary: When an argument to a call like `iterator_count()` did not implement `Traversable`, this used to throw a pure `fatal`. Since 5.6, it now throws a `catchable fatal` (i.e. `E_RECOVERABLE_ERROR` in PHP). Let's match.

Reviewed By: @ptarjan

Differential Revision: D1623321
  • Loading branch information
JoelMarcey authored and hhvm-bot committed Oct 20, 2014
1 parent 75f08ff commit a664efe
Show file tree
Hide file tree
Showing 6 changed files with 11 additions and 6 deletions.
15 changes: 10 additions & 5 deletions hphp/runtime/ext/ext_spl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,14 @@ Variant f_class_uses(const Variant& obj, bool autoload /* = true */) {
return ret;
}

Object get_traversable_object_iterator(const Variant& obj) {
if (!obj.isObject() ||
!obj.getObjectData()->instanceof(SystemLib::s_TraversableClass)) {
raise_error("Argument must implement interface Traversable");
#define CHECK_TRAVERSABLE_IMPL(obj, ret) \
if (!obj.isObject() || \
!obj.getObjectData()->instanceof(SystemLib::s_TraversableClass)) { \
raise_recoverable_error("Argument must implement interface Traversable"); \
return ret; \
}

Object get_traversable_object_iterator(const Variant& obj) {
bool isIteratorAggregate;
Object itObj = obj.getObjectData()
->iterableObject(isIteratorAggregate, true);
Expand All @@ -256,6 +258,7 @@ Object get_traversable_object_iterator(const Variant& obj) {

Variant f_iterator_apply(const Variant& obj, const Variant& func,
const Array& params /* = null_array */) {
CHECK_TRAVERSABLE_IMPL(obj, 0);
Object pobj = get_traversable_object_iterator(obj);
pobj->o_invoke_few_args(s_rewind, 0);
int64_t count = 0;
Expand All @@ -270,6 +273,7 @@ Variant f_iterator_apply(const Variant& obj, const Variant& func,
}

Variant f_iterator_count(const Variant& obj) {
CHECK_TRAVERSABLE_IMPL(obj, 0);
Object pobj = get_traversable_object_iterator(obj);
pobj->o_invoke_few_args(s_rewind, 0);
int64_t count = 0;
Expand All @@ -281,8 +285,9 @@ Variant f_iterator_count(const Variant& obj) {
}

Variant f_iterator_to_array(const Variant& obj, bool use_keys /* = true */) {
Object pobj = get_traversable_object_iterator(obj);
Array ret(Array::Create());
CHECK_TRAVERSABLE_IMPL(obj, ret);
Object pobj = get_traversable_object_iterator(obj);

pobj->o_invoke_few_args(s_rewind, 0);
while (same(pobj->o_invoke_few_args(s_valid, 0), true)) {
Expand Down
2 changes: 1 addition & 1 deletion hphp/test/slow/iterator/iterator_to_array.php.expectf
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ array(3) {
int(3)
}

Fatal error: Argument must implement interface Traversable in %s/test/slow/iterator/iterator_to_array.php on line 11
Catchable fatal error: Argument must implement interface Traversable in %s/test/slow/iterator/iterator_to_array.php on line 11

0 comments on commit a664efe

Please sign in to comment.