Module#remove_method: Check frozen on the right object
Previously, the frozen check happened on `RCLASS_ORIGIN(self)`, which can return an iclass. The frozen check is supposed to respond to objects that users can call methods on while iclasses are hidden from users. Other mutation methods like Module#{define_method,alias_method,public} don't do this. Check frozen status on the module itself. Fixes [Bug #19164] and [Bug #19166]. Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
This commit is contained in:
parent
9da2a5204f
commit
3d272b0fc8
Notes:
git
2022-12-01 22:33:02 +00:00
Merged: https://github.com/ruby/ruby/pull/6842 Merged-By: XrXr
@ -809,4 +809,13 @@ PREP
|
||||
3_000_000.times(&code)
|
||||
CODE
|
||||
end
|
||||
|
||||
def test_instance_freeze_dont_freeze_the_class_bug_19164
|
||||
klass = Class.new
|
||||
klass.prepend(Module.new)
|
||||
|
||||
klass.new.freeze
|
||||
klass.define_method(:bar) {}
|
||||
assert_equal klass, klass.remove_method(:bar), '[Bug #19164]'
|
||||
end
|
||||
end
|
||||
|
@ -2350,6 +2350,18 @@ class TestModule < Test::Unit::TestCase
|
||||
assert_equal(:foo, removed)
|
||||
end
|
||||
|
||||
def test_frozen_prepend_remove_method
|
||||
[Module, Class].each do |klass|
|
||||
mod = klass.new do
|
||||
prepend(Module.new)
|
||||
def foo; end
|
||||
end
|
||||
mod.freeze
|
||||
assert_raise(FrozenError, '[Bug #19166]') { mod.send(:remove_method, :foo) }
|
||||
assert_equal([:foo], mod.instance_methods(false))
|
||||
end
|
||||
end
|
||||
|
||||
def test_prepend_class_ancestors
|
||||
bug6658 = '[ruby-core:45919]'
|
||||
m = labeled_module("m")
|
||||
|
@ -1541,8 +1541,8 @@ remove_method(VALUE klass, ID mid)
|
||||
rb_method_entry_t *me = 0;
|
||||
VALUE self = klass;
|
||||
|
||||
klass = RCLASS_ORIGIN(klass);
|
||||
rb_class_modify_check(klass);
|
||||
klass = RCLASS_ORIGIN(klass);
|
||||
if (mid == object_id || mid == id__send__ || mid == idInitialize) {
|
||||
rb_warn("removing `%s' may cause serious problems", rb_id2name(mid));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user