summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--class.c31
-rw-r--r--test/ruby/test_object.rb8
2 files changed, 35 insertions, 4 deletions
diff --git a/class.c b/class.c
index 0b24acd..051632e 100644
--- a/class.c
+++ b/class.c
@@ -1174,6 +1174,23 @@ method_entry_i(ID key, VALUE value, void *data)
return ID_TABLE_CONTINUE;
}
+static void
+add_instance_method_list(VALUE mod, struct method_entry_arg *me_arg)
+{
+ struct rb_id_table *m_tbl = RCLASS_M_TBL(mod);
+ if (!m_tbl) return;
+ rb_id_table_foreach(m_tbl, method_entry_i, me_arg);
+}
+
+static bool
+particular_class_p(VALUE mod)
+{
+ if (!mod) return false;
+ if (FL_TEST(mod, FL_SINGLETON)) return true;
+ if (BUILTIN_TYPE(mod) == T_ICLASS) return true;
+ return false;
+}
+
static VALUE
class_instance_method_list(int argc, const VALUE *argv, VALUE mod, int obj, int (*func) (st_data_t, st_data_t, st_data_t))
{
@@ -1183,17 +1200,23 @@ class_instance_method_list(int argc, const VALUE *argv, VALUE mod, int obj, int
if (rb_check_arity(argc, 0, 1)) recur = RTEST(argv[0]);
+ me_arg.list = st_init_numtable();
+ me_arg.recur = recur;
+
+ if (obj) {
+ for (; particular_class_p(mod); mod = RCLASS_SUPER(mod)) {
+ add_instance_method_list(mod, &me_arg);
+ }
+ }
+
if (!recur && RCLASS_ORIGIN(mod) != mod) {
mod = RCLASS_ORIGIN(mod);
prepended = 1;
}
- me_arg.list = st_init_numtable();
- me_arg.recur = recur;
for (; mod; mod = RCLASS_SUPER(mod)) {
- if (RCLASS_M_TBL(mod)) rb_id_table_foreach(RCLASS_M_TBL(mod), method_entry_i, &me_arg);
+ add_instance_method_list(mod, &me_arg);
if (BUILTIN_TYPE(mod) == T_ICLASS && !prepended) continue;
- if (obj && FL_TEST(mod, FL_SINGLETON)) continue;
if (!recur) break;
}
ary = rb_ary_new();
diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb
index 0d31eb3..277995b 100644
--- a/test/ruby/test_object.rb
+++ b/test/ruby/test_object.rb
@@ -227,6 +227,14 @@ class TestObject < Test::Unit::TestCase
assert_equal([:foo], o.methods(false), bug8044)
end
+ def test_methods_prepend_singleton
+ c = Class.new(Module) {private def foo; end}
+ k = c.new
+ k.singleton_class
+ c.module_eval {prepend(Module.new)}
+ assert_equal([:foo], k.private_methods(false))
+ end
+
def test_instance_variable_get
o = Object.new
o.instance_eval { @foo = :foo }