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

ruby-changes:65243

From: Jeremy <ko1@a...>
Date: Fri, 12 Feb 2021 00:46:15 +0900 (JST)
Subject: [ruby-changes:65243] 2d877327e1 (master): Make a cyclic prepend not modify ancestors for the receiver

https://git.ruby-lang.org/ruby.git/commit/?id=2d877327e1

From 2d877327e12f499ac1a0d7096f4314cc92ef228e Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Tue, 9 Feb 2021 15:39:34 -0800
Subject: Make a cyclic prepend not modify ancestors for the receiver

Check for cyclic prepend before making any changes.  This requires
scanning the module ancestor chain twice, but in general modules
do not have large numbers of ancestors.
---
 class.c                  | 14 ++++++++++++--
 test/ruby/test_module.rb |  7 +++++++
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/class.c b/class.c
index f97956c..12a67d1 100644
--- a/class.c
+++ b/class.c
@@ -1024,6 +1024,18 @@ include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super) https://github.com/ruby/ruby/blob/trunk/class.c#L1024
     struct rb_id_table *const klass_m_tbl = RCLASS_M_TBL(klass_origin);
     VALUE original_klass = klass;
 
+    if (klass_m_tbl) {
+        VALUE original_module = module;
+
+        while (module) {
+            if (klass_m_tbl == RCLASS_M_TBL(module))
+                return -1;
+            module = RCLASS_SUPER(module);
+        }
+
+        module = original_module;
+    }
+
     while (module) {
         int c_seen = FALSE;
 	int superclass_seen = FALSE;
@@ -1032,8 +1044,6 @@ include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super) https://github.com/ruby/ruby/blob/trunk/class.c#L1044
         if (klass == c) {
             c_seen = TRUE;
         }
-	if (klass_m_tbl && klass_m_tbl == RCLASS_M_TBL(module))
-	    return -1;
         if (klass_origin != c || search_super) {
             /* ignore if the module included already in superclasses for include,
              * ignore if the module included before origin class for prepend
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index 6b53b7d..0a5597f 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -478,6 +478,13 @@ class TestModule < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_module.rb#L478
     assert_raise(ArgumentError) { Module.new { include } }
   end
 
+  def test_prepend_self
+    m = Module.new
+    assert_equal([m], m.ancestors)
+    m.prepend(m) rescue nil
+    assert_equal([m], m.ancestors)
+  end
+
   def test_prepend_works_with_duped_classes
     m = Module.new
     a = Class.new do
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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