class.c: always clear tables first

* class.c (rb_mod_init_copy): always clear instance variable,
  constant and method tables first, regardless the source tables.
  [ruby-dev:48182] [Bug #9813]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2014-05-08 05:34:31 +00:00
Родитель 97cd982a3e
Коммит 7c072b35d1
3 изменённых файлов: 38 добавлений и 9 удалений

Просмотреть файл

@ -1,3 +1,9 @@
Thu May 8 14:34:29 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* class.c (rb_mod_init_copy): always clear instance variable,
constant and method tables first, regardless the source tables.
[ruby-dev:48182] [Bug #9813]
Thu May 8 10:53:14 2014 NARUSE, Yui <naruse@ruby-lang.org> Thu May 8 10:53:14 2014 NARUSE, Yui <naruse@ruby-lang.org>
* configure.in: OpenBSD needs to include sys/param.h before include * configure.in: OpenBSD needs to include sys/param.h before include

22
class.c
Просмотреть файл

@ -328,12 +328,21 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
} }
RCLASS_SET_SUPER(clone, RCLASS_SUPER(orig)); RCLASS_SET_SUPER(clone, RCLASS_SUPER(orig));
RCLASS_EXT(clone)->allocator = RCLASS_EXT(orig)->allocator; RCLASS_EXT(clone)->allocator = RCLASS_EXT(orig)->allocator;
if (RCLASS_IV_TBL(clone)) {
st_free_table(RCLASS_IV_TBL(clone));
RCLASS_IV_TBL(clone) = 0;
}
if (RCLASS_CONST_TBL(clone)) {
rb_free_const_table(RCLASS_CONST_TBL(clone));
RCLASS_CONST_TBL(clone) = 0;
}
if (RCLASS_M_TBL_WRAPPER(clone)) {
rb_free_m_tbl_wrapper(RCLASS_M_TBL_WRAPPER(clone));
RCLASS_M_TBL_WRAPPER(clone) = 0;
}
if (RCLASS_IV_TBL(orig)) { if (RCLASS_IV_TBL(orig)) {
st_data_t id; st_data_t id;
if (RCLASS_IV_TBL(clone)) {
st_free_table(RCLASS_IV_TBL(clone));
}
RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(orig)); RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(orig));
CONST_ID(id, "__tmp_classpath__"); CONST_ID(id, "__tmp_classpath__");
st_delete(RCLASS_IV_TBL(clone), &id, 0); st_delete(RCLASS_IV_TBL(clone), &id, 0);
@ -344,18 +353,13 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
} }
if (RCLASS_CONST_TBL(orig)) { if (RCLASS_CONST_TBL(orig)) {
struct clone_const_arg arg; struct clone_const_arg arg;
if (RCLASS_CONST_TBL(clone)) {
rb_free_const_table(RCLASS_CONST_TBL(clone));
}
RCLASS_CONST_TBL(clone) = st_init_numtable(); RCLASS_CONST_TBL(clone) = st_init_numtable();
arg.klass = clone; arg.klass = clone;
arg.tbl = RCLASS_CONST_TBL(clone); arg.tbl = RCLASS_CONST_TBL(clone);
st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)&arg); st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)&arg);
} }
if (RCLASS_M_TBL(orig)) { if (RCLASS_M_TBL(orig)) {
if (RCLASS_M_TBL_WRAPPER(clone)) {
rb_free_m_tbl_wrapper(RCLASS_M_TBL_WRAPPER(clone));
}
RCLASS_M_TBL_INIT(clone); RCLASS_M_TBL_INIT(clone);
st_foreach(RCLASS_M_TBL(orig), clone_method_i, (st_data_t)clone); st_foreach(RCLASS_M_TBL(orig), clone_method_i, (st_data_t)clone);
} }

Просмотреть файл

@ -375,6 +375,25 @@ class TestModule < Test::Unit::TestCase
assert_equal(:ok, Object.new.extend(m).foo, bug9535) assert_equal(:ok, Object.new.extend(m).foo, bug9535)
end end
def test_initialize_copy_empty
bug9813 = '[ruby-dev:48182] [Bug #9813]'
m = Module.new do
def x
end
const_set(:X, 1)
@x = 2
end
assert_equal([:x], m.instance_methods)
assert_equal([:@x], m.instance_variables)
assert_equal([:X], m.constants)
m.module_eval do
initialize_copy(Module.new)
end
assert_empty(m.instance_methods, bug9813)
assert_empty(m.instance_variables, bug9813)
assert_empty(m.constants, bug9813)
end
def test_dup def test_dup
bug6454 = '[ruby-core:45132]' bug6454 = '[ruby-core:45132]'