Make Module#prepend affect the iclasses of the module

3556a834a2 added support for
Module#include to affect the iclasses of the module.  It didn't add
support for Module#prepend because there were bugs in the object model
and GC at the time that prevented it.  Those problems have been
addressed in ad729a1d11 and
98286e9850, and now adding support for
it is straightforward and does not break any tests or specs.

Fixes [Bug #9573]
This commit is contained in:
Jeremy Evans 2020-06-03 12:14:49 -07:00
Родитель 750203c514
Коммит 41582d5866
2 изменённых файлов: 29 добавлений и 0 удалений

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

@ -1141,6 +1141,13 @@ rb_prepend_module(VALUE klass, VALUE module)
if (changed) {
rb_vm_check_redefinition_by_prepend(klass);
}
if (RB_TYPE_P(klass, T_MODULE)) {
rb_subclass_entry_t *iclass = RCLASS_EXT(klass)->subclasses;
while (iclass) {
include_modules_at(iclass->klass, iclass->klass, module, FALSE);
iclass = iclass->next;
}
}
}
/*

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

@ -587,6 +587,28 @@ class TestModule < Test::Unit::TestCase
m1.include m2
m1.include m3
assert_equal([:m1, :sc, :m2, :m3, :c], o.foo)
m1, m2, m3, sc, o = modules.call
assert_equal([:sc, :c], o.foo)
sc.prepend m1
assert_equal([:m1, :sc, :c], o.foo)
m1.prepend m2
assert_equal([:m2, :m1, :sc, :c], o.foo)
m2.prepend m3
assert_equal([:m3, :m2, :m1, :sc, :c], o.foo)
m1, m2, m3, sc, o = modules.call
sc.include m1
assert_equal([:sc, :m1, :c], o.foo)
sc.prepend m2
assert_equal([:m2, :sc, :m1, :c], o.foo)
sc.prepend m3
assert_equal([:m3, :m2, :sc, :m1, :c], o.foo)
m1, m2, m3, sc, o = modules.call
sc.include m1
assert_equal([:sc, :m1, :c], o.foo)
m2.prepend m3
m1.include m2
assert_equal([:sc, :m1, :m3, :m2, :c], o.foo)
end
def test_included_modules