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

ruby-changes:38465

From: nagachika <ko1@a...>
Date: Wed, 20 May 2015 02:59:53 +0900 (JST)
Subject: [ruby-changes:38465] nagachika:r50546 (ruby_2_2): merge revision(s) 50038: [Backport #10985]

nagachika	2015-05-20 02:59:39 +0900 (Wed, 20 May 2015)

  New Revision: 50546

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=50546

  Log:
    merge revision(s) 50038: [Backport #10985]
    
    * proc.c (respond_to_missing_p): check if the receiver responds to
      the given method by respond_to_missing?.
    
    * proc.c (mnew_missing): create Method object for method_missing.
      [ruby-core:68564] [Bug #10985]

  Modified directories:
    branches/ruby_2_2/
  Modified files:
    branches/ruby_2_2/ChangeLog
    branches/ruby_2_2/proc.c
    branches/ruby_2_2/test/-ext-/symbol/test_inadvertent_creation.rb
    branches/ruby_2_2/version.h
Index: ruby_2_2/ChangeLog
===================================================================
--- ruby_2_2/ChangeLog	(revision 50545)
+++ ruby_2_2/ChangeLog	(revision 50546)
@@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_2/ChangeLog#L1
+Wed May 20 02:49:49 2015  Nobuyoshi Nakada  <nobu@r...>
+
+	* proc.c (respond_to_missing_p): check if the receiver responds to
+	  the given method by respond_to_missing?.
+
+	* proc.c (mnew_missing): create Method object for method_missing.
+	  [ruby-core:68564] [Bug #10985]
+
 Wed May 20 02:16:05 2015  NAKAMURA Usaku  <usa@r...>
 
 	* dir.c (replace_real_basename): need to check the return value of
Index: ruby_2_2/proc.c
===================================================================
--- ruby_2_2/proc.c	(revision 50545)
+++ ruby_2_2/proc.c	(revision 50546)
@@ -1131,29 +1131,68 @@ rb_obj_is_method(VALUE m) https://github.com/ruby/ruby/blob/trunk/ruby_2_2/proc.c#L1131
     }
 }
 
+static int
+respond_to_missing_p(VALUE klass, VALUE obj, VALUE sym, int scope)
+{
+    /* TODO: merge with obj_respond_to() */
+    ID rmiss = idRespond_to_missing;
+
+    if (obj == Qundef) return 0;
+    if (rb_method_basic_definition_p(klass, rmiss)) return 0;
+    return RTEST(rb_funcall(obj, rmiss, 2, sym, scope ? Qfalse : Qtrue));
+}
+
+
+static VALUE
+mnew_missing(VALUE rclass, VALUE klass, VALUE obj, ID id, ID rid, VALUE mclass)
+{
+    struct METHOD *data;
+    VALUE method = TypedData_Make_Struct(mclass, struct METHOD, &method_data_type, data);
+    rb_method_entry_t *me;
+    rb_method_definition_t *def;
+
+    data->recv = obj;
+    data->rclass = rclass;
+    data->defined_class = klass;
+    data->id = rid;
+
+    me = ALLOC(rb_method_entry_t);
+    data->me = me;
+    me->flag = 0;
+    me->mark = 0;
+    me->called_id = id;
+    me->klass = klass;
+    me->def = 0;
+
+    def = ALLOC(rb_method_definition_t);
+    me->def = def;
+    def->type = VM_METHOD_TYPE_MISSING;
+    def->original_id = id;
+    def->alias_count = 0;
+
+    data->ume = ALLOC(struct unlinked_method_entry_list_entry);
+    data->me->def->alias_count++;
+
+    OBJ_INFECT(method, klass);
+
+    return method;
+}
+
 static VALUE
 mnew_internal(rb_method_entry_t *me, VALUE defined_class, VALUE klass,
 	      VALUE obj, ID id, VALUE mclass, int scope, int error)
 {
-    VALUE method;
+    struct METHOD *data;
     VALUE rclass = klass;
+    VALUE method;
     ID rid = id;
-    struct METHOD *data;
     rb_method_definition_t *def = 0;
     rb_method_flag_t flag = NOEX_UNDEF;
 
   again:
     if (UNDEFINED_METHOD_ENTRY_P(me)) {
-	ID rmiss = idRespond_to_missing;
-	VALUE sym = ID2SYM(id);
-
-	if (obj != Qundef && !rb_method_basic_definition_p(klass, rmiss)) {
-	    if (RTEST(rb_funcall(obj, rmiss, 2, sym, scope ? Qfalse : Qtrue))) {
-		me = 0;
-		defined_class = klass;
-
-		goto gen_method;
-	    }
+	if (respond_to_missing_p(klass, obj, ID2SYM(id), scope)) {
+	    return mnew_missing(rclass, klass, obj, id, rid, mclass);
 	}
 	if (!error) return Qnil;
 	rb_print_undef(klass, id, 0);
@@ -1180,7 +1219,6 @@ mnew_internal(rb_method_entry_t *me, VAL https://github.com/ruby/ruby/blob/trunk/ruby_2_2/proc.c#L1219
 	rclass = RCLASS_SUPER(rclass);
     }
 
-  gen_method:
     method = TypedData_Make_Struct(mclass, struct METHOD, &method_data_type, data);
 
     data->recv = obj;
@@ -1188,25 +1226,7 @@ mnew_internal(rb_method_entry_t *me, VAL https://github.com/ruby/ruby/blob/trunk/ruby_2_2/proc.c#L1226
     data->defined_class = defined_class;
     data->id = rid;
     data->me = ALLOC(rb_method_entry_t);
-    if (me) {
-	*data->me = *me;
-    }
-    else {
-	me = data->me;
-	me->flag = 0;
-	me->mark = 0;
-	me->called_id = id;
-	me->klass = klass;
-	me->def = 0;
-
-	def = ALLOC(rb_method_definition_t);
-	me->def = def;
-
-	def->type = VM_METHOD_TYPE_MISSING;
-	def->original_id = id;
-	def->alias_count = 0;
-
-    }
+    *data->me = *me;
     data->ume = ALLOC(struct unlinked_method_entry_list_entry);
     data->me->def->alias_count++;
 
@@ -1438,6 +1458,23 @@ rb_method_name_error(VALUE klass, VALUE https://github.com/ruby/ruby/blob/trunk/ruby_2_2/proc.c#L1458
 		      QUOTE(str), s0, rb_class_name(c));
 }
 
+static VALUE
+obj_method(VALUE obj, VALUE vid, int scope)
+{
+    ID id = rb_check_id(&vid);
+    const VALUE klass = CLASS_OF(obj);
+    const VALUE mclass = rb_cMethod;
+
+    if (!id) {
+	if (respond_to_missing_p(klass, obj, vid, scope)) {
+	    id = rb_intern_str(vid);
+	    return mnew_missing(klass, klass, obj, id, id, mclass);
+	}
+	rb_method_name_error(klass, vid);
+    }
+    return mnew(klass, obj, id, mclass, scope);
+}
+
 /*
  *  call-seq:
  *     obj.method(sym)    -> method
@@ -1469,11 +1506,7 @@ rb_method_name_error(VALUE klass, VALUE https://github.com/ruby/ruby/blob/trunk/ruby_2_2/proc.c#L1506
 VALUE
 rb_obj_method(VALUE obj, VALUE vid)
 {
-    ID id = rb_check_id(&vid);
-    if (!id) {
-	rb_method_name_error(CLASS_OF(obj), vid);
-    }
-    return mnew(CLASS_OF(obj), obj, id, rb_cMethod, FALSE);
+    return obj_method(obj, vid, FALSE);
 }
 
 /*
@@ -1486,11 +1519,7 @@ rb_obj_method(VALUE obj, VALUE vid) https://github.com/ruby/ruby/blob/trunk/ruby_2_2/proc.c#L1519
 VALUE
 rb_obj_public_method(VALUE obj, VALUE vid)
 {
-    ID id = rb_check_id(&vid);
-    if (!id) {
-	rb_method_name_error(CLASS_OF(obj), vid);
-    }
-    return mnew(CLASS_OF(obj), obj, id, rb_cMethod, TRUE);
+    return obj_method(obj, vid, TRUE);
 }
 
 /*
@@ -1524,6 +1553,11 @@ rb_obj_singleton_method(VALUE obj, VALUE https://github.com/ruby/ruby/blob/trunk/ruby_2_2/proc.c#L1553
     VALUE klass;
     ID id = rb_check_id(&vid);
     if (!id) {
+	if (!NIL_P(klass = rb_singleton_class_get(obj)) &&
+	    respond_to_missing_p(klass, obj, vid, FALSE)) {
+	    id = rb_intern_str(vid);
+	    return mnew_missing(klass, klass, obj, id, id, rb_cMethod);
+	}
 	rb_name_error_str(vid, "undefined singleton method `%"PRIsVALUE"' for `%"PRIsVALUE"'",
 			  QUOTE(vid), obj);
     }
Index: ruby_2_2/version.h
===================================================================
--- ruby_2_2/version.h	(revision 50545)
+++ ruby_2_2/version.h	(revision 50546)
@@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_2/version.h#L1
 #define RUBY_VERSION "2.2.3"
 #define RUBY_RELEASE_DATE "2015-05-20"
-#define RUBY_PATCHLEVEL 105
+#define RUBY_PATCHLEVEL 106
 
 #define RUBY_RELEASE_YEAR 2015
 #define RUBY_RELEASE_MONTH 5
Index: ruby_2_2/test/-ext-/symbol/test_inadvertent_creation.rb
===================================================================
--- ruby_2_2/test/-ext-/symbol/test_inadvertent_creation.rb	(revision 50545)
+++ ruby_2_2/test/-ext-/symbol/test_inadvertent_creation.rb	(revision 50546)
@@ -82,6 +82,28 @@ module Test_Symbol https://github.com/ruby/ruby/blob/trunk/ruby_2_2/test/-ext-/symbol/test_inadvertent_creation.rb#L82
       assert_not_interned_false(c, :class_variable_defined?, noninterned_name("@@"), feature5072)
     end
 
+    def test_missing_method
+      bug10985 = '[ruby-core:68564] [Bug #10985]'
+      m = nil
+      c = Class.new do
+        def self.respond_to_missing?(*)
+          true
+        end
+      end
+
+      s = noninterned_name
+      assert_nothing_raised(NameError, bug10985) {m = c.method(s)}
+      assert_raise_with_message(NoMethodError, /#{s}/) {m.call}
+
+      s = noninterned_name
+      assert_nothing_raised(NameError, bug10985) {m = c.public_method(s.to_sym)}
+      assert_raise_with_message(NoMethodError, /#{s}/) {m.call}
+
+      s = noninterned_name
+      assert_nothing_raised(NameError, bug10985) {m = c.singleton_method(s.to_sym)}
+      assert_raise_with_message(NoMethodError, /#{s}/) {m.call}
+    end
+
     Feature5079 = '[ruby-core:38404]'
 
     def test_undefined_instance_variable

Property changes on: ruby_2_2
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /trunk:r50038


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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