mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 21:49:06 +02:00
merge revision(s) 62394,62395: [Backport #14469]
vm_insnhelper.c: rb_autoloading_value flag * vm_insnhelper.c (vm_get_ev_const): add flag argument of `rb_autoloading_value`. * constant.h (rb_autoloading_value): moved the declaration from vm_core.h for `rb_const_flag_t`. [ruby-core:85516] [Bug #14469] variable.c: flags at autoloading * variable.c (const_tbl_update): flags by deprecate_constant / private_constant set during autoloading should be preserved after required. [ruby-core:85516] [Bug #14469] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_4@62916 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
ad0b27d054
commit
9869b65573
6 changed files with 81 additions and 15 deletions
|
@ -46,5 +46,6 @@ int rb_public_const_defined(VALUE klass, ID id);
|
||||||
int rb_public_const_defined_at(VALUE klass, ID id);
|
int rb_public_const_defined_at(VALUE klass, ID id);
|
||||||
int rb_public_const_defined_from(VALUE klass, ID id);
|
int rb_public_const_defined_from(VALUE klass, ID id);
|
||||||
rb_const_entry_t *rb_const_lookup(VALUE klass, ID id);
|
rb_const_entry_t *rb_const_lookup(VALUE klass, ID id);
|
||||||
|
int rb_autoloading_value(VALUE mod, ID id, VALUE *value, rb_const_flag_t *flag);
|
||||||
|
|
||||||
#endif /* CONSTANT_H */
|
#endif /* CONSTANT_H */
|
||||||
|
|
|
@ -246,6 +246,46 @@ p Foo::Bar
|
||||||
assert_ruby_status([script], '', '[ruby-core:81016] [Bug #13526]')
|
assert_ruby_status([script], '', '[ruby-core:81016] [Bug #13526]')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_autoload_private_constant
|
||||||
|
Dir.mktmpdir('autoload') do |tmpdir|
|
||||||
|
File.write(tmpdir+"/zzz.rb", "#{<<~"begin;"}\n#{<<~'end;'}")
|
||||||
|
begin;
|
||||||
|
class AutoloadTest
|
||||||
|
ZZZ = :ZZZ
|
||||||
|
private_constant :ZZZ
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-'end;'}")
|
||||||
|
bug = '[ruby-core:85516] [Bug #14469]'
|
||||||
|
begin;
|
||||||
|
class AutoloadTest
|
||||||
|
autoload :ZZZ, "zzz.rb"
|
||||||
|
end
|
||||||
|
assert_raise(NameError, bug) {AutoloadTest::ZZZ}
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_autoload_deprecate_constant
|
||||||
|
Dir.mktmpdir('autoload') do |tmpdir|
|
||||||
|
File.write(tmpdir+"/zzz.rb", "#{<<~"begin;"}\n#{<<~'end;'}")
|
||||||
|
begin;
|
||||||
|
class AutoloadTest
|
||||||
|
ZZZ = :ZZZ
|
||||||
|
deprecate_constant :ZZZ
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-'end;'}")
|
||||||
|
bug = '[ruby-core:85516] [Bug #14469]'
|
||||||
|
begin;
|
||||||
|
class AutoloadTest
|
||||||
|
autoload :ZZZ, "zzz.rb"
|
||||||
|
end
|
||||||
|
assert_warning(/ZZZ is deprecated/, bug) {AutoloadTest::ZZZ}
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def add_autoload(path)
|
def add_autoload(path)
|
||||||
(@autoload_paths ||= []) << path
|
(@autoload_paths ||= []) << path
|
||||||
::Object.class_eval {autoload(:AutoloadTest, path)}
|
::Object.class_eval {autoload(:AutoloadTest, path)}
|
||||||
|
|
49
variable.c
49
variable.c
|
@ -1903,6 +1903,7 @@ struct autoload_state {
|
||||||
struct autoload_data_i {
|
struct autoload_data_i {
|
||||||
VALUE feature;
|
VALUE feature;
|
||||||
int safe_level;
|
int safe_level;
|
||||||
|
rb_const_flag_t flag;
|
||||||
VALUE value;
|
VALUE value;
|
||||||
struct autoload_state *state; /* points to on-stack struct */
|
struct autoload_state *state; /* points to on-stack struct */
|
||||||
};
|
};
|
||||||
|
@ -1985,6 +1986,7 @@ rb_autoload_str(VALUE mod, ID id, VALUE file)
|
||||||
ele->safe_level = rb_safe_level();
|
ele->safe_level = rb_safe_level();
|
||||||
ele->value = Qundef;
|
ele->value = Qundef;
|
||||||
ele->state = 0;
|
ele->state = 0;
|
||||||
|
ele->flag = CONST_PUBLIC;
|
||||||
st_insert(tbl, (st_data_t)id, (st_data_t)ad);
|
st_insert(tbl, (st_data_t)id, (st_data_t)ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2060,7 +2062,7 @@ check_autoload_required(VALUE mod, ID id, const char **loadingpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rb_autoloading_value(VALUE mod, ID id, VALUE* value)
|
rb_autoloading_value(VALUE mod, ID id, VALUE* value, rb_const_flag_t *flag)
|
||||||
{
|
{
|
||||||
VALUE load;
|
VALUE load;
|
||||||
struct autoload_data_i *ele;
|
struct autoload_data_i *ele;
|
||||||
|
@ -2073,6 +2075,9 @@ rb_autoloading_value(VALUE mod, ID id, VALUE* value)
|
||||||
if (value) {
|
if (value) {
|
||||||
*value = ele->value;
|
*value = ele->value;
|
||||||
}
|
}
|
||||||
|
if (flag) {
|
||||||
|
*flag = ele->flag;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2087,13 +2092,14 @@ autoload_defined_p(VALUE mod, ID id)
|
||||||
if (!ce || ce->value != Qundef) {
|
if (!ce || ce->value != Qundef) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return !rb_autoloading_value(mod, id, NULL);
|
return !rb_autoloading_value(mod, id, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct autoload_const_set_args {
|
struct autoload_const_set_args {
|
||||||
VALUE mod;
|
VALUE mod;
|
||||||
ID id;
|
ID id;
|
||||||
VALUE value;
|
VALUE value;
|
||||||
|
rb_const_flag_t flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void const_tbl_update(struct autoload_const_set_args *);
|
static void const_tbl_update(struct autoload_const_set_args *);
|
||||||
|
@ -2140,6 +2146,7 @@ autoload_reset(VALUE arg)
|
||||||
args.mod = state->mod;
|
args.mod = state->mod;
|
||||||
args.id = state->id;
|
args.id = state->id;
|
||||||
args.value = state->ele->value;
|
args.value = state->ele->value;
|
||||||
|
args.flag = state->ele->flag;
|
||||||
safe_backup = rb_safe_level();
|
safe_backup = rb_safe_level();
|
||||||
rb_set_safe_level_force(state->ele->safe_level);
|
rb_set_safe_level_force(state->ele->safe_level);
|
||||||
rb_ensure(autoload_const_set, (VALUE)&args,
|
rb_ensure(autoload_const_set, (VALUE)&args,
|
||||||
|
@ -2286,6 +2293,7 @@ static VALUE
|
||||||
rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility)
|
rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility)
|
||||||
{
|
{
|
||||||
VALUE value, tmp, av;
|
VALUE value, tmp, av;
|
||||||
|
rb_const_flag_t flag;
|
||||||
int mod_retry = 0;
|
int mod_retry = 0;
|
||||||
|
|
||||||
tmp = klass;
|
tmp = klass;
|
||||||
|
@ -2304,7 +2312,7 @@ rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility)
|
||||||
if (value == Qundef) {
|
if (value == Qundef) {
|
||||||
if (am == tmp) break;
|
if (am == tmp) break;
|
||||||
am = tmp;
|
am = tmp;
|
||||||
if (rb_autoloading_value(tmp, id, &av)) return av;
|
if (rb_autoloading_value(tmp, id, &av, &flag)) return av;
|
||||||
rb_autoload_load(tmp, id);
|
rb_autoload_load(tmp, id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2556,7 +2564,7 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
|
||||||
return (int)Qfalse;
|
return (int)Qfalse;
|
||||||
}
|
}
|
||||||
if (ce->value == Qundef && !check_autoload_required(tmp, id, 0) &&
|
if (ce->value == Qundef && !check_autoload_required(tmp, id, 0) &&
|
||||||
!rb_autoloading_value(tmp, id, 0))
|
!rb_autoloading_value(tmp, id, NULL, NULL))
|
||||||
return (int)Qfalse;
|
return (int)Qfalse;
|
||||||
return (int)Qtrue;
|
return (int)Qtrue;
|
||||||
}
|
}
|
||||||
|
@ -2637,6 +2645,7 @@ rb_const_set(VALUE klass, ID id, VALUE val)
|
||||||
args.mod = klass;
|
args.mod = klass;
|
||||||
args.id = id;
|
args.id = id;
|
||||||
args.value = val;
|
args.value = val;
|
||||||
|
args.flag = CONST_PUBLIC;
|
||||||
const_tbl_update(&args);
|
const_tbl_update(&args);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -2668,6 +2677,21 @@ rb_const_set(VALUE klass, ID id, VALUE val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct autoload_data_i *
|
||||||
|
current_autoload_data(VALUE mod, ID id)
|
||||||
|
{
|
||||||
|
struct autoload_data_i *ele;
|
||||||
|
VALUE load = autoload_data(mod, id);
|
||||||
|
if (!load) return 0;
|
||||||
|
ele = check_autoload_data(load);
|
||||||
|
if (!ele) return 0;
|
||||||
|
/* for autoloading thread, keep the defined value to autoloading storage */
|
||||||
|
if (ele->state && (ele->state->thread == rb_thread_current())) {
|
||||||
|
return ele;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
const_tbl_update(struct autoload_const_set_args *args)
|
const_tbl_update(struct autoload_const_set_args *args)
|
||||||
{
|
{
|
||||||
|
@ -2676,19 +2700,15 @@ const_tbl_update(struct autoload_const_set_args *args)
|
||||||
VALUE val = args->value;
|
VALUE val = args->value;
|
||||||
ID id = args->id;
|
ID id = args->id;
|
||||||
struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
|
struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
|
||||||
rb_const_flag_t visibility = CONST_PUBLIC;
|
rb_const_flag_t visibility = args->flag;
|
||||||
rb_const_entry_t *ce;
|
rb_const_entry_t *ce;
|
||||||
|
|
||||||
if (rb_id_table_lookup(tbl, id, &value)) {
|
if (rb_id_table_lookup(tbl, id, &value)) {
|
||||||
ce = (rb_const_entry_t *)value;
|
ce = (rb_const_entry_t *)value;
|
||||||
if (ce->value == Qundef) {
|
if (ce->value == Qundef) {
|
||||||
VALUE load;
|
struct autoload_data_i *ele = current_autoload_data(klass, id);
|
||||||
struct autoload_data_i *ele;
|
|
||||||
|
|
||||||
load = autoload_data(klass, id);
|
if (ele) {
|
||||||
/* for autoloading thread, keep the defined value to autoloading storage */
|
|
||||||
if (load && (ele = check_autoload_data(load)) && ele->state &&
|
|
||||||
(ele->state->thread == rb_thread_current())) {
|
|
||||||
rb_clear_constant_cache();
|
rb_clear_constant_cache();
|
||||||
|
|
||||||
ele->value = val; /* autoload_i is non-WB-protected */
|
ele->value = val; /* autoload_i is non-WB-protected */
|
||||||
|
@ -2777,6 +2797,13 @@ set_const_visibility(VALUE mod, int argc, const VALUE *argv,
|
||||||
if ((ce = rb_const_lookup(mod, id))) {
|
if ((ce = rb_const_lookup(mod, id))) {
|
||||||
ce->flag &= ~mask;
|
ce->flag &= ~mask;
|
||||||
ce->flag |= flag;
|
ce->flag |= flag;
|
||||||
|
if (ce->value == Qundef) {
|
||||||
|
struct autoload_data_i *ele = current_autoload_data(mod, id);
|
||||||
|
if (ele) {
|
||||||
|
ele->flag &= ~mask;
|
||||||
|
ele->flag |= flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#define RUBY_VERSION "2.4.4"
|
#define RUBY_VERSION "2.4.4"
|
||||||
#define RUBY_RELEASE_DATE "2018-03-25"
|
#define RUBY_RELEASE_DATE "2018-03-25"
|
||||||
#define RUBY_PATCHLEVEL 285
|
#define RUBY_PATCHLEVEL 286
|
||||||
|
|
||||||
#define RUBY_RELEASE_YEAR 2018
|
#define RUBY_RELEASE_YEAR 2018
|
||||||
#define RUBY_RELEASE_MONTH 3
|
#define RUBY_RELEASE_MONTH 3
|
||||||
|
|
|
@ -1477,8 +1477,6 @@ void rb_vm_register_special_exception(enum ruby_special_exceptions sp, VALUE exc
|
||||||
|
|
||||||
void rb_gc_mark_machine_stack(rb_thread_t *th);
|
void rb_gc_mark_machine_stack(rb_thread_t *th);
|
||||||
|
|
||||||
int rb_autoloading_value(VALUE mod, ID id, VALUE* value);
|
|
||||||
|
|
||||||
void rb_vm_rewrite_cref(rb_cref_t *node, VALUE old_klass, VALUE new_klass, rb_cref_t **new_cref_ptr);
|
void rb_vm_rewrite_cref(rb_cref_t *node, VALUE old_klass, VALUE new_klass, rb_cref_t **new_cref_ptr);
|
||||||
|
|
||||||
const rb_callable_method_entry_t *rb_vm_frame_method_entry(const rb_control_frame_t *cfp);
|
const rb_callable_method_entry_t *rb_vm_frame_method_entry(const rb_control_frame_t *cfp);
|
||||||
|
|
|
@ -790,7 +790,7 @@ vm_get_ev_const(rb_thread_t *th, VALUE orig_klass, ID id, int is_defined)
|
||||||
if (am == klass) break;
|
if (am == klass) break;
|
||||||
am = klass;
|
am = klass;
|
||||||
if (is_defined) return 1;
|
if (is_defined) return 1;
|
||||||
if (rb_autoloading_value(klass, id, &av)) return av;
|
if (rb_autoloading_value(klass, id, &av, NULL)) return av;
|
||||||
rb_autoload_load(klass, id);
|
rb_autoload_load(klass, id);
|
||||||
goto search_continue;
|
goto search_continue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue