Feature #16175 » clone-freeze-true-16175.patch
| object.c | ||
|---|---|---|
|
}
|
||
|
}
|
||
|
static int freeze_opt(int argc, VALUE *argv);
|
||
|
static VALUE immutable_obj_clone(VALUE obj, int kwfreeze);
|
||
|
static VALUE mutable_obj_clone(VALUE obj, int kwfreeze);
|
||
|
static VALUE freeze_opt(int argc, VALUE *argv);
|
||
|
static VALUE immutable_obj_clone(VALUE obj, VALUE kwfreeze);
|
||
|
static VALUE mutable_obj_clone(VALUE obj, VALUE kwfreeze);
|
||
|
PUREFUNC(static inline int special_object_p(VALUE obj)); /*!< \private */
|
||
|
static inline int
|
||
|
special_object_p(VALUE obj)
|
||
| ... | ... | |
|
/*
|
||
|
* call-seq:
|
||
|
* obj.clone(freeze: true) -> an_object
|
||
|
* obj.clone(freeze: frozen?) -> an_object
|
||
|
*
|
||
|
* Produces a shallow copy of <i>obj</i>---the instance variables of
|
||
|
* <i>obj</i> are copied, but not the objects they reference.
|
||
|
* #clone copies the frozen (unless +:freeze+ keyword argument is
|
||
|
* given with a false value) and tainted state of <i>obj</i>. See
|
||
|
* also the discussion under Object#dup.
|
||
|
* By default, #clone copies the frozen state of the object, but the
|
||
|
* +:freeze+ keyword can override this. See also the discussion under
|
||
|
* Object#dup.
|
||
|
*
|
||
|
* class Klass
|
||
|
* attr_accessor :str
|
||
| ... | ... | |
|
static VALUE
|
||
|
rb_obj_clone2(int argc, VALUE *argv, VALUE obj)
|
||
|
{
|
||
|
int kwfreeze = freeze_opt(argc, argv);
|
||
|
VALUE kwfreeze = freeze_opt(argc, argv);
|
||
|
if (!special_object_p(obj))
|
||
|
return mutable_obj_clone(obj, kwfreeze);
|
||
|
return immutable_obj_clone(obj, kwfreeze);
|
||
| ... | ... | |
|
VALUE
|
||
|
rb_immutable_obj_clone(int argc, VALUE *argv, VALUE obj)
|
||
|
{
|
||
|
int kwfreeze = freeze_opt(argc, argv);
|
||
|
VALUE kwfreeze = freeze_opt(argc, argv);
|
||
|
return immutable_obj_clone(obj, kwfreeze);
|
||
|
}
|
||
|
static int
|
||
|
static VALUE
|
||
|
freeze_opt(int argc, VALUE *argv)
|
||
|
{
|
||
|
static ID keyword_ids[1];
|
||
|
VALUE opt;
|
||
|
VALUE kwfreeze;
|
||
|
VALUE kwfreeze = Qundef;
|
||
|
if (!keyword_ids[0]) {
|
||
|
CONST_ID(keyword_ids[0], "freeze");
|
||
| ... | ... | |
|
rb_scan_args(argc, argv, "0:", &opt);
|
||
|
if (!NIL_P(opt)) {
|
||
|
rb_get_kwargs(opt, keyword_ids, 0, 1, &kwfreeze);
|
||
|
if (kwfreeze == Qfalse) return FALSE;
|
||
|
if (kwfreeze == Qfalse) return kwfreeze;
|
||
|
if (kwfreeze != Qundef && kwfreeze != Qtrue) {
|
||
|
rb_raise(rb_eArgError, "unexpected value for freeze: %"PRIsVALUE,
|
||
|
rb_obj_class(kwfreeze));
|
||
|
}
|
||
|
}
|
||
|
return TRUE;
|
||
|
return kwfreeze;
|
||
|
}
|
||
|
static VALUE
|
||
|
immutable_obj_clone(VALUE obj, int kwfreeze)
|
||
|
immutable_obj_clone(VALUE obj, VALUE kwfreeze)
|
||
|
{
|
||
|
if (!kwfreeze)
|
||
|
if (kwfreeze == Qfalse)
|
||
|
rb_raise(rb_eArgError, "can't unfreeze %"PRIsVALUE,
|
||
|
rb_obj_class(obj));
|
||
|
return obj;
|
||
|
}
|
||
|
static VALUE
|
||
|
mutable_obj_clone(VALUE obj, int kwfreeze)
|
||
|
mutable_obj_clone(VALUE obj, VALUE kwfreeze)
|
||
|
{
|
||
|
VALUE clone, singleton;
|
||
| ... | ... | |
|
init_copy(clone, obj);
|
||
|
rb_funcall(clone, id_init_clone, 1, obj);
|
||
|
if (kwfreeze) {
|
||
|
switch (kwfreeze) {
|
||
|
case Qtrue:
|
||
|
RBASIC(clone)->flags |= FL_FREEZE;
|
||
|
break;
|
||
|
case Qundef:
|
||
|
RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
return clone;
|
||
| test/ruby/test_object.rb | ||
|---|---|---|
|
a = Object.new
|
||
|
def a.b; 2 end
|
||
|
c = a.clone
|
||
|
assert_equal(false, c.frozen?)
|
||
|
assert_equal(2, c.b)
|
||
|
c = a.clone(freeze: true)
|
||
|
assert_equal(true, c.frozen?)
|
||
|
assert_equal(2, c.b)
|
||
|
a.freeze
|
||
|
c = a.clone
|
||
|
assert_equal(true, c.frozen?)
|
||
- « Previous
- 1
- 2
- Next »