Project

General

Profile

Feature #16129 ยป initialize-clone-freeze-false.patch

jeremyevans0 (Jeremy Evans), 08/26/2019 04:20 AM

View differences:

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
-