Project

General

Profile

Feature #12300 ยป 0001-Allow-clone-to-take-freeze-false-keyword-argument-to.patch

jeremyevans0 (Jeremy Evans), 04/19/2016 12:38 AM

View differences:

object.c
299 299

  
300 300
/*
301 301
 *  call-seq:
302
 *     obj.clone -> an_object
302
 *     obj.clone(freeze: true) -> an_object
303 303
 *
304 304
 *  Produces a shallow copy of <i>obj</i>---the instance variables of
305 305
 *  <i>obj</i> are copied, but not the objects they reference.
306
 *  <code>clone</code> copies the frozen and tainted state of <i>obj</i>.
306
 *  <code>clone</code> copies the frozen (unless :freeze keyword argument
307
 *  is given with a false value) and tainted state of <i>obj</i>.
307 308
 *  See also the discussion under <code>Object#dup</code>.
308 309
 *
309 310
 *     class Klass
......
321 322
 *  the class.
322 323
 */
323 324

  
324
VALUE
325
rb_obj_clone(VALUE obj)
325
static VALUE
326
rb_obj_clone2(int argc, VALUE *argv, VALUE obj)
326 327
{
328
    static ID keyword_ids[1];
329
    VALUE opt;
330
    VALUE kwargs[1];
327 331
    VALUE clone;
328 332
    VALUE singleton;
333
    VALUE kwfreeze = Qtrue;
334
    int n;
335

  
336
    if (!keyword_ids[0]) {
337
	CONST_ID(keyword_ids[0], "freeze");
338
    }
339
    n = rb_scan_args(argc, argv, "0:", &opt);
340
    if (!NIL_P(opt)) {
341
	rb_get_kwargs(opt, keyword_ids, 0, 1, kwargs);
342
	kwfreeze = kwargs[0];
343
    }
329 344

  
330 345
    if (rb_special_const_p(obj)) {
331 346
        rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj));
......
342 357

  
343 358
    init_copy(clone, obj);
344 359
    rb_funcall(clone, id_init_clone, 1, obj);
345
    RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
360

  
361
    if (Qfalse != kwfreeze) {
362
	RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
363
    }
346 364

  
347 365
    return clone;
348 366
}
349 367

  
368
VALUE
369
rb_obj_clone(VALUE obj)
370
{
371
    return rb_obj_clone2(0, NULL, obj);
372
}
373

  
350 374
/*
351 375
 *  call-seq:
352 376
 *     obj.dup -> an_object
......
3424 3448

  
3425 3449
    rb_define_method(rb_mKernel, "class", rb_obj_class, 0);
3426 3450
    rb_define_method(rb_mKernel, "singleton_class", rb_obj_singleton_class, 0);
3427
    rb_define_method(rb_mKernel, "clone", rb_obj_clone, 0);
3451
    rb_define_method(rb_mKernel, "clone", rb_obj_clone2, -1);
3428 3452
    rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0);
3429 3453
    rb_define_method(rb_mKernel, "itself", rb_obj_itself, 0);
3430 3454
    rb_define_method(rb_mKernel, "initialize_copy", rb_obj_init_copy, 1);
test/ruby/test_object.rb
28 28
    end
29 29
  end
30 30

  
31
  def test_clone
32
    a = Object.new
33
    def a.b; 2 end
34
    
35
    a.freeze
36
    c = a.clone
37
    assert_equal(true, c.frozen?)
38
    assert_equal(2, c.b)
39

  
40
    d = a.clone(freeze: false)
41
    def d.e; 3; end
42
    assert_equal(false, d.frozen?)
43
    assert_equal(2, d.b)
44
    assert_equal(3, d.e)
45
  end
46

  
31 47
  def test_init_dupclone
32 48
    cls = Class.new do
33 49
      def initialize_clone(orig); throw :initialize_clone; end
34
-