aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--lib/delegate.rb9
-rw-r--r--object.c18
-rw-r--r--test/test_delegate.rb3
4 files changed, 39 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 905fa8b38e..ae8c1afcc7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,21 @@ Mon Feb 8 16:27:57 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
* tool/eval.rb, win32/{mkexports,resource}.rb: miniruby no longer
contains "." in $:.
+Mon Feb 8 15:15:07 2010 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_obj_clone): call initialize_clone hook method to
+ call initialize_copy.
+
+ * object.c (rb_obj_dup): call initialize_dup hook.
+
+ * lib/delegate.rb (Delegator#initialize_clone): use new hook to
+ implement deep copy. [ruby-dev:40242]
+
+ * lib/delegate.rb (Delegator#initialize_dup): ditto.
+
+ * test/test_delegate.rb (TestDelegateClass#test_copy_frozen): add
+ a test to ensure #clone copies frozen status.
+
Mon Feb 8 10:28:58 2010 Yukihiro Matsumoto <matz@ruby-lang.org>
* configure.in: check pthread_attr_getstack to prevent obsolete
diff --git a/lib/delegate.rb b/lib/delegate.rb
index 2891167fa8..c38aea5947 100644
--- a/lib/delegate.rb
+++ b/lib/delegate.rb
@@ -205,13 +205,14 @@ class Delegator < BasicObject
end
# :nodoc:
- def dup
- self.class.new(__getobj__.dup)
+ def initialize_clone(obj)
+ self.__setobj__(obj.__getobj__.clone)
end
# :nodoc:
- def clone
- self.class.new(__getobj__.clone)
+ def initialize_dup(obj)
+ self.__setobj__(obj.__getobj__.dup)
end
+ private :initialize_clone, :initialize_dup
# Freeze self and target at once.
def freeze
diff --git a/object.c b/object.c
index 73e5bd12a2..0421824202 100644
--- a/object.c
+++ b/object.c
@@ -31,7 +31,8 @@ VALUE rb_cNilClass;
VALUE rb_cTrueClass;
VALUE rb_cFalseClass;
-static ID id_eq, id_eql, id_match, id_inspect, id_init_copy;
+static ID id_eq, id_eql, id_match, id_inspect;
+static ID id_init_copy, id_init_clone, id_init_dup;
/*
* call-seq:
@@ -204,7 +205,6 @@ init_copy(VALUE dest, VALUE obj)
}
break;
}
- rb_funcall(dest, id_init_copy, 1, obj);
}
/*
@@ -243,6 +243,7 @@ rb_obj_clone(VALUE obj)
RBASIC(clone)->klass = rb_singleton_class_clone(obj);
RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT) | FL_TEST(clone, FL_UNTRUSTED)) & ~(FL_FREEZE|FL_FINALIZE);
init_copy(clone, obj);
+ rb_funcall(clone, id_init_clone, 1, obj);
RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
return clone;
@@ -276,6 +277,7 @@ rb_obj_dup(VALUE obj)
}
dup = rb_obj_alloc(rb_obj_class(obj));
init_copy(dup, obj);
+ rb_funcall(dup, id_init_dup, 1, obj);
return dup;
}
@@ -292,6 +294,14 @@ rb_obj_init_copy(VALUE obj, VALUE orig)
return obj;
}
+/* :nodoc: */
+VALUE
+rb_obj_init_dup_clone(VALUE obj, VALUE orig)
+{
+ rb_funcall(obj, id_init_copy, 1, orig);
+ return obj;
+}
+
/*
* call-seq:
* obj.to_s => string
@@ -2578,6 +2588,8 @@ Init_Object(void)
rb_define_method(rb_mKernel, "clone", rb_obj_clone, 0);
rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0);
rb_define_method(rb_mKernel, "initialize_copy", rb_obj_init_copy, 1);
+ rb_define_method(rb_mKernel, "initialize_dup", rb_obj_init_dup_clone, 1);
+ rb_define_method(rb_mKernel, "initialize_clone", rb_obj_init_dup_clone, 1);
rb_define_method(rb_mKernel, "taint", rb_obj_taint, 0);
rb_define_method(rb_mKernel, "tainted?", rb_obj_tainted, 0);
@@ -2712,6 +2724,8 @@ Init_Object(void)
id_match = rb_intern("=~");
id_inspect = rb_intern("inspect");
id_init_copy = rb_intern("initialize_copy");
+ id_init_clone = rb_intern("initialize_clone");
+ id_init_dup = rb_intern("initialize_dup");
for (i=0; conv_method_names[i].method; i++) {
conv_method_names[i].id = rb_intern(conv_method_names[i].method);
diff --git a/test/test_delegate.rb b/test/test_delegate.rb
index 6998ac748d..dc12aa35f9 100644
--- a/test/test_delegate.rb
+++ b/test/test_delegate.rb
@@ -92,6 +92,9 @@ class TestDelegateClass < Test::Unit::TestCase
d = SimpleDelegator.new(a)
assert_nothing_raised(bug2679) {d.dup[0] += 1}
assert_raise(RuntimeError) {d.clone[0] += 1}
+ d.freeze
+ assert(d.clone.frozen?)
+ assert(!d.dup.frozen?)
end
def test_frozen