Make attr* methods define public methods if self in caller is not same as receiver
Previously, attr* methods could be private even if not in the private section of a class/module block. This uses the same approach that ruby started using for define_method in 1fc33199736f316dd71d0c551edbf514528ddde6. Fixes [Bug #4537]
This commit is contained in:
parent
b8e351a1b9
commit
ef45a57801
@ -705,6 +705,32 @@ class TestModule < Test::Unit::TestCase
|
|||||||
assert_equal(false, o.respond_to?(:bar=))
|
assert_equal(false, o.respond_to?(:bar=))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_attr_public_at_toplevel
|
||||||
|
s = Object.new
|
||||||
|
TOPLEVEL_BINDING.eval(<<-END).call(s.singleton_class)
|
||||||
|
proc do |c|
|
||||||
|
c.send(:attr_accessor, :x)
|
||||||
|
c.send(:attr, :y)
|
||||||
|
c.send(:attr_reader, :z)
|
||||||
|
c.send(:attr_writer, :w)
|
||||||
|
end
|
||||||
|
END
|
||||||
|
assert_nil s.x
|
||||||
|
s.x = 1
|
||||||
|
assert_equal 1, s.x
|
||||||
|
|
||||||
|
assert_nil s.y
|
||||||
|
s.instance_variable_set(:@y, 2)
|
||||||
|
assert_equal 2, s.y
|
||||||
|
|
||||||
|
assert_nil s.z
|
||||||
|
s.instance_variable_set(:@z, 3)
|
||||||
|
assert_equal 3, s.z
|
||||||
|
|
||||||
|
s.w = 4
|
||||||
|
assert_equal 4, s.instance_variable_get(:@w)
|
||||||
|
end
|
||||||
|
|
||||||
def test_const_get_evaled
|
def test_const_get_evaled
|
||||||
c1 = Class.new
|
c1 = Class.new
|
||||||
c2 = Class.new(c1)
|
c2 = Class.new(c1)
|
||||||
|
2
vm.c
2
vm.c
@ -1383,7 +1383,7 @@ rb_vm_cref_in_context(VALUE self, VALUE cbase)
|
|||||||
const rb_execution_context_t *ec = GET_EC();
|
const rb_execution_context_t *ec = GET_EC();
|
||||||
const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
|
const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
|
||||||
const rb_cref_t *cref;
|
const rb_cref_t *cref;
|
||||||
if (cfp->self != self) return NULL;
|
if (!cfp || cfp->self != self) return NULL;
|
||||||
if (!vm_env_cref_by_cref(cfp->ep)) return NULL;
|
if (!vm_env_cref_by_cref(cfp->ep)) return NULL;
|
||||||
cref = vm_get_cref(cfp->ep);
|
cref = vm_get_cref(cfp->ep);
|
||||||
if (CREF_CLASS(cref) != cbase) return NULL;
|
if (CREF_CLASS(cref) != cbase) return NULL;
|
||||||
|
@ -1135,14 +1135,16 @@ rb_scope_module_func_set(void)
|
|||||||
vm_cref_set_visibility(METHOD_VISI_PRIVATE, TRUE);
|
vm_cref_set_visibility(METHOD_VISI_PRIVATE, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rb_cref_t *rb_vm_cref_in_context(VALUE self, VALUE cbase);
|
||||||
void
|
void
|
||||||
rb_attr(VALUE klass, ID id, int read, int write, int ex)
|
rb_attr(VALUE klass, ID id, int read, int write, int ex)
|
||||||
{
|
{
|
||||||
ID attriv;
|
ID attriv;
|
||||||
rb_method_visibility_t visi;
|
rb_method_visibility_t visi;
|
||||||
const rb_execution_context_t *ec = GET_EC();
|
const rb_execution_context_t *ec = GET_EC();
|
||||||
|
const rb_cref_t *cref = rb_vm_cref_in_context(klass, klass);
|
||||||
|
|
||||||
if (!ex) {
|
if (!ex || !cref) {
|
||||||
visi = METHOD_VISI_PUBLIC;
|
visi = METHOD_VISI_PUBLIC;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user