[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]