ruby-changes:38657
From: ko1 <ko1@a...>
Date: Wed, 3 Jun 2015 04:49:33 +0900 (JST)
Subject: [ruby-changes:38657] ko1:r50738 (trunk): * vm_insnhelper.c (vm_defined): check respond_to_missing?
ko1 2015-06-03 04:49:22 +0900 (Wed, 03 Jun 2015) New Revision: 50738 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=50738 Log: * vm_insnhelper.c (vm_defined): check respond_to_missing? at defined?(func()). * test/ruby/test_defined.rb: add a test for this fix. Modified files: trunk/ChangeLog trunk/test/ruby/test_defined.rb trunk/vm_insnhelper.c Index: ChangeLog =================================================================== --- ChangeLog (revision 50737) +++ ChangeLog (revision 50738) @@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Wed Jun 3 04:48:05 2015 Koichi Sasada <ko1@a...> + + * vm_insnhelper.c (vm_defined): check respond_to_missing? + at defined?(func()). + + * test/ruby/test_defined.rb: add a test for this fix. + Wed Jun 3 04:34:39 2015 Koichi Sasada <ko1@a...> * vm_insnhelper.c (vm_defined): skip respond_to_missing? when Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 50737) +++ vm_insnhelper.c (revision 50738) @@ -2409,6 +2409,22 @@ FUNC_FASTCALL(rb_vm_opt_struct_aset)(rb_ https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L2409 /* defined insn */ +static enum defined_type +check_resopnd_to_missing(VALUE obj, VALUE v) +{ + VALUE args[2]; + VALUE r; + + args[0] = obj; args[1] = Qfalse; + r = rb_check_funcall(v, idRespond_to_missing, 2, args); + if (r != Qundef && RTEST(r)) { + return DEFINED_METHOD; + } + else { + return 0; + } +} + static VALUE vm_defined(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE obj, VALUE needstr, VALUE v) { @@ -2449,6 +2465,9 @@ vm_defined(rb_thread_t *th, rb_control_f https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L2465 if (rb_method_boundp(klass, SYM2ID(obj), 0)) { expr_type = DEFINED_METHOD; } + else { + expr_type = check_resopnd_to_missing(obj, v); + } break; case DEFINED_METHOD:{ VALUE klass = CLASS_OF(v); @@ -2462,13 +2481,7 @@ vm_defined(rb_thread_t *th, rb_control_f https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L2481 } } else { - VALUE args[2]; - VALUE r; - - args[0] = obj; args[1] = Qfalse; - r = rb_check_funcall(v, idRespond_to_missing, 2, args); - if (r != Qundef && RTEST(r)) - expr_type = DEFINED_METHOD; + expr_type = check_resopnd_to_missing(obj, v); } break; } Index: test/ruby/test_defined.rb =================================================================== --- test/ruby/test_defined.rb (revision 50737) +++ test/ruby/test_defined.rb (revision 50738) @@ -223,6 +223,14 @@ class TestDefined < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_defined.rb#L223 def existing_method end + + def func_defined_existing_func + defined?(existing_method()) + end + + def func_defined_non_existing_func + defined?(non_existing_method()) + end end def test_method_by_respond_to_missing @@ -232,5 +240,12 @@ class TestDefined < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_defined.rb#L240 assert_equal(false, obj.called, bug_11211) assert_equal(nil, defined?(obj.non_existing_method), bug_11211) assert_equal(true, obj.called, bug_11211) + + bug_11212 = '[Bug #11212]' + obj = ExampleRespondToMissing.new + assert_equal("method", obj.func_defined_existing_func, bug_11212) + assert_equal(false, obj.called, bug_11212) + assert_equal(nil, obj.func_defined_non_existing_func, bug_11212) + assert_equal(true, obj.called, bug_11212) end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/