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]
This commit is contained in:
Jeremy Evans 2019-08-11 20:53:37 -07:00
Родитель b96d559c69
Коммит 47c97e1e84
2 изменённых файлов: 69 добавлений и 0 удалений

Просмотреть файл

@ -295,6 +295,66 @@ p Foo::Bar
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|

Просмотреть файл

@ -2226,6 +2226,8 @@ rb_autoload_load(VALUE mod, ID id)
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)
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)
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;
}