diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2011-08-05 03:18:25 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2011-08-05 03:18:25 +0000 |
commit | 55148a250101b662fde32919f14afcf2dcdc801d (patch) | |
tree | fc5c632f160f695dabc3579a58b4fb188fd7e190 | |
parent | 2205687ccf6caf2d7b9998478751508afba707c6 (diff) | |
download | ruby-55148a250101b662fde32919f14afcf2dcdc801d.tar.gz |
* vm_eval.c (check_funcall): try respond_to? first if redefined.
[Bug #5158]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32855 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | test/ruby/test_object.rb | 25 | ||||
-rw-r--r-- | test/ruby/test_proc.rb | 2 | ||||
-rw-r--r-- | vm_eval.c | 17 |
4 files changed, 44 insertions, 5 deletions
@@ -1,3 +1,8 @@ +Fri Aug 5 12:18:20 2011 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * vm_eval.c (check_funcall): try respond_to? first if redefined. + [Bug #5158] + Fri Aug 05 09:48:22 2011 Eric Hodel <drbrain@segment7.net> * lib/rubygems: Import RubyGems 1.8.7: diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb index c4f0f79db3..b23a8e6498 100644 --- a/test/ruby/test_object.rb +++ b/test/ruby/test_object.rb @@ -396,6 +396,31 @@ class TestObject < Test::Unit::TestCase end end + def test_implicit_respond_to + bug5158 = '[ruby-core:38799]' + + p = Object.new + + called = [] + p.singleton_class.class_eval do + define_method(:to_ary) do + called << [:to_ary, bug5158] + end + end + [[p]].flatten + assert_equal([[:to_ary, bug5158]], called, bug5158) + + called = [] + p.singleton_class.class_eval do + define_method(:respond_to?) do |*a| + called << [:respond_to?, *a] + false + end + end + [[p]].flatten + assert_equal([[:respond_to?, :to_ary, true]], called, bug5158) + end + def test_send_with_no_arguments assert_raise(ArgumentError) { 1.send } end diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb index efd5a269fd..3cac94a100 100644 --- a/test/ruby/test_proc.rb +++ b/test/ruby/test_proc.rb @@ -787,7 +787,7 @@ class TestProc < Test::Unit::TestCase end def test_splat_without_respond_to - def (obj = Object.new).respond_to?(m); false end + def (obj = Object.new).respond_to?(m,*); false end [obj].each do |a, b| assert_equal([obj, nil], [a, b], '[ruby-core:24139]') end @@ -203,7 +203,7 @@ stack_check(void) } static inline rb_method_entry_t *rb_search_method_entry(VALUE recv, ID mid); -static inline int rb_method_call_status(rb_thread_t *th, rb_method_entry_t *me, call_type scope, VALUE self); +static inline int rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type scope, VALUE self); #define NOEX_OK NOEX_NOSUPER /*! @@ -265,10 +265,19 @@ check_funcall_failed(struct rescue_funcall_args *args, VALUE e) static VALUE check_funcall(VALUE recv, ID mid, int argc, VALUE *argv) { - rb_method_entry_t *me = rb_search_method_entry(recv, mid); + const rb_method_entry_t *me = rb_method_entry(CLASS_OF(recv), idRespond_to); rb_thread_t *th = GET_THREAD(); - int call_status = rb_method_call_status(th, me, CALL_FCALL, Qundef); + int call_status; + + if (me && !(me->flag & NOEX_BASIC)) { + VALUE args[2] = {ID2SYM(mid), Qtrue}; + if (!RTEST(vm_call0(th, recv, idRespond_to, 2, args, me))) { + return Qundef; + } + } + me = rb_search_method_entry(recv, mid); + call_status = rb_method_call_status(th, me, CALL_FCALL, Qundef); if (call_status != NOEX_OK) { if (rb_method_basic_definition_p(CLASS_OF(recv), idMethodMissing)) { return Qundef; @@ -375,7 +384,7 @@ rb_search_method_entry(VALUE recv, ID mid) } static inline int -rb_method_call_status(rb_thread_t *th, rb_method_entry_t *me, call_type scope, VALUE self) +rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type scope, VALUE self) { VALUE klass; ID oid; |