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

ruby-changes:26597

From: nobu <ko1@a...>
Date: Sat, 29 Dec 2012 11:38:00 +0900 (JST)
Subject: [ruby-changes:26597] nobu:r38648 (trunk): object.c: singleton class clone

nobu	2012-12-29 11:37:47 +0900 (Sat, 29 Dec 2012)

  New Revision: 38648

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

  Log:
    object.c: singleton class clone
    
    * object.c (rb_obj_clone): attach clone to its singleton class during
      cloning singleton class so that singleton_method_added will be called
      on it.  based on the patch by shiba (satoshi shiba)[Bug #5283] in
      [ruby-dev:44477].  [Bug #5283]

  Modified files:
    trunk/ChangeLog
    trunk/class.c
    trunk/internal.h
    trunk/object.c
    trunk/test/ruby/test_class.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 38647)
+++ ChangeLog	(revision 38648)
@@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sat Dec 29 11:37:36 2012  Nobuyoshi Nakada  <nobu@r...>
+
+	* object.c (rb_obj_clone): attach clone to its singleton class during
+	  cloning singleton class so that singleton_method_added will be called
+	  on it.  based on the patch by shiba (satoshi shiba)[Bug #5283] in
+	  [ruby-dev:44477].  [Bug #5283]
+
 Sat Dec 29 10:10:39 2012  Nobuyoshi Nakada  <nobu@r...>
 
 	* configure.in (crt_externs.h): use standard macro AC_CHECK_HEADERS.
Index: object.c
===================================================================
--- object.c	(revision 38647)
+++ object.c	(revision 38648)
@@ -298,7 +298,7 @@ rb_obj_clone(VALUE obj) https://github.com/ruby/ruby/blob/trunk/object.c#L298
         rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj));
     }
     clone = rb_obj_alloc(rb_obj_class(obj));
-    singleton = rb_singleton_class_clone(obj);
+    singleton = rb_singleton_class_clone_and_attach(obj, clone);
     RBASIC(clone)->klass = singleton;
     if (FL_TEST(singleton, FL_SINGLETON)) {
 	rb_singleton_class_attached(singleton, clone);
Index: class.c
===================================================================
--- class.c	(revision 38647)
+++ class.c	(revision 38648)
@@ -240,6 +240,12 @@ rb_mod_init_copy(VALUE clone, VALUE orig https://github.com/ruby/ruby/blob/trunk/class.c#L240
 VALUE
 rb_singleton_class_clone(VALUE obj)
 {
+    return rb_singleton_class_clone_and_attach(obj, Qundef);
+}
+
+VALUE
+rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
+{
     VALUE klass = RBASIC(obj)->klass;
 
     if (!FL_TEST(klass, FL_SINGLETON))
@@ -264,6 +270,9 @@ rb_singleton_class_clone(VALUE obj) https://github.com/ruby/ruby/blob/trunk/class.c#L270
 	    RCLASS_CONST_TBL(clone) = st_init_numtable();
 	    st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone));
 	}
+	if (attach != Qundef) {
+	    rb_singleton_class_attached(clone, attach);
+	}
 	RCLASS_M_TBL(clone) = st_init_numtable();
 	st_foreach(RCLASS_M_TBL(klass), clone_method_i, (st_data_t)clone);
 	rb_singleton_class_attached(RBASIC(clone)->klass, clone);
Index: internal.h
===================================================================
--- internal.h	(revision 38647)
+++ internal.h	(revision 38648)
@@ -63,6 +63,7 @@ VALUE rb_obj_private_methods(int argc, V https://github.com/ruby/ruby/blob/trunk/internal.h#L63
 VALUE rb_obj_public_methods(int argc, VALUE *argv, VALUE obj);
 int rb_obj_basic_to_s_p(VALUE);
 VALUE rb_special_singleton_class(VALUE);
+VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach);
 void Init_class_hierarchy(void);
 
 /* compile.c */
Index: test/ruby/test_class.rb
===================================================================
--- test/ruby/test_class.rb	(revision 38647)
+++ test/ruby/test_class.rb	(revision 38648)
@@ -336,4 +336,18 @@ class TestClass < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_class.rb#L336
       end;
     end
   end
+
+  def test_cloned_singleton_method_added
+    bug5283 = '[ruby-dev:44477]'
+    added = []
+    c = Class.new
+    c.singleton_class.class_eval do
+      define_method(:singleton_method_added) {|mid| added << [self, mid]}
+      def foo; :foo; end
+    end
+    added.clear
+    d = c.clone
+    assert_empty(added.grep(->(k) {c == k[0]}), bug5283)
+    assert_equal(:foo, d.foo)
+  end
 end

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

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