зеркало из https://github.com/github/ruby.git
* eval_error.c (rb_print_undef_str): new function to raise
NameError for undefined method. * load.c (rb_mod_autoload_p), object.c (rb_mod_const_get), variable.c (rb_f_untrace_var, set_const_visibility), vm_method.c (rb_mod_{remove,undef,alias}_method, set_method_visibility): remove inadvertent symbol creation. based on the first patch by Jeremy Evans at [ruby-core:38447]. [Feature #5089] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32686 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
298349d03b
Коммит
8603c5934a
11
ChangeLog
11
ChangeLog
|
@ -1,4 +1,13 @@
|
||||||
Wed Jul 27 01:05:28 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Wed Jul 27 01:05:32 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* eval_error.c (rb_print_undef_str): new function to raise
|
||||||
|
NameError for undefined method.
|
||||||
|
|
||||||
|
* load.c (rb_mod_autoload_p), object.c (rb_mod_const_get),
|
||||||
|
variable.c (rb_f_untrace_var, set_const_visibility), vm_method.c
|
||||||
|
(rb_mod_{remove,undef,alias}_method, set_method_visibility):
|
||||||
|
remove inadvertent symbol creation. based on the first patch by
|
||||||
|
Jeremy Evans at [ruby-core:38447]. [Feature #5089]
|
||||||
|
|
||||||
* vm_method.c (obj_respond_to): fix the respond_to_missing? override
|
* vm_method.c (obj_respond_to): fix the respond_to_missing? override
|
||||||
case. based on the patch by Jeremy Evans at [ruby-core:38417].
|
case. based on the patch by Jeremy Evans at [ruby-core:38417].
|
||||||
|
|
|
@ -206,6 +206,15 @@ rb_print_undef(VALUE klass, ID id, int scope)
|
||||||
rb_class2name(klass));
|
rb_class2name(klass));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_print_undef_str(VALUE klass, VALUE name)
|
||||||
|
{
|
||||||
|
rb_name_error_str(name, "undefined method `%s' for %s `%s'",
|
||||||
|
RSTRING_PTR(name),
|
||||||
|
(TYPE(klass) == T_MODULE) ? "module" : "class",
|
||||||
|
rb_class2name(klass));
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sysexit_status(VALUE err)
|
sysexit_status(VALUE err)
|
||||||
{
|
{
|
||||||
|
|
|
@ -198,9 +198,12 @@ int rb_threadptr_reset_raised(rb_thread_t *th);
|
||||||
VALUE rb_f_eval(int argc, VALUE *argv, VALUE self);
|
VALUE rb_f_eval(int argc, VALUE *argv, VALUE self);
|
||||||
VALUE rb_make_exception(int argc, VALUE *argv);
|
VALUE rb_make_exception(int argc, VALUE *argv);
|
||||||
|
|
||||||
|
NORETURN(void rb_method_name_error(VALUE, VALUE));
|
||||||
|
|
||||||
NORETURN(void rb_fiber_start(void));
|
NORETURN(void rb_fiber_start(void));
|
||||||
|
|
||||||
NORETURN(void rb_print_undef(VALUE, ID, int));
|
NORETURN(void rb_print_undef(VALUE, ID, int));
|
||||||
|
NORETURN(void rb_print_undef_str(VALUE, VALUE));
|
||||||
NORETURN(void rb_vm_localjump_error(const char *,VALUE, int));
|
NORETURN(void rb_vm_localjump_error(const char *,VALUE, int));
|
||||||
NORETURN(void rb_vm_jump_tag_but_local_jump(int, VALUE));
|
NORETURN(void rb_vm_jump_tag_but_local_jump(int, VALUE));
|
||||||
NORETURN(void rb_raise_method_missing(rb_thread_t *th, int argc, VALUE *argv,
|
NORETURN(void rb_raise_method_missing(rb_thread_t *th, int argc, VALUE *argv,
|
||||||
|
|
6
load.c
6
load.c
|
@ -705,7 +705,11 @@ rb_mod_autoload(VALUE mod, VALUE sym, VALUE file)
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_mod_autoload_p(VALUE mod, VALUE sym)
|
rb_mod_autoload_p(VALUE mod, VALUE sym)
|
||||||
{
|
{
|
||||||
return rb_autoload_p(mod, rb_to_id(sym));
|
ID id = rb_check_id(&sym);
|
||||||
|
if (!id) {
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
return rb_autoload_p(mod, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
20
object.c
20
object.c
|
@ -35,6 +35,7 @@ VALUE rb_cFalseClass;
|
||||||
|
|
||||||
static ID id_eq, id_eql, id_match, id_inspect;
|
static ID id_eq, id_eql, id_match, id_inspect;
|
||||||
static ID id_init_copy, id_init_clone, id_init_dup;
|
static ID id_init_copy, id_init_clone, id_init_dup;
|
||||||
|
static ID id_const_missing;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
|
@ -1774,7 +1775,23 @@ rb_mod_const_get(int argc, VALUE *argv, VALUE mod)
|
||||||
else {
|
else {
|
||||||
rb_scan_args(argc, argv, "11", &name, &recur);
|
rb_scan_args(argc, argv, "11", &name, &recur);
|
||||||
}
|
}
|
||||||
id = rb_to_id(name);
|
id = rb_check_id(&name);
|
||||||
|
if (!id) {
|
||||||
|
if (!rb_is_const_name(name)) {
|
||||||
|
rb_name_error_str(name, "wrong constant name %s", RSTRING_PTR(name));
|
||||||
|
}
|
||||||
|
else if (!rb_method_basic_definition_p(CLASS_OF(mod), id_const_missing)) {
|
||||||
|
id = rb_to_id(name);
|
||||||
|
}
|
||||||
|
else if (mod && rb_class_real(mod) != rb_cObject) {
|
||||||
|
rb_name_error_str(name, "uninitialized constant %s::%s",
|
||||||
|
rb_class2name(mod),
|
||||||
|
RSTRING_PTR(name));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rb_name_error_str(name, "uninitialized constant %s", RSTRING_PTR(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!rb_is_const_id(id)) {
|
if (!rb_is_const_id(id)) {
|
||||||
rb_name_error(id, "wrong constant name %s", rb_id2name(id));
|
rb_name_error(id, "wrong constant name %s", rb_id2name(id));
|
||||||
}
|
}
|
||||||
|
@ -2813,6 +2830,7 @@ Init_Object(void)
|
||||||
id_init_copy = rb_intern("initialize_copy");
|
id_init_copy = rb_intern("initialize_copy");
|
||||||
id_init_clone = rb_intern("initialize_clone");
|
id_init_clone = rb_intern("initialize_clone");
|
||||||
id_init_dup = rb_intern("initialize_dup");
|
id_init_dup = rb_intern("initialize_dup");
|
||||||
|
id_const_missing = rb_intern("const_missing");
|
||||||
|
|
||||||
for (i=0; conv_method_names[i].method; i++) {
|
for (i=0; conv_method_names[i].method; i++) {
|
||||||
conv_method_names[i].id = rb_intern(conv_method_names[i].method);
|
conv_method_names[i].id = rb_intern(conv_method_names[i].method);
|
||||||
|
|
2
proc.c
2
proc.c
|
@ -1144,7 +1144,7 @@ method_owner(VALUE obj)
|
||||||
return data->me->klass;
|
return data->me->klass;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
rb_method_name_error(VALUE klass, VALUE str)
|
rb_method_name_error(VALUE klass, VALUE str)
|
||||||
{
|
{
|
||||||
const char *s0 = " class";
|
const char *s0 = " class";
|
||||||
|
|
|
@ -472,6 +472,9 @@ class TestModule < Test::Unit::TestCase
|
||||||
assert_raise(NameError) { c2::Bar }
|
assert_raise(NameError) { c2::Bar }
|
||||||
assert_raise(NameError) { c2.const_get(:Bar) }
|
assert_raise(NameError) { c2.const_get(:Bar) }
|
||||||
assert_raise(NameError) { c2.const_get(:Bar, false) }
|
assert_raise(NameError) { c2.const_get(:Bar, false) }
|
||||||
|
assert_raise(NameError) { c2.const_get("Bar", false) }
|
||||||
|
assert_raise(NameError) { c2.const_get("BaR11", false) }
|
||||||
|
assert_raise(NameError) { Object.const_get("BaR11", false) }
|
||||||
|
|
||||||
c1.instance_eval do
|
c1.instance_eval do
|
||||||
def const_missing(x)
|
def const_missing(x)
|
||||||
|
@ -483,6 +486,11 @@ class TestModule < Test::Unit::TestCase
|
||||||
assert_equal(:Bar, c2::Bar)
|
assert_equal(:Bar, c2::Bar)
|
||||||
assert_equal(:Bar, c2.const_get(:Bar))
|
assert_equal(:Bar, c2.const_get(:Bar))
|
||||||
assert_equal(:Bar, c2.const_get(:Bar, false))
|
assert_equal(:Bar, c2.const_get(:Bar, false))
|
||||||
|
assert_equal(:Bar, c2.const_get("Bar"))
|
||||||
|
assert_equal(:Bar, c2.const_get("Bar", false))
|
||||||
|
|
||||||
|
v = c2.const_get("Bar11", false)
|
||||||
|
assert_equal("Bar11".to_sym, v)
|
||||||
|
|
||||||
assert_raise(NameError) { c1.const_get(:foo) }
|
assert_raise(NameError) { c1.const_get(:foo) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -197,4 +197,37 @@ class TestSymbol < Test::Unit::TestCase
|
||||||
assert !Symbol.all_symbols.any? {|sym| sym.to_s == str}, msg
|
assert !Symbol.all_symbols.any? {|sym| sym.to_s == str}, msg
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_no_inadvertent_symbol_creation3
|
||||||
|
feature5089 = '[ruby-core:38447]'
|
||||||
|
c = Class.new do
|
||||||
|
def self.alias_method(str)
|
||||||
|
super(:puts, str)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
s = "gadzoooks"
|
||||||
|
{:alias_method => ["#{s}1", NameError],
|
||||||
|
:autoload? => ["#{s}2", nil],
|
||||||
|
:const_get => ["A#{s}3", NameError],
|
||||||
|
:private_class_method => ["#{s}4", NameError],
|
||||||
|
:private_constant => ["#{s}5", NameError],
|
||||||
|
:private => ["#{s}6", NameError],
|
||||||
|
:protected => ["#{s}7", NameError],
|
||||||
|
:public => ["#{s}8", NameError],
|
||||||
|
:public_class_method => ["#{s}9", NameError],
|
||||||
|
:public_constant => ["#{s}10", NameError],
|
||||||
|
:remove_method => ["#{s}11", NameError],
|
||||||
|
:undef_method => ["#{s}12", NameError],
|
||||||
|
:untrace_var => ["#{s}13", NameError],
|
||||||
|
}.each do |meth, arr|
|
||||||
|
str, ret = arr
|
||||||
|
msg = "#{meth}(#{str}) #{feature5089}"
|
||||||
|
if ret.is_a?(Class) && (ret < Exception)
|
||||||
|
assert_raises(ret){c.send(meth, str)}
|
||||||
|
else
|
||||||
|
assert(c.send(meth, str) == ret, msg)
|
||||||
|
end
|
||||||
|
assert !Symbol.all_symbols.any? {|sym| sym.to_s == str}, msg
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
11
variable.c
11
variable.c
|
@ -634,7 +634,10 @@ rb_f_untrace_var(int argc, VALUE *argv)
|
||||||
|
|
||||||
rb_secure(4);
|
rb_secure(4);
|
||||||
rb_scan_args(argc, argv, "11", &var, &cmd);
|
rb_scan_args(argc, argv, "11", &var, &cmd);
|
||||||
id = rb_to_id(var);
|
id = rb_check_id(&var);
|
||||||
|
if (!id) {
|
||||||
|
rb_name_error_str(var, "undefined global variable %s", RSTRING_PTR(var));
|
||||||
|
}
|
||||||
if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) {
|
if (!st_lookup(rb_global_tbl, (st_data_t)id, &data)) {
|
||||||
rb_name_error(id, "undefined global variable %s", rb_id2name(id));
|
rb_name_error(id, "undefined global variable %s", rb_id2name(id));
|
||||||
}
|
}
|
||||||
|
@ -1972,7 +1975,11 @@ set_const_visibility(VALUE mod, int argc, VALUE *argv, rb_const_flag_t flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
id = rb_to_id(argv[i]);
|
VALUE val = argv[i];
|
||||||
|
id = rb_check_id(&val);
|
||||||
|
if (!id) {
|
||||||
|
rb_name_error_str(val, "constant %s::%s not defined", rb_class2name(mod), RSTRING_PTR(val));
|
||||||
|
}
|
||||||
if (RCLASS_CONST_TBL(mod) && st_lookup(RCLASS_CONST_TBL(mod), (st_data_t)id, &v)) {
|
if (RCLASS_CONST_TBL(mod) && st_lookup(RCLASS_CONST_TBL(mod), (st_data_t)id, &v)) {
|
||||||
((rb_const_entry_t*)v)->flag = flag;
|
((rb_const_entry_t*)v)->flag = flag;
|
||||||
return;
|
return;
|
||||||
|
|
28
vm_method.c
28
vm_method.c
|
@ -485,7 +485,13 @@ rb_mod_remove_method(int argc, VALUE *argv, VALUE mod)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
remove_method(mod, rb_to_id(argv[i]));
|
VALUE v = argv[i];
|
||||||
|
ID id = rb_check_id(&v);
|
||||||
|
if (!id) {
|
||||||
|
rb_name_error_str(v, "method `%s' not defined in %s",
|
||||||
|
RSTRING_PTR(v), rb_class2name(mod));
|
||||||
|
}
|
||||||
|
remove_method(mod, id);
|
||||||
}
|
}
|
||||||
return mod;
|
return mod;
|
||||||
}
|
}
|
||||||
|
@ -693,7 +699,12 @@ rb_mod_undef_method(int argc, VALUE *argv, VALUE mod)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
rb_undef(mod, rb_to_id(argv[i]));
|
VALUE v = argv[i];
|
||||||
|
ID id = rb_check_id(&v);
|
||||||
|
if (!id) {
|
||||||
|
rb_method_name_error(mod, v);
|
||||||
|
}
|
||||||
|
rb_undef(mod, id);
|
||||||
}
|
}
|
||||||
return mod;
|
return mod;
|
||||||
}
|
}
|
||||||
|
@ -952,7 +963,11 @@ rb_alias(VALUE klass, ID name, ID def)
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
|
rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
|
||||||
{
|
{
|
||||||
rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
|
ID oldid = rb_check_id(&oldname);
|
||||||
|
if (!oldid) {
|
||||||
|
rb_print_undef_str(mod, oldname);
|
||||||
|
}
|
||||||
|
rb_alias(mod, rb_to_id(newname), oldid);
|
||||||
return mod;
|
return mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -971,7 +986,12 @@ set_method_visibility(VALUE self, int argc, VALUE *argv, rb_method_flag_t ex)
|
||||||
int i;
|
int i;
|
||||||
secure_visibility(self);
|
secure_visibility(self);
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
rb_export_method(self, rb_to_id(argv[i]), ex);
|
VALUE v = argv[i];
|
||||||
|
ID id = rb_check_id(&v);
|
||||||
|
if (!id) {
|
||||||
|
rb_print_undef_str(self, v);
|
||||||
|
}
|
||||||
|
rb_export_method(self, id, ex);
|
||||||
}
|
}
|
||||||
rb_clear_cache_by_class(self);
|
rb_clear_cache_by_class(self);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче