From ca7f52a32a9e7967fafc7efd65423303c36753b5 Mon Sep 17 00:00:00 2001 From: marcandre Date: Tue, 27 Aug 2013 02:50:08 +0000 Subject: [PATCH] * enumerator.c: Allow Enumerator size argument to be any callable. Patch by Avdi Grimm. [bug #8641] [ruby-core:56032] [fix GH-362] * test/ruby/test_enumerator.rb: Test for above git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42698 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- enumerator.c | 15 +++++++++------ test/ruby/test_enumerator.rb | 3 +++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/enumerator.c b/enumerator.c index 2a73d6a740..07916e5af5 100644 --- a/enumerator.c +++ b/enumerator.c @@ -339,7 +339,7 @@ enumerator_initialize(int argc, VALUE *argv, VALUE obj) rb_check_arity(argc, 0, 1); recv = generator_init(generator_allocate(rb_cGenerator), rb_block_proc()); if (argc) { - if (NIL_P(argv[0]) || rb_obj_is_proc(argv[0]) || + if (NIL_P(argv[0]) || rb_respond_to(argv[0], id_call) || (RB_TYPE_P(argv[0], T_FLOAT) && RFLOAT_VALUE(argv[0]) == INFINITY)) { size = argv[0]; } @@ -1007,11 +1007,14 @@ enumerator_size(VALUE obj) if (e->size_fn) { return (*e->size_fn)(e->obj, e->args, obj); } - if (rb_obj_is_proc(e->size)) { - if (e->args) - return rb_proc_call(e->size, e->args); - else - return rb_proc_call_with_block(e->size, 0, 0, Qnil); + if (rb_respond_to(e->size, id_call)) { + if (e->args) { + int argc = RARRAY_LENINT(e->args); + VALUE *argv = RARRAY_PTR(e->args); + return rb_funcall2(e->size, id_call, argc, argv); + } else { + return rb_funcall(e->size, id_call, 0); + } } return e->size; } diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb index e3270f3d6a..e1b23792bd 100644 --- a/test/ruby/test_enumerator.rb +++ b/test/ruby/test_enumerator.rb @@ -452,6 +452,9 @@ class TestEnumerator < Test::Unit::TestCase def test_size assert_equal nil, Enumerator.new{}.size assert_equal 42, Enumerator.new(->{42}){}.size + obj = Object.new + def obj.call; 42; end + assert_equal 42, Enumerator.new(obj){}.size assert_equal 42, Enumerator.new(42){}.size assert_equal 1 << 70, Enumerator.new(1 << 70){}.size assert_equal Float::INFINITY, Enumerator.new(Float::INFINITY){}.size