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

ruby-changes:59056

From: Jeremy <ko1@a...>
Date: Wed, 4 Dec 2019 00:32:06 +0900 (JST)
Subject: [ruby-changes:59056] 47c97e1e84 (master): Do not lose existing constant visibility when autoloading

https://git.ruby-lang.org/ruby.git/commit/?id=47c97e1e84

From 47c97e1e843159c3c4d57f8c5e22daea57c3ffe1 Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Sun, 11 Aug 2019 20:53:37 -0700
Subject: Do not lose existing constant visibility when autoloading

This copies the private/deprecate constant visibility across the
autoload.  It still is backwards compatible with setting the
private/deprecate constant visibility in the autoloaded file.
However, if you explicitly set public constant in the autoloaded
file, that will be reset after the autoload.

Fixes [Bug #11055]

diff --git a/test/ruby/test_autoload.rb b/test/ruby/test_autoload.rb
index 53510e8..e9e13ee 100644
--- a/test/ruby/test_autoload.rb
+++ b/test/ruby/test_autoload.rb
@@ -295,6 +295,66 @@ p Foo::Bar https://github.com/ruby/ruby/blob/trunk/test/ruby/test_autoload.rb#L295
     end
   end
 
+  def test_autoload_private_constant_before_autoload
+    Dir.mktmpdir('autoload') do |tmpdir|
+      File.write(tmpdir+"/zzz.rb", "#{<<~"begin;"}\n#{<<~'end;'}")
+      begin;
+        class AutoloadTest
+          ZZZ = :ZZZ
+        end
+      end;
+      assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-'end;'}")
+      bug = '[Bug #11055]'
+      begin;
+        class AutoloadTest
+          autoload :ZZZ, "zzz.rb"
+          private_constant :ZZZ
+          ZZZ
+        end
+        assert_raise(NameError, bug) {AutoloadTest::ZZZ}
+      end;
+      assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-'end;'}")
+      bug = '[Bug #11055]'
+      begin;
+        class AutoloadTest
+          autoload :ZZZ, "zzz.rb"
+          private_constant :ZZZ
+        end
+        assert_raise(NameError, bug) {AutoloadTest::ZZZ}
+      end;
+    end
+  end
+
+  def test_autoload_deprecate_constant_before_autoload
+    Dir.mktmpdir('autoload') do |tmpdir|
+      File.write(tmpdir+"/zzz.rb", "#{<<~"begin;"}\n#{<<~'end;'}")
+      begin;
+        class AutoloadTest
+          ZZZ = :ZZZ
+        end
+      end;
+      assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-'end;'}")
+      bug = '[Bug #11055]'
+      begin;
+        class AutoloadTest
+          autoload :ZZZ, "zzz.rb"
+          deprecate_constant :ZZZ
+        end
+        assert_warning(/ZZZ is deprecated/, bug) {class AutoloadTest; ZZZ; end}
+        assert_warning(/ZZZ is deprecated/, bug) {AutoloadTest::ZZZ}
+      end;
+      assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-'end;'}")
+      bug = '[Bug #11055]'
+      begin;
+        class AutoloadTest
+          autoload :ZZZ, "zzz.rb"
+          deprecate_constant :ZZZ
+        end
+        assert_warning(/ZZZ is deprecated/, bug) {AutoloadTest::ZZZ}
+      end;
+    end
+  end
+
   def test_autoload_fork
     EnvUtil.default_warning do
       Tempfile.create(['autoload', '.rb']) {|file|
diff --git a/variable.c b/variable.c
index 9c50b75..74c4472 100644
--- a/variable.c
+++ b/variable.c
@@ -2226,6 +2226,8 @@ rb_autoload_load(VALUE mod, ID id) https://github.com/ruby/ruby/blob/trunk/variable.c#L2226
     struct autoload_data_i *ele;
     struct autoload_const *ac;
     struct autoload_state state;
+    int flag = -1;
+    rb_const_entry_t *ce;
 
     if (!autoload_defined_p(mod, id)) return Qfalse;
     load = check_autoload_required(mod, id, &loading);
@@ -2233,6 +2235,10 @@ rb_autoload_load(VALUE mod, ID id) https://github.com/ruby/ruby/blob/trunk/variable.c#L2235
     src = rb_sourcefile();
     if (src && loading && strcmp(src, loading) == 0) return Qfalse;
 
+    if ((ce = rb_const_lookup(mod, id))) {
+        flag = ce->flag & (CONST_DEPRECATED | CONST_VISIBILITY_MASK);
+    }
+
     /* set ele->state for a marker of autoloading thread */
     if (!(ele = get_autoload_data(load, &ac))) {
 	return Qfalse;
@@ -2264,6 +2270,9 @@ rb_autoload_load(VALUE mod, ID id) https://github.com/ruby/ruby/blob/trunk/variable.c#L2270
     result = rb_ensure(autoload_require, (VALUE)&state,
 		       autoload_reset, (VALUE)&state);
 
+    if (flag > 0 && (ce = rb_const_lookup(mod, id))) {
+        ce->flag |= flag;
+    }
     RB_GC_GUARD(load);
     return result;
 }
-- 
cgit v0.10.2


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

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