[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]