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 »