ruby-changes:57855
From: Jeremy <ko1@a...>
Date: Sun, 22 Sep 2019 08:10:42 +0900 (JST)
Subject: [ruby-changes:57855] 7470f96565 (master): Fix Module#class_variables for singleton classes of classes/modules
https://git.ruby-lang.org/ruby.git/commit/?id=7470f96565 From 7470f965650bf17875632f0c5f9e5a4d9de9fc3f Mon Sep 17 00:00:00 2001 From: Jeremy Evans <code@j...> Date: Fri, 9 Aug 2019 16:44:43 -0700 Subject: Fix Module#class_variables for singleton classes of classes/modules Module#class_variables should reflect class variable lookup. For singleton classes of classes/modules, this means the lookup should be: * Singleton Class * Class * All Ancestors of Class Note that this doesn't include modules included in the singleton class, because class variable lookup doesn't include those. Singleton classes of other objects do not have this behavior and always just search all ancestors of the singleton class, so do not change the behavior for them. Fixes [Bug #8297] diff --git a/test/ruby/test_variable.rb b/test/ruby/test_variable.rb index aa301f2..f14b401 100644 --- a/test/ruby/test_variable.rb +++ b/test/ruby/test_variable.rb @@ -35,6 +35,34 @@ class TestVariable < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_variable.rb#L35 end end + def test_singleton_class_included_class_variable + c = Class.new + c.extend(Olympians) + assert_empty(c.singleton_class.class_variables) + assert_raise(NameError){ c.singleton_class.class_variable_get(:@@rule) } + c.class_variable_set(:@@foo, 1) + assert_equal([:@@foo], c.singleton_class.class_variables) + assert_equal(1, c.singleton_class.class_variable_get(:@@foo)) + + c = Class.new + c.extend(Olympians) + sc = Class.new(c) + assert_empty(sc.singleton_class.class_variables) + assert_raise(NameError){ sc.singleton_class.class_variable_get(:@@rule) } + c.class_variable_set(:@@foo, 1) + assert_equal([:@@foo], sc.singleton_class.class_variables) + assert_equal(1, sc.singleton_class.class_variable_get(:@@foo)) + + c = Class.new + o = c.new + o.extend(Olympians) + assert_equal([:@@rule], o.singleton_class.class_variables) + assert_equal("Zeus", o.singleton_class.class_variable_get(:@@rule)) + c.class_variable_set(:@@foo, 1) + assert_equal([:@@foo, :@@rule], o.singleton_class.class_variables.sort) + assert_equal(1, o.singleton_class.class_variable_get(:@@foo)) + end + def test_variable assert_instance_of(Integer, $$) diff --git a/variable.c b/variable.c index f3d73fa..1627467 100644 --- a/variable.c +++ b/variable.c @@ -3209,6 +3209,12 @@ static void* https://github.com/ruby/ruby/blob/trunk/variable.c#L3209 mod_cvar_of(VALUE mod, void *data) { VALUE tmp = mod; + if (FL_TEST(mod, FL_SINGLETON)) { + if (rb_namespace_p(rb_ivar_get(mod, id__attached__))) { + data = mod_cvar_at(tmp, data); + tmp = cvar_front_klass(tmp); + } + } for (;;) { data = mod_cvar_at(tmp, data); tmp = RCLASS_SUPER(tmp); -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/