Trigger inherited
and const_set
callbacks after const has been defined
[Misc #21143] [Bug #21193] The previous change caused a backward compatibility issue with code that called `Object.const_source_location` from the `inherited` callback. To fix this, the order is now: - Define the constant - Invoke `inherited` - Invoke `const_set`
This commit is contained in:
parent
a51364f54b
commit
de097fbe5f
Notes:
git
2025-03-20 17:18:28 +00:00
7
class.c
7
class.c
@ -1004,8 +1004,9 @@ rb_define_class(const char *name, VALUE super)
|
||||
}
|
||||
klass = rb_define_class_id(id, super);
|
||||
rb_vm_register_global_object(klass);
|
||||
rb_const_set_raw(rb_cObject, id, klass);
|
||||
rb_class_inherited(super, klass);
|
||||
rb_const_set(rb_cObject, id, klass);
|
||||
rb_const_added(klass, id);
|
||||
|
||||
return klass;
|
||||
}
|
||||
@ -1043,8 +1044,10 @@ rb_define_class_id_under_no_pin(VALUE outer, ID id, VALUE super)
|
||||
}
|
||||
klass = rb_define_class_id(id, super);
|
||||
rb_set_class_path_string(klass, outer, rb_id2str(id));
|
||||
|
||||
rb_const_set_raw(outer, id, klass);
|
||||
rb_class_inherited(super, klass);
|
||||
rb_const_set(outer, id, klass);
|
||||
rb_const_added(outer, id);
|
||||
|
||||
return klass;
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "shape.h" /* for rb_shape_t */
|
||||
|
||||
/* variable.c */
|
||||
void rb_const_added(VALUE klass, ID const_name);
|
||||
void rb_const_set_raw(VALUE klass, ID id, VALUE val);
|
||||
void rb_gc_mark_global_tbl(void);
|
||||
void rb_gc_update_global_tbl(void);
|
||||
size_t rb_generic_ivar_memsize(VALUE);
|
||||
|
@ -3,7 +3,12 @@ module CoreClassSpecs
|
||||
class Base
|
||||
def self.inherited(subclass)
|
||||
subclass.const_set(:INHERITED_NAME, subclass.name)
|
||||
ORDER << [:inherited, subclass, eval("defined?(#{subclass.name})")]
|
||||
ORDER << [
|
||||
:inherited,
|
||||
subclass,
|
||||
eval("defined?(#{subclass.name})"),
|
||||
Object.const_source_location(subclass.name) ? :location : :unknown_location,
|
||||
]
|
||||
super
|
||||
end
|
||||
end
|
||||
@ -11,7 +16,12 @@ module CoreClassSpecs
|
||||
ORDER = []
|
||||
|
||||
def self.const_added(const_name)
|
||||
ORDER << [:const_added, const_name, eval("defined?(#{const_name})")]
|
||||
ORDER << [
|
||||
:const_added,
|
||||
const_name,
|
||||
eval("defined?(#{const_name})"),
|
||||
const_source_location(const_name) ? :location : :unknown_location,
|
||||
]
|
||||
super
|
||||
end
|
||||
|
||||
|
@ -106,8 +106,8 @@ describe "Class.inherited" do
|
||||
ruby_version_is "3.5" do # https://bugs.ruby-lang.org/issues/21143
|
||||
it "is invoked before `const_added`" do
|
||||
CoreClassSpecs::Callbacks::ORDER.should == [
|
||||
[:inherited, CoreClassSpecs::Callbacks::Child, nil],
|
||||
[:const_added, :Child, "constant"],
|
||||
[:inherited, CoreClassSpecs::Callbacks::Child, "constant", :location],
|
||||
[:const_added, :Child, "constant", :location],
|
||||
]
|
||||
end
|
||||
end
|
||||
|
@ -389,8 +389,8 @@ describe "C-API Class function" do
|
||||
ScratchPad.record([])
|
||||
@s.rb_define_class_id_under(CApiClassSpecs::Callbacks, :Subclass, CApiClassSpecs::Callbacks)
|
||||
ScratchPad.recorded.should == [
|
||||
[:inherited, "CApiClassSpecs::Callbacks::Subclass"],
|
||||
[:const_added, :Subclass],
|
||||
[:inherited, "CApiClassSpecs::Callbacks::Subclass", :location],
|
||||
[:const_added, :Subclass, :location],
|
||||
]
|
||||
end
|
||||
end
|
||||
|
@ -104,11 +104,11 @@ class CApiClassSpecs
|
||||
|
||||
class Callbacks
|
||||
def self.inherited(child)
|
||||
ScratchPad << [:inherited, child.name]
|
||||
ScratchPad << [:inherited, child.name, Object.const_source_location(child.name) ? :location : :unknown_location]
|
||||
end
|
||||
|
||||
def self.const_added(const_name)
|
||||
ScratchPad << [:const_added, const_name]
|
||||
ScratchPad << [:const_added, const_name, const_source_location(const_name) ? :location : :unknown_location]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
15
variable.c
15
variable.c
@ -2624,7 +2624,6 @@ rb_autoload(VALUE module, ID name, const char *feature)
|
||||
}
|
||||
|
||||
static void const_set(VALUE klass, ID id, VALUE val);
|
||||
static void const_added(VALUE klass, ID const_name);
|
||||
|
||||
struct autoload_arguments {
|
||||
VALUE module;
|
||||
@ -2733,7 +2732,7 @@ rb_autoload_str(VALUE module, ID name, VALUE feature)
|
||||
VALUE result = rb_mutex_synchronize(autoload_mutex, autoload_synchronized, (VALUE)&arguments);
|
||||
|
||||
if (result == Qtrue) {
|
||||
const_added(module, name);
|
||||
rb_const_added(module, name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3604,8 +3603,8 @@ set_namespace_path(VALUE named_namespace, VALUE namespace_path)
|
||||
RB_VM_LOCK_LEAVE();
|
||||
}
|
||||
|
||||
static void
|
||||
const_added(VALUE klass, ID const_name)
|
||||
void
|
||||
rb_const_added(VALUE klass, ID const_name)
|
||||
{
|
||||
if (GET_VM()->running) {
|
||||
VALUE name = ID2SYM(const_name);
|
||||
@ -3680,11 +3679,17 @@ const_set(VALUE klass, ID id, VALUE val)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rb_const_set_raw(VALUE klass, ID id, VALUE val)
|
||||
{
|
||||
const_set(klass, id, val);
|
||||
}
|
||||
|
||||
void
|
||||
rb_const_set(VALUE klass, ID id, VALUE val)
|
||||
{
|
||||
const_set(klass, id, val);
|
||||
const_added(klass, id);
|
||||
rb_const_added(klass, id);
|
||||
}
|
||||
|
||||
static struct autoload_data *
|
||||
|
@ -5752,8 +5752,9 @@ vm_declare_class(ID id, rb_num_t flags, VALUE cbase, VALUE super)
|
||||
VALUE c = rb_define_class_id(id, s);
|
||||
rb_define_alloc_func(c, rb_get_alloc_func(c));
|
||||
rb_set_class_path_string(c, cbase, rb_id2str(id));
|
||||
rb_const_set_raw(cbase, id, c);
|
||||
rb_class_inherited(s, c);
|
||||
rb_const_set(cbase, id, c);
|
||||
rb_const_added(cbase, id);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user