Bug #9573 » prepend-future-ancestors-9573.patch
class.c | ||
---|---|---|
RCLASS_M_TBL(OBJ_WB_UNPROTECT(klass)) =
|
||
RCLASS_M_TBL(OBJ_WB_UNPROTECT(module)); /* TODO: unprotected? */
|
||
RCLASS_SET_ORIGIN(klass, module == RCLASS_ORIGIN(module) ? klass : RCLASS_ORIGIN(module));
|
||
RCLASS_SET_ORIGIN(klass, klass);
|
||
if (BUILTIN_TYPE(module) == T_ICLASS) {
|
||
module = RBASIC(module)->klass;
|
||
}
|
||
... | ... | |
static void ensure_origin(VALUE klass);
|
||
struct origin_stack {
|
||
VALUE iclass;
|
||
VALUE origin_module;
|
||
struct origin_stack* next;
|
||
};
|
||
static int
|
||
include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super)
|
||
{
|
||
VALUE p, iclass;
|
||
int method_changed = 0, constant_changed = 0;
|
||
VALUE p, iclass, orig_iclass;
|
||
struct origin_stack* orig_stack = NULL;
|
||
struct origin_stack* tmp_stack = NULL;
|
||
int method_changed = 0, constant_changed = 0, add_subclass;
|
||
struct rb_id_table *const klass_m_tbl = RCLASS_M_TBL(RCLASS_ORIGIN(klass));
|
||
if (FL_TEST(module, RCLASS_REFINED_BY_ANY)) {
|
||
ensure_origin(module);
|
||
}
|
||
ensure_origin(module);
|
||
while (module) {
|
||
int superclass_seen = FALSE;
|
||
... | ... | |
iclass = rb_include_class_new(module, RCLASS_SUPER(c));
|
||
c = RCLASS_SET_SUPER(c, iclass);
|
||
RCLASS_SET_INCLUDER(iclass, klass);
|
||
add_subclass = TRUE;
|
||
if (module != RCLASS_ORIGIN(module)) {
|
||
tmp_stack = orig_stack;
|
||
orig_stack = malloc(sizeof(struct origin_stack));
|
||
orig_stack->iclass = iclass;
|
||
orig_stack->origin_module = RCLASS_ORIGIN(module);
|
||
orig_stack->next = tmp_stack;
|
||
}
|
||
else if (orig_stack && orig_stack->origin_module == module)
|
||
{
|
||
RCLASS_SET_ORIGIN(orig_stack->iclass, iclass);
|
||
tmp_stack = orig_stack;
|
||
orig_stack = orig_stack->next;
|
||
free(tmp_stack);
|
||
add_subclass = FALSE;
|
||
}
|
||
{
|
||
VALUE m = module;
|
||
if (BUILTIN_TYPE(m) == T_ICLASS) m = RBASIC(m)->klass;
|
||
rb_module_add_to_subclasses_list(m, iclass);
|
||
if (add_subclass) rb_module_add_to_subclasses_list(m, iclass);
|
||
}
|
||
if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
|
||
... | ... | |
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;
|
||
}
|
||
}
|
||
}
|
||
/*
|
||
... | ... | |
VALUE origin = RCLASS_ORIGIN(mod);
|
||
for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
|
||
if (p != origin && BUILTIN_TYPE(p) == T_ICLASS) {
|
||
if (p != origin && BUILTIN_TYPE(p) == T_ICLASS && !FL_TEST(p, RICLASS_IS_ORIGIN)) {
|
||
VALUE m = RBASIC(p)->klass;
|
||
if (RB_TYPE_P(m, T_MODULE))
|
||
rb_ary_push(ary, m);
|
||
... | ... | |
Check_Type(mod2, T_MODULE);
|
||
for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
|
||
if (BUILTIN_TYPE(p) == T_ICLASS) {
|
||
if (BUILTIN_TYPE(p) == T_ICLASS && !FL_TEST(p, RICLASS_IS_ORIGIN)) {
|
||
if (RBASIC(p)->klass == mod2) return Qtrue;
|
||
}
|
||
}
|
gc.c | ||
---|---|---|
break;
|
||
case T_ICLASS:
|
||
/* Basically , T_ICLASS shares table with the module */
|
||
if (FL_TEST(obj, RICLASS_IS_ORIGIN)) {
|
||
rb_id_table_free(RCLASS_M_TBL(obj));
|
||
}
|
||
if (RCLASS_CALLABLE_M_TBL(obj) != NULL) {
|
||
rb_id_table_free(RCLASS_CALLABLE_M_TBL(obj));
|
||
}
|
test/ruby/test_module.rb | ||
---|---|---|
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
|
- « Previous
- 1
- 2
- Next »