Project

General

Profile

Feature #16175 ยป clone-freeze-true-16175.patch

jeremyevans0 (Jeremy Evans), 09/23/2019 11:06 PM

View differences:

object.c
351 351
    }
352 352
}
353 353

  
354
static int freeze_opt(int argc, VALUE *argv);
355
static VALUE immutable_obj_clone(VALUE obj, int kwfreeze);
356
static VALUE mutable_obj_clone(VALUE obj, int kwfreeze);
354
static VALUE freeze_opt(int argc, VALUE *argv);
355
static VALUE immutable_obj_clone(VALUE obj, VALUE kwfreeze);
356
static VALUE mutable_obj_clone(VALUE obj, VALUE kwfreeze);
357 357
PUREFUNC(static inline int special_object_p(VALUE obj)); /*!< \private */
358 358
static inline int
359 359
special_object_p(VALUE obj)
......
374 374

  
375 375
/*
376 376
 *  call-seq:
377
 *     obj.clone(freeze: true) -> an_object
377
 *     obj.clone(freeze: frozen?) -> an_object
378 378
 *
379 379
 *  Produces a shallow copy of <i>obj</i>---the instance variables of
380 380
 *  <i>obj</i> are copied, but not the objects they reference.
381
 *  #clone copies the frozen (unless +:freeze+ keyword argument is
382
 *  given with a false value) and tainted state of <i>obj</i>.  See
383
 *  also the discussion under Object#dup.
381
 *  By default, #clone copies the frozen state of the object, but the
382
 *  +:freeze+ keyword can override this. See also the discussion under
383
 *  Object#dup.
384 384
 *
385 385
 *     class Klass
386 386
 *        attr_accessor :str
......
400 400
static VALUE
401 401
rb_obj_clone2(int argc, VALUE *argv, VALUE obj)
402 402
{
403
    int kwfreeze = freeze_opt(argc, argv);
403
    VALUE kwfreeze = freeze_opt(argc, argv);
404 404
    if (!special_object_p(obj))
405 405
	return mutable_obj_clone(obj, kwfreeze);
406 406
    return immutable_obj_clone(obj, kwfreeze);
......
410 410
VALUE
411 411
rb_immutable_obj_clone(int argc, VALUE *argv, VALUE obj)
412 412
{
413
    int kwfreeze = freeze_opt(argc, argv);
413
    VALUE kwfreeze = freeze_opt(argc, argv);
414 414
    return immutable_obj_clone(obj, kwfreeze);
415 415
}
416 416

  
417
static int
417
static VALUE
418 418
freeze_opt(int argc, VALUE *argv)
419 419
{
420 420
    static ID keyword_ids[1];
421 421
    VALUE opt;
422
    VALUE kwfreeze;
422
    VALUE kwfreeze = Qundef;
423 423

  
424 424
    if (!keyword_ids[0]) {
425 425
	CONST_ID(keyword_ids[0], "freeze");
......
427 427
    rb_scan_args(argc, argv, "0:", &opt);
428 428
    if (!NIL_P(opt)) {
429 429
	rb_get_kwargs(opt, keyword_ids, 0, 1, &kwfreeze);
430
	if (kwfreeze == Qfalse) return FALSE;
430
        if (kwfreeze == Qfalse) return kwfreeze;
431 431
	if (kwfreeze != Qundef && kwfreeze != Qtrue) {
432 432
	    rb_raise(rb_eArgError, "unexpected value for freeze: %"PRIsVALUE,
433 433
		     rb_obj_class(kwfreeze));
434 434
	}
435 435
    }
436
    return TRUE;
436
    return kwfreeze;
437 437
}
438 438

  
439 439
static VALUE
440
immutable_obj_clone(VALUE obj, int kwfreeze)
440
immutable_obj_clone(VALUE obj, VALUE kwfreeze)
441 441
{
442
    if (!kwfreeze)
442
    if (kwfreeze == Qfalse)
443 443
	rb_raise(rb_eArgError, "can't unfreeze %"PRIsVALUE,
444 444
		 rb_obj_class(obj));
445 445
    return obj;
446 446
}
447 447

  
448 448
static VALUE
449
mutable_obj_clone(VALUE obj, int kwfreeze)
449
mutable_obj_clone(VALUE obj, VALUE kwfreeze)
450 450
{
451 451
    VALUE clone, singleton;
452 452

  
......
461 461
    init_copy(clone, obj);
462 462
    rb_funcall(clone, id_init_clone, 1, obj);
463 463

  
464
    if (kwfreeze) {
464
    switch (kwfreeze) {
465
      case Qtrue:
466
        RBASIC(clone)->flags |= FL_FREEZE;
467
        break;
468
      case Qundef:
465 469
	RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
470
        break;
471
      default:
472
        break;
466 473
    }
467 474

  
468 475
    return clone;
test/ruby/test_object.rb
47 47
    a = Object.new
48 48
    def a.b; 2 end
49 49

  
50
    c = a.clone
51
    assert_equal(false, c.frozen?)
52
    assert_equal(2, c.b)
53

  
54
    c = a.clone(freeze: true)
55
    assert_equal(true, c.frozen?)
56
    assert_equal(2, c.b)
57

  
50 58
    a.freeze
51 59
    c = a.clone
52 60
    assert_equal(true, c.frozen?)
53
-