diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-01-30 10:08:23 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-01-30 10:08:23 +0000 |
commit | 72969cd348ac6f00bbe71ad63120db0114b35367 (patch) | |
tree | d4f7ef5476957e10c14141cfcb3897d468eb8316 | |
parent | cba57022b0685690b29bae9f8d9e8c264ab76fe0 (diff) | |
download | ruby-72969cd348ac6f00bbe71ad63120db0114b35367.tar.gz |
* vm_eval.c (vm_call0): should pass block to enumerators. patched
by Kazuki Tsujimoto. [ruby-dev:44961][Bug #5731]
* vm_eval.c (method_missing), vm_insnhelper.c (vm_call_method):
ditto. patched by satoshi shiba.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34399 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | test/ruby/test_object.rb | 51 | ||||
-rw-r--r-- | vm_eval.c | 3 | ||||
-rw-r--r-- | vm_insnhelper.c | 1 |
4 files changed, 63 insertions, 0 deletions
@@ -1,3 +1,11 @@ +Mon Jan 30 19:08:19 2012 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * vm_eval.c (vm_call0): should pass block to enumerators. patched + by Kazuki Tsujimoto. [ruby-dev:44961][Bug #5731] + + * vm_eval.c (method_missing), vm_insnhelper.c (vm_call_method): + ditto. patched by satoshi shiba. + Mon Jan 30 12:31:05 2012 NAKAMURA Usaku <usa@ruby-lang.org> * file.c (append_fspath): need to set the encoding to result always. diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb index 8d8fd8f847..08d85559c4 100644 --- a/test/ruby/test_object.rb +++ b/test/ruby/test_object.rb @@ -446,6 +446,57 @@ class TestObject < Test::Unit::TestCase assert_equal([[:respond_to?, :to_ary, true]], called, bug5158) end + def test_method_missing_passed_block + bug5731 = '[ruby-dev:44961]' + + c = Class.new do + def method_missing(meth, *args) yield(meth, *args) end + end + a = c.new + result = nil + assert_nothing_raised(LocalJumpError, bug5731) do + a.foo {|x| result = x} + end + assert_equal(:foo, result, bug5731) + result = nil + e = a.enum_for(:foo) + assert_nothing_raised(LocalJumpError, bug5731) do + e.each {|x| result = x} + end + assert_equal(:foo, result, bug5731) + + c = Class.new do + def respond_to_missing?(id, priv) + true + end + def method_missing(id, *args, &block) + return block.call(:foo, *args) + end + end + foo = c.new + + result = nil + assert_nothing_raised(LocalJumpError, bug5731) do + foo.foobar {|x| result = x} + end + assert_equal(:foo, result, bug5731) + result = nil + assert_nothing_raised(LocalJumpError, bug5731) do + foo.enum_for(:foobar).each {|x| result = x} + end + assert_equal(:foo, result, bug5731) + + result = nil + foobar = foo.method(:foobar) + foobar.call {|x| result = x} + assert_equal(:foo, result, bug5731) + + result = nil + foobar = foo.method(:foobar) + foobar.enum_for(:call).each {|x| result = x} + assert_equal(:foo, result, bug5731) + end + def test_send_with_no_arguments assert_raise(ArgumentError) { 1.send } end @@ -118,6 +118,7 @@ vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv, RB_GC_GUARD(new_args); rb_ary_unshift(new_args, ID2SYM(id)); + th->passed_block = blockptr; return rb_funcall2(recv, idMethodMissing, argc+1, RARRAY_PTR(new_args)); } @@ -563,6 +564,7 @@ method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status) { VALUE *nargv, result, argv_ary = 0; rb_thread_t *th = GET_THREAD(); + const rb_block_t *blockptr = th->passed_block; th->method_missing_reason = call_status; th->passed_block = 0; @@ -589,6 +591,7 @@ method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status) if (rb_method_basic_definition_p(CLASS_OF(obj) , idMethodMissing)) { raise_method_missing(th, argc+1, nargv, obj, call_status | NOEX_MISSING); } + th->passed_block = blockptr; result = rb_funcall2(obj, idMethodMissing, argc + 1, nargv); if (argv_ary) rb_ary_clear(argv_ary); return result; diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 92f6f7c1e2..a123171580 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -599,6 +599,7 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, argv[0] = ID2SYM(me->def->original_id); MEMCPY(argv+1, cfp->sp - num, VALUE, num); cfp->sp += - num - 1; + th->passed_block = blockptr; val = rb_funcall2(recv, rb_intern("method_missing"), num+1, argv); break; } |