Feature #16129 ยป initialize-clone-freeze-false.patch
lib/delegate.rb | ||
---|---|---|
201 | 201 |
end |
202 | 202 |
end |
203 | 203 | |
204 |
def initialize_clone(obj) # :nodoc: |
|
205 |
self.__setobj__(obj.__getobj__.clone) |
|
204 |
def initialize_clone(obj, freeze: true) # :nodoc:
|
|
205 |
self.__setobj__(obj.__getobj__.clone(freeze: freeze))
|
|
206 | 206 |
end |
207 | 207 |
def initialize_dup(obj) # :nodoc: |
208 | 208 |
self.__setobj__(obj.__getobj__.dup) |
lib/set.rb | ||
---|---|---|
137 | 137 |
end |
138 | 138 | |
139 | 139 |
# Clone internal hash. |
140 |
def initialize_clone(orig) |
|
140 |
def initialize_clone(orig, freeze: true)
|
|
141 | 141 |
super |
142 |
@hash = orig.instance_variable_get(:@hash).clone |
|
142 |
@hash = orig.instance_variable_get(:@hash).clone(freeze: freeze)
|
|
143 | 143 |
end |
144 | 144 | |
145 | 145 |
def freeze # :nodoc: |
object.c | ||
---|---|---|
459 | 459 |
} |
460 | 460 | |
461 | 461 |
init_copy(clone, obj); |
462 |
rb_funcall(clone, id_init_clone, 1, obj); |
|
463 | 462 | |
464 | 463 |
if (kwfreeze) { |
464 |
rb_funcall(clone, id_init_clone, 1, obj); |
|
465 | 465 |
RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE; |
466 | 466 |
} |
467 |
else { |
|
468 |
static VALUE freeze_false_hash; |
|
469 |
if (!freeze_false_hash) { |
|
470 |
freeze_false_hash = rb_hash_new(); |
|
471 |
rb_hash_aset(freeze_false_hash, ID2SYM(rb_intern("freeze")), Qfalse); |
|
472 |
rb_obj_freeze(freeze_false_hash); |
|
473 |
rb_gc_register_mark_object(freeze_false_hash); |
|
474 |
} |
|
475 | ||
476 |
rb_funcall(clone, id_init_clone, 2, obj, freeze_false_hash); |
|
477 |
} |
|
467 | 478 | |
468 | 479 |
return clone; |
469 | 480 |
} |
... | ... | |
622 | 633 |
/*! |
623 | 634 |
* :nodoc: |
624 | 635 |
*-- |
625 |
* Default implementation of \c #initialize_dup and \c #initialize_clone
|
|
636 |
* Default implementation of \c #initialize_dup |
|
626 | 637 |
* |
627 | 638 |
* \param[in,out] obj the receiver being initialized |
628 |
* \param[in] orig the object to be dup or cloned from.
|
|
639 |
* \param[in] orig the object to be dup from. |
|
629 | 640 |
*++ |
630 | 641 |
**/ |
631 | 642 |
VALUE |
... | ... | |
635 | 646 |
return obj; |
636 | 647 |
} |
637 | 648 | |
649 |
/*! |
|
650 |
* :nodoc: |
|
651 |
*-- |
|
652 |
* Default implementation of \c #initialize_clone |
|
653 |
* |
|
654 |
* \param[in,out] obj the receiver being initialized |
|
655 |
* \param[in] orig the object to be cloned from. |
|
656 |
*++ |
|
657 |
**/ |
|
658 |
static VALUE |
|
659 |
rb_obj_init_clone(int argc, VALUE *argv, VALUE obj) |
|
660 |
{ |
|
661 |
VALUE orig, opts; |
|
662 |
rb_scan_args(argc, argv, "1:", &orig, &opts); |
|
663 |
/* Ignore a freeze keyword */ |
|
664 |
if (argc == 2) (void)freeze_opt(1, &opts); |
|
665 |
rb_funcall(obj, id_init_copy, 1, orig); |
|
666 |
return obj; |
|
667 |
} |
|
668 | ||
638 | 669 |
/** |
639 | 670 |
* call-seq: |
640 | 671 |
* obj.to_s -> string |
... | ... | |
2017 | 2048 | |
2018 | 2049 |
/* :nodoc: */ |
2019 | 2050 |
static VALUE |
2020 |
rb_mod_initialize_clone(VALUE clone, VALUE orig)
|
|
2051 |
rb_mod_initialize_clone(int argc, VALUE* argv, VALUE clone)
|
|
2021 | 2052 |
{ |
2022 |
VALUE ret; |
|
2023 |
ret = rb_obj_init_dup_clone(clone, orig); |
|
2053 |
VALUE ret, orig, opts; |
|
2054 |
rb_scan_args(argc, argv, "1:", &orig, &opts); |
|
2055 |
ret = rb_obj_init_clone(argc, argv, clone); |
|
2024 | 2056 |
if (OBJ_FROZEN(orig)) |
2025 | 2057 |
rb_class_name(clone); |
2026 | 2058 |
return ret; |
... | ... | |
4269 | 4301 |
rb_define_method(rb_mKernel, "then", rb_obj_yield_self, 0); |
4270 | 4302 |
rb_define_method(rb_mKernel, "initialize_copy", rb_obj_init_copy, 1); |
4271 | 4303 |
rb_define_method(rb_mKernel, "initialize_dup", rb_obj_init_dup_clone, 1); |
4272 |
rb_define_method(rb_mKernel, "initialize_clone", rb_obj_init_dup_clone, 1);
|
|
4304 |
rb_define_method(rb_mKernel, "initialize_clone", rb_obj_init_clone, -1);
|
|
4273 | 4305 | |
4274 | 4306 |
rb_define_method(rb_mKernel, "taint", rb_obj_taint, 0); |
4275 | 4307 |
rb_define_method(rb_mKernel, "tainted?", rb_obj_tainted, 0); |
... | ... | |
4354 | 4386 | |
4355 | 4387 |
rb_define_alloc_func(rb_cModule, rb_module_s_alloc); |
4356 | 4388 |
rb_define_method(rb_cModule, "initialize", rb_mod_initialize, 0); |
4357 |
rb_define_method(rb_cModule, "initialize_clone", rb_mod_initialize_clone, 1); |
|
4389 |
rb_define_method(rb_cModule, "initialize_clone", rb_mod_initialize_clone, -1);
|
|
4358 | 4390 |
rb_define_method(rb_cModule, "instance_methods", rb_class_instance_methods, -1); /* in class.c */ |
4359 | 4391 |
rb_define_method(rb_cModule, "public_instance_methods", |
4360 | 4392 |
rb_class_public_instance_methods, -1); /* in class.c */ |
test/ruby/test_module.rb | ||
---|---|---|
2469 | 2469 |
assert_equal :M2, CloneTestC2.new.foo, '[Bug #15877]' |
2470 | 2470 |
end |
2471 | 2471 | |
2472 |
def test_clone_freeze |
|
2473 |
m = Module.new.freeze |
|
2474 |
assert_predicate m.clone, :frozen? |
|
2475 |
assert_not_predicate m.clone(freeze: false), :frozen? |
|
2476 |
end |
|
2477 | ||
2472 | 2478 |
private |
2473 | 2479 | |
2474 | 2480 |
def assert_top_method_is_private(method) |
test/ruby/test_object.rb | ||
---|---|---|
75 | 75 |
assert_raise_with_message(ArgumentError, /\u{1f4a9}/) do |
76 | 76 |
Object.new.clone(freeze: x) |
77 | 77 |
end |
78 | ||
79 |
c = Class.new do |
|
80 |
attr_reader :f |
|
81 |
end |
|
82 |
o = c.new |
|
83 |
f = true |
|
84 |
def o.initialize_clone(_, freeze: true) |
|
85 |
@f = freeze |
|
86 |
super |
|
87 |
end |
|
88 |
clone = o.clone |
|
89 |
assert_kind_of c, clone |
|
90 |
assert_equal true, clone.f |
|
91 |
clone = o.clone(freeze: false) |
|
92 |
assert_kind_of c, clone |
|
93 |
assert_equal false, clone.f |
|
94 | ||
95 |
def o.initialize_clone(_) |
|
96 |
super |
|
97 |
end |
|
98 |
assert_kind_of c, o.clone |
|
99 |
assert_raise(ArgumentError) { o.clone(freeze: false) } |
|
78 | 100 |
end |
79 | 101 | |
80 | 102 |
def test_init_dupclone |
test/test_delegate.rb | ||
---|---|---|
50 | 50 |
assert_equal(SimpleDelegator,simple.clone.class) |
51 | 51 |
end |
52 | 52 | |
53 |
def test_simpledelegator_clone |
|
54 |
simple=SimpleDelegator.new([]) |
|
55 |
simple.freeze |
|
56 | ||
57 |
clone = simple.clone |
|
58 |
assert_predicate clone, :frozen? |
|
59 |
assert_predicate clone.__getobj__, :frozen? |
|
60 |
assert_equal true, Kernel.instance_method(:frozen?).bind(clone).call |
|
61 | ||
62 |
clone = simple.clone(freeze: false) |
|
63 |
assert_not_predicate clone, :frozen? |
|
64 |
assert_not_predicate clone.__getobj__, :frozen? |
|
65 |
assert_equal false, Kernel.instance_method(:frozen?).bind(clone).call |
|
66 |
end |
|
67 | ||
53 | 68 |
class Object |
54 | 69 |
def m |
55 | 70 |
:o |
test/test_set.rb | ||
---|---|---|
739 | 739 |
} |
740 | 740 |
end |
741 | 741 | |
742 |
def test_freeze_clone_false |
|
743 |
set1 = Set[1,2,3] |
|
744 |
set1.freeze |
|
745 |
set2 = set1.clone(freeze: false) |
|
746 | ||
747 |
assert_not_predicate set2, :frozen? |
|
748 |
set2.add 5 |
|
749 |
assert_equal Set[1,2,3,5], set2 |
|
750 |
assert_equal Set[1,2,3], set1 |
|
751 |
end |
|
752 | ||
742 | 753 |
def test_inspect |
743 | 754 |
set1 = Set[1, 2] |
744 | 755 |
assert_equal('#<Set: {1, 2}>', set1.inspect) |
745 |
- |