mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
[Bug #21094] Update nested module names when setting temporary name
[Backport #21094]
This commit is contained in:
parent
8b491169c3
commit
5b3970f68b
3 changed files with 103 additions and 2 deletions
|
@ -64,5 +64,19 @@ ruby_version_is "3.3" do
|
||||||
m::M = m::N
|
m::M = m::N
|
||||||
m::M.name.should =~ /\A#<Module:0x\h+>::M\z/m
|
m::M.name.should =~ /\A#<Module:0x\h+>::M\z/m
|
||||||
end
|
end
|
||||||
|
|
||||||
|
ruby_bug "#21094", ""..."3.5" do
|
||||||
|
it "also updates a name of a nested module" do
|
||||||
|
m = Module.new
|
||||||
|
m::N = Module.new
|
||||||
|
m::N.name.should =~ /\A#<Module:0x\h+>::N\z/
|
||||||
|
|
||||||
|
m.set_temporary_name "m"
|
||||||
|
m::N.name.should == "m::N"
|
||||||
|
|
||||||
|
m.set_temporary_name nil
|
||||||
|
m::N.name.should == nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3379,13 +3379,22 @@ class TestModule < Test::Unit::TestCase
|
||||||
m::N.set_temporary_name(nil)
|
m::N.set_temporary_name(nil)
|
||||||
assert_nil(m::N.name)
|
assert_nil(m::N.name)
|
||||||
|
|
||||||
|
m::N.const_set(:O, Module.new)
|
||||||
|
m.const_set(:Recursive, m)
|
||||||
|
m::N.const_set(:Recursive, m)
|
||||||
|
m.const_set(:A, 42)
|
||||||
|
|
||||||
m.set_temporary_name(name = "fake_name")
|
m.set_temporary_name(name = "fake_name")
|
||||||
name.upcase!
|
name.upcase!
|
||||||
assert_equal("fake_name", m.name)
|
assert_equal("fake_name", m.name)
|
||||||
assert_raise(FrozenError) {m.name.upcase!}
|
assert_raise(FrozenError) {m.name.upcase!}
|
||||||
|
assert_equal("fake_name::N", m::N.name)
|
||||||
|
assert_equal("fake_name::N::O", m::N::O.name)
|
||||||
|
|
||||||
m.set_temporary_name(nil)
|
m.set_temporary_name(nil)
|
||||||
assert_nil m.name
|
assert_nil m.name
|
||||||
|
assert_nil m::N.name
|
||||||
|
assert_nil m::N::O.name
|
||||||
|
|
||||||
assert_raise_with_message(ArgumentError, "empty class/module name") do
|
assert_raise_with_message(ArgumentError, "empty class/module name") do
|
||||||
m.set_temporary_name("")
|
m.set_temporary_name("")
|
||||||
|
|
82
variable.c
82
variable.c
|
@ -166,6 +166,80 @@ is_constant_path(VALUE name)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct sub_temporary_name_args {
|
||||||
|
VALUE names;
|
||||||
|
ID last;
|
||||||
|
};
|
||||||
|
|
||||||
|
static VALUE build_const_path(VALUE head, ID tail);
|
||||||
|
static void set_sub_temporary_name_foreach(VALUE mod, struct sub_temporary_name_args *args, VALUE name);
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
set_sub_temporary_name_recursive(VALUE mod, VALUE data, int recursive)
|
||||||
|
{
|
||||||
|
if (recursive) return Qfalse;
|
||||||
|
|
||||||
|
struct sub_temporary_name_args *args = (void *)data;
|
||||||
|
VALUE name = 0;
|
||||||
|
if (args->names) {
|
||||||
|
name = build_const_path(rb_ary_last(0, 0, args->names), args->last);
|
||||||
|
}
|
||||||
|
set_sub_temporary_name_foreach(mod, args, name);
|
||||||
|
return Qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
set_sub_temporary_name_topmost(VALUE mod, VALUE data, int recursive)
|
||||||
|
{
|
||||||
|
if (recursive) return Qfalse;
|
||||||
|
|
||||||
|
struct sub_temporary_name_args *args = (void *)data;
|
||||||
|
VALUE name = args->names;
|
||||||
|
if (name) {
|
||||||
|
args->names = rb_ary_hidden_new(0);
|
||||||
|
}
|
||||||
|
set_sub_temporary_name_foreach(mod, args, name);
|
||||||
|
return Qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum rb_id_table_iterator_result
|
||||||
|
set_sub_temporary_name_i(ID id, VALUE val, void *data)
|
||||||
|
{
|
||||||
|
val = ((rb_const_entry_t *)val)->value;
|
||||||
|
if (rb_namespace_p(val) && !RCLASS_EXT(val)->permanent_classpath) {
|
||||||
|
VALUE arg = (VALUE)data;
|
||||||
|
struct sub_temporary_name_args *args = data;
|
||||||
|
args->last = id;
|
||||||
|
rb_exec_recursive_paired(set_sub_temporary_name_recursive, val, arg, arg);
|
||||||
|
}
|
||||||
|
return ID_TABLE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_sub_temporary_name_foreach(VALUE mod, struct sub_temporary_name_args *args, VALUE name)
|
||||||
|
{
|
||||||
|
RCLASS_SET_CLASSPATH(mod, name, FALSE);
|
||||||
|
struct rb_id_table *tbl = RCLASS_CONST_TBL(mod);
|
||||||
|
if (!tbl) return;
|
||||||
|
if (!name) {
|
||||||
|
rb_id_table_foreach(tbl, set_sub_temporary_name_i, args);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
long names_len = RARRAY_LEN(args->names); // paranoiac check?
|
||||||
|
rb_ary_push(args->names, name);
|
||||||
|
rb_id_table_foreach(tbl, set_sub_temporary_name_i, args);
|
||||||
|
rb_ary_set_len(args->names, names_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_sub_temporary_name(VALUE mod, VALUE name)
|
||||||
|
{
|
||||||
|
struct sub_temporary_name_args args = {name};
|
||||||
|
VALUE arg = (VALUE)&args;
|
||||||
|
rb_exec_recursive_paired(set_sub_temporary_name_topmost, mod, arg, arg);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* mod.set_temporary_name(string) -> self
|
* mod.set_temporary_name(string) -> self
|
||||||
|
@ -224,7 +298,9 @@ rb_mod_set_temporary_name(VALUE mod, VALUE name)
|
||||||
|
|
||||||
if (NIL_P(name)) {
|
if (NIL_P(name)) {
|
||||||
// Set the temporary classpath to NULL (anonymous):
|
// Set the temporary classpath to NULL (anonymous):
|
||||||
RCLASS_SET_CLASSPATH(mod, 0, FALSE);
|
RB_VM_LOCK_ENTER();
|
||||||
|
set_sub_temporary_name(mod, 0);
|
||||||
|
RB_VM_LOCK_LEAVE();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Ensure the name is a string:
|
// Ensure the name is a string:
|
||||||
|
@ -241,7 +317,9 @@ rb_mod_set_temporary_name(VALUE mod, VALUE name)
|
||||||
name = rb_str_new_frozen(name);
|
name = rb_str_new_frozen(name);
|
||||||
|
|
||||||
// Set the temporary classpath to the given name:
|
// Set the temporary classpath to the given name:
|
||||||
RCLASS_SET_CLASSPATH(mod, name, FALSE);
|
RB_VM_LOCK_ENTER();
|
||||||
|
set_sub_temporary_name(mod, name);
|
||||||
|
RB_VM_LOCK_LEAVE();
|
||||||
}
|
}
|
||||||
|
|
||||||
return mod;
|
return mod;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue