mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
NoMethodError#private_call?
* error.c (nometh_err_initialize): add private_call? parameter. * error.c (nometh_err_private_call_p): add private_call? method, to tell if the exception raised in private form FCALL or VCALL. [Feature #12043] * vm_eval.c (make_no_method_exception): append private_call? argument. * vm_insnhelper.c (ci_missing_reason): copy FCALL flag. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53961 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
74e5e61849
commit
4d9f5482ae
7 changed files with 67 additions and 10 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
|||
Sun Feb 28 13:40:46 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* error.c (nometh_err_initialize): add private_call? parameter.
|
||||
|
||||
* error.c (nometh_err_private_call_p): add private_call? method,
|
||||
to tell if the exception raised in private form FCALL or VCALL.
|
||||
[Feature #12043]
|
||||
|
||||
* vm_eval.c (make_no_method_exception): append private_call?
|
||||
argument.
|
||||
|
||||
* vm_insnhelper.c (ci_missing_reason): copy FCALL flag.
|
||||
|
||||
Sun Feb 28 10:19:47 2016 Ryan T. Hosford <tad.hosford@gmail.com>
|
||||
|
||||
* array.c (rb_ary_and): clarify that set intersection returns the
|
||||
|
|
11
error.c
11
error.c
|
@ -697,6 +697,7 @@ static VALUE rb_eNOERROR;
|
|||
static ID id_new, id_cause, id_message, id_backtrace;
|
||||
static ID id_name, id_args, id_Errno, id_errno, id_i_path;
|
||||
static ID id_receiver, id_iseq, id_local_variables;
|
||||
static ID id_private_call_p;
|
||||
extern ID ruby_static_id_status;
|
||||
#define id_bt idBt
|
||||
#define id_bt_locations idBt_locations
|
||||
|
@ -1203,9 +1204,11 @@ name_err_local_variables(VALUE self)
|
|||
static VALUE
|
||||
nometh_err_initialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
VALUE priv = (argc > 3) && (--argc, RTEST(argv[argc])) ? Qtrue : Qfalse;
|
||||
VALUE args = (argc > 2) ? argv[--argc] : Qnil;
|
||||
name_err_initialize(argc, argv, self);
|
||||
rb_ivar_set(self, id_args, args);
|
||||
rb_ivar_set(self, id_private_call_p, RTEST(priv) ? Qtrue : Qfalse);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -1392,6 +1395,12 @@ nometh_err_args(VALUE self)
|
|||
return rb_attr_get(self, id_args);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
nometh_err_private_call_p(VALUE self)
|
||||
{
|
||||
return rb_attr_get(self, id_private_call_p);
|
||||
}
|
||||
|
||||
void
|
||||
rb_invalid_str(const char *str, const char *type)
|
||||
{
|
||||
|
@ -2019,6 +2028,7 @@ Init_Exception(void)
|
|||
rb_eNoMethodError = rb_define_class("NoMethodError", rb_eNameError);
|
||||
rb_define_method(rb_eNoMethodError, "initialize", nometh_err_initialize, -1);
|
||||
rb_define_method(rb_eNoMethodError, "args", nometh_err_args, 0);
|
||||
rb_define_method(rb_eNoMethodError, "private_call?", nometh_err_private_call_p, 0);
|
||||
|
||||
rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
|
||||
rb_eSecurityError = rb_define_class("SecurityError", rb_eException);
|
||||
|
@ -2043,6 +2053,7 @@ Init_Exception(void)
|
|||
id_name = rb_intern_const("name");
|
||||
id_args = rb_intern_const("args");
|
||||
id_receiver = rb_intern_const("receiver");
|
||||
id_private_call_p = rb_intern_const("private_call?");
|
||||
id_local_variables = rb_intern_const("local_variables");
|
||||
id_Errno = rb_intern_const("Errno");
|
||||
id_errno = rb_intern_const("errno");
|
||||
|
|
|
@ -762,6 +762,7 @@ end.join
|
|||
assert_equal(:foo, e.name)
|
||||
assert_equal([1, 2], e.args)
|
||||
assert_same(obj, e.receiver)
|
||||
assert_not_predicate(e, :private_call?)
|
||||
|
||||
e = assert_raise(NoMethodError) {
|
||||
obj.instance_eval {foo(1, 2)}
|
||||
|
@ -769,6 +770,7 @@ end.join
|
|||
assert_equal(:foo, e.name)
|
||||
assert_equal([1, 2], e.args)
|
||||
assert_same(obj, e.receiver)
|
||||
assert_predicate(e, :private_call?)
|
||||
end
|
||||
|
||||
def test_name_error_info_local_variables
|
||||
|
@ -787,6 +789,29 @@ end.join
|
|||
assert_equal(%i[a b c d e f g], e.local_variables.sort)
|
||||
end
|
||||
|
||||
def test_name_error_info_method_missing
|
||||
obj = PrettyObject.new
|
||||
def obj.method_missing(*)
|
||||
super
|
||||
end
|
||||
|
||||
e = assert_raise(NoMethodError) {
|
||||
obj.foo(1, 2)
|
||||
}
|
||||
assert_equal(:foo, e.name)
|
||||
assert_equal([1, 2], e.args)
|
||||
assert_same(obj, e.receiver)
|
||||
assert_not_predicate(e, :private_call?)
|
||||
|
||||
e = assert_raise(NoMethodError) {
|
||||
obj.instance_eval {foo(1, 2)}
|
||||
}
|
||||
assert_equal(:foo, e.name)
|
||||
assert_equal([1, 2], e.args)
|
||||
assert_same(obj, e.receiver)
|
||||
assert_predicate(e, :private_call?)
|
||||
end
|
||||
|
||||
def test_name_error_info_parent_iseq_mark
|
||||
assert_separately(['-', File.join(__dir__, 'bug-11928.rb')], <<-'end;')
|
||||
-> {require ARGV[0]}.call
|
||||
|
|
|
@ -200,10 +200,11 @@ enum method_missing_reason {
|
|||
MISSING_NOENTRY = 0x00,
|
||||
MISSING_PRIVATE = 0x01,
|
||||
MISSING_PROTECTED = 0x02,
|
||||
MISSING_VCALL = 0x04,
|
||||
MISSING_SUPER = 0x08,
|
||||
MISSING_MISSING = 0x10,
|
||||
MISSING_NONE = 0x20
|
||||
MISSING_FCALL = 0x04,
|
||||
MISSING_VCALL = 0x08,
|
||||
MISSING_SUPER = 0x10,
|
||||
MISSING_MISSING = 0x20,
|
||||
MISSING_NONE = 0x40
|
||||
};
|
||||
|
||||
struct rb_call_info {
|
||||
|
|
11
vm_eval.c
11
vm_eval.c
|
@ -682,13 +682,15 @@ rb_method_missing(int argc, const VALUE *argv, VALUE obj)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
make_no_method_exception(VALUE exc, VALUE format, VALUE obj, int argc, const VALUE *argv)
|
||||
make_no_method_exception(VALUE exc, VALUE format, VALUE obj,
|
||||
int argc, const VALUE *argv, int priv)
|
||||
{
|
||||
int n = 0;
|
||||
enum {
|
||||
arg_mesg,
|
||||
arg_name,
|
||||
arg_args,
|
||||
arg_priv,
|
||||
args_size
|
||||
};
|
||||
VALUE args[args_size];
|
||||
|
@ -700,6 +702,7 @@ make_no_method_exception(VALUE exc, VALUE format, VALUE obj, int argc, const VAL
|
|||
args[n++] = argv[0];
|
||||
if (exc == rb_eNoMethodError) {
|
||||
args[n++] = rb_ary_new4(argc - 1, argv + 1);
|
||||
args[n++] = priv ? Qtrue : Qfalse;
|
||||
}
|
||||
return rb_class_new_instance(n, args, exc);
|
||||
}
|
||||
|
@ -737,7 +740,8 @@ raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj,
|
|||
}
|
||||
|
||||
{
|
||||
exc = make_no_method_exception(exc, format, obj, argc, argv);
|
||||
exc = make_no_method_exception(exc, format, obj, argc, argv,
|
||||
last_call_status & (MISSING_FCALL|MISSING_VCALL));
|
||||
if (!(last_call_status & MISSING_MISSING)) {
|
||||
rb_vm_pop_cfunc_frame();
|
||||
}
|
||||
|
@ -929,7 +933,8 @@ send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
|
|||
if (!id) {
|
||||
if (rb_method_basic_definition_p(CLASS_OF(recv), idMethodMissing)) {
|
||||
VALUE exc = make_no_method_exception(rb_eNoMethodError, 0,
|
||||
recv, argc, argv);
|
||||
recv, argc, argv,
|
||||
scope != CALL_PUBLIC);
|
||||
rb_exc_raise(exc);
|
||||
}
|
||||
if (!SYMBOL_P(*argv)) {
|
||||
|
|
|
@ -1782,6 +1782,7 @@ ci_missing_reason(const struct rb_call_info *ci)
|
|||
{
|
||||
enum method_missing_reason stat = MISSING_NOENTRY;
|
||||
if (ci->flag & VM_CALL_VCALL) stat |= MISSING_VCALL;
|
||||
if (ci->flag & VM_CALL_FCALL) stat |= MISSING_FCALL;
|
||||
if (ci->flag & VM_CALL_SUPER) stat |= MISSING_SUPER;
|
||||
return stat;
|
||||
}
|
||||
|
@ -1823,7 +1824,8 @@ vm_call_opt_send(rb_thread_t *th, rb_control_frame_t *reg_cfp, struct rb_calling
|
|||
if (!(ci->mid = rb_check_id(&sym))) {
|
||||
if (rb_method_basic_definition_p(CLASS_OF(calling->recv), idMethodMissing)) {
|
||||
VALUE exc = make_no_method_exception(rb_eNoMethodError, 0, calling->recv,
|
||||
rb_long2int(calling->argc), &TOPN(i));
|
||||
rb_long2int(calling->argc), &TOPN(i),
|
||||
ci->flag & (VM_CALL_FCALL|VM_CALL_VCALL));
|
||||
rb_exc_raise(exc);
|
||||
}
|
||||
TOPN(i) = rb_str_intern(sym);
|
||||
|
|
|
@ -185,8 +185,8 @@ enum vm_regan_acttype {
|
|||
#define GET_GLOBAL_CONSTANT_STATE() (ruby_vm_global_constant_state)
|
||||
#define INC_GLOBAL_CONSTANT_STATE() (++ruby_vm_global_constant_state)
|
||||
|
||||
static VALUE make_no_method_exception(VALUE exc, VALUE format,
|
||||
VALUE obj, int argc, const VALUE *argv);
|
||||
static VALUE make_no_method_exception(VALUE exc, VALUE format, VALUE obj,
|
||||
int argc, const VALUE *argv, int priv);
|
||||
|
||||
static inline struct vm_throw_data *
|
||||
THROW_DATA_NEW(VALUE val, rb_control_frame_t *cf, VALUE st)
|
||||
|
|
Loading…
Reference in a new issue