diff --git a/ChangeLog b/ChangeLog index 87c467fa0b..f76aafa2a4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Sun Mar 31 17:17:56 2013 Nobuyoshi Nakada + + * proc.c (rb_mod_define_method): consider visibility in define_method. + patch by mashiro . fix GH-268. + Sun Mar 31 15:40:30 2013 Nobuyoshi Nakada * win32/configure.bat: try to fix option arguments split by commas and diff --git a/proc.c b/proc.c index fe1bbff00d..4596003daf 100644 --- a/proc.c +++ b/proc.c @@ -1377,7 +1377,7 @@ rb_mod_define_method(int argc, VALUE *argv, VALUE mod) { ID id; VALUE body; - int noex = NOEX_PUBLIC; + int noex = (int)rb_vm_cref()->nd_visi; if (argc == 1) { id = rb_to_id(argv[0]); @@ -1410,6 +1410,9 @@ rb_mod_define_method(int argc, VALUE *argv, VALUE mod) } } rb_method_entry_set(mod, id, method->me, noex); + if (noex == NOEX_MODFUNC) { + rb_method_entry_set(rb_singleton_class(mod), id, method->me, NOEX_PUBLIC); + } } else if (rb_obj_is_proc(body)) { rb_proc_t *proc; @@ -1423,6 +1426,9 @@ rb_mod_define_method(int argc, VALUE *argv, VALUE mod) proc->block.klass = mod; } rb_add_method(mod, id, VM_METHOD_TYPE_BMETHOD, (void *)body, noex); + if (noex == NOEX_MODFUNC) { + rb_add_method(rb_singleton_class(mod), id, VM_METHOD_TYPE_BMETHOD, (void *)body, NOEX_PUBLIC); + } } else { /* type error */ diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb index c1dbd9f35f..655fac5d3b 100644 --- a/test/ruby/test_method.rb +++ b/test/ruby/test_method.rb @@ -270,6 +270,38 @@ class TestMethod < Test::Unit::TestCase assert_equal(:meth, c.new.meth, feature4254) end + def test_define_method_visibility + c = Class.new do + public + define_method(:foo) {:foo} + protected + define_method(:bar) {:bar} + private + define_method(:baz) {:baz} + end + + assert_equal(true, c.public_method_defined?(:foo)) + assert_equal(false, c.public_method_defined?(:bar)) + assert_equal(false, c.public_method_defined?(:baz)) + + assert_equal(false, c.protected_method_defined?(:foo)) + assert_equal(true, c.protected_method_defined?(:bar)) + assert_equal(false, c.protected_method_defined?(:baz)) + + assert_equal(false, c.private_method_defined?(:foo)) + assert_equal(false, c.private_method_defined?(:bar)) + assert_equal(true, c.private_method_defined?(:baz)) + + m = Module.new do + module_function + define_method(:foo) {:foo} + end + assert_equal(true, m.respond_to?(:foo)) + assert_equal(false, m.public_method_defined?(:foo)) + assert_equal(false, m.protected_method_defined?(:foo)) + assert_equal(true, m.private_method_defined?(:foo)) + end + def test_super_in_proc_from_define_method c1 = Class.new { def m