summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2019-12-20 19:23:13 +0900
committerGitHub <[email protected]>2019-12-20 19:23:13 +0900
commit64e9f278b3c3acf3a512891a3447f68d37b252dc (patch)
treefecbdf71993835edb76120c6391890ab12d85bf9
parent87809742f57fc78be9c17a0d5943dd12440a90db (diff)
parent184ad732df68a63d7f864b051b931e88259ce38f (diff)
downloadmruby-64e9f278b3c3acf3a512891a3447f68d37b252dc.tar.gz
mruby-64e9f278b3c3acf3a512891a3447f68d37b252dc.zip
Merge pull request #4874 from dearblue/method-list
Fix for `#methods` to include methods that were `undef`
-rw-r--r--mrbgems/mruby-metaprog/src/metaprog.c33
1 files changed, 22 insertions, 11 deletions
diff --git a/mrbgems/mruby-metaprog/src/metaprog.c b/mrbgems/mruby-metaprog/src/metaprog.c
index bca8ab34c..f00c4493b 100644
--- a/mrbgems/mruby-metaprog/src/metaprog.c
+++ b/mrbgems/mruby-metaprog/src/metaprog.c
@@ -172,7 +172,7 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
KHASH_DECLARE(st, mrb_sym, char, FALSE)
static void
-method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set)
+method_entry_loop(mrb_state *mrb, struct RClass *klass, khash_t(st) *set, khash_t(st) *undef)
{
khint_t i;
@@ -181,20 +181,28 @@ method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set)
for (i=0;i<kh_end(h);i++) {
if (kh_exist(h, i)) {
mrb_method_t m = kh_value(h, i);
- if (MRB_METHOD_UNDEF_P(m)) continue;
- kh_put(st, mrb, set, kh_key(h, i));
+ if (MRB_METHOD_UNDEF_P(m)) {
+ if (undef) {
+ kh_put(st, mrb, undef, kh_key(h, i));
+ }
+ }
+ else if (undef == NULL ||
+ kh_get(st, mrb, undef, kh_key(h, i)) == kh_end(undef)) {
+ kh_put(st, mrb, set, kh_key(h, i));
+ }
}
}
}
static mrb_value
-mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass, int obj)
+mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass *klass, int obj)
{
khint_t i;
mrb_value ary;
mrb_bool prepended = FALSE;
- struct RClass* oldklass;
- khash_t(st)* set = kh_init(st, mrb);
+ struct RClass *oldklass;
+ khash_t(st) *set = kh_init(st, mrb);
+ khash_t(st) *undef = (recur ? kh_init(st, mrb) : NULL);
if (!recur && (klass->flags & MRB_FL_CLASS_IS_PREPENDED)) {
MRB_CLASS_ORIGIN(klass);
@@ -203,7 +211,7 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* kl
oldklass = 0;
while (klass && (klass != oldklass)) {
- method_entry_loop(mrb, klass, set);
+ method_entry_loop(mrb, klass, set, undef);
if ((klass->tt == MRB_TT_ICLASS && !prepended) ||
(klass->tt == MRB_TT_SCLASS)) {
}
@@ -221,6 +229,7 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* kl
}
}
kh_destroy(st, mrb, set);
+ if (undef) kh_destroy(st, mrb, undef);
return ary;
}
@@ -313,18 +322,19 @@ mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
{
khint_t i;
mrb_value ary;
- struct RClass* klass;
- khash_t(st)* set = kh_init(st, mrb);
+ struct RClass *klass;
+ khash_t(st) *set = kh_init(st, mrb);
+ khash_t(st) *undef = (recur ? kh_init(st, mrb) : NULL);
klass = mrb_class(mrb, obj);
if (klass && (klass->tt == MRB_TT_SCLASS)) {
- method_entry_loop(mrb, klass, set);
+ method_entry_loop(mrb, klass, set, undef);
klass = klass->super;
}
if (recur) {
while (klass && ((klass->tt == MRB_TT_SCLASS) || (klass->tt == MRB_TT_ICLASS))) {
- method_entry_loop(mrb, klass, set);
+ method_entry_loop(mrb, klass, set, undef);
klass = klass->super;
}
}
@@ -336,6 +346,7 @@ mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
}
}
kh_destroy(st, mrb, set);
+ if (undef) kh_destroy(st, mrb, undef);
return ary;
}