Make Module#prepend affect the iclasses of the module

3556a834a2847e52162d1d3302d4c64390df1694 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 ad729a1d11c6c57efd2e92803b4e937db0f75252 and
98286e9850936e27e8ae5e4f20858cc9c13d2dde, 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
parent 750203c514
commit 41582d5866
Notes: git 2020-06-19 00:19:04 +09:00
2 changed files with 29 additions and 0 deletions

View File

@ -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;
}
}
}
/*

View File

@ -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