mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	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 1fc3319973.
Fixes [Bug #4537]
			
			
This commit is contained in:
		
							parent
							
								
									b8e351a1b9
								
							
						
					
					
						commit
						ef45a57801
					
				
					 3 changed files with 30 additions and 2 deletions
				
			
		| 
						 | 
				
			
			@ -705,6 +705,32 @@ class TestModule < Test::Unit::TestCase
 | 
			
		|||
    assert_equal(false, o.respond_to?(:bar=))
 | 
			
		||||
  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
 | 
			
		||||
    c1 = Class.new
 | 
			
		||||
    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_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
 | 
			
		||||
    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;
 | 
			
		||||
    cref = vm_get_cref(cfp->ep);
 | 
			
		||||
    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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const rb_cref_t *rb_vm_cref_in_context(VALUE self, VALUE cbase);
 | 
			
		||||
void
 | 
			
		||||
rb_attr(VALUE klass, ID id, int read, int write, int ex)
 | 
			
		||||
{
 | 
			
		||||
    ID attriv;
 | 
			
		||||
    rb_method_visibility_t visi;
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue