mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
vm_eval.c: redefined respond_to_missing?
* vm_method.c (basic_obj_respond_to): call respond_to_missing? only when redefined. [ruby-core:70460] [Bug #11465] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51647 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
629d26ef3a
commit
0970a928ef
2 changed files with 42 additions and 20 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
Thu Aug 20 22:19:17 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* vm_method.c (basic_obj_respond_to): call respond_to_missing?
|
||||||
|
only when redefined. [ruby-core:70460] [Bug #11465]
|
||||||
|
|
||||||
Thu Aug 20 14:13:27 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Thu Aug 20 14:13:27 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* vm_eval.c (check_funcall_respond_to): share the behavior with
|
* vm_eval.c (check_funcall_respond_to): share the behavior with
|
||||||
|
|
57
vm_method.c
57
vm_method.c
|
@ -1811,19 +1811,44 @@ rb_method_basic_definition_p(VALUE klass, ID id)
|
||||||
return (me && METHOD_ENTRY_BASIC(me)) ? TRUE : FALSE;
|
return (me && METHOD_ENTRY_BASIC(me)) ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
call_method_entry(rb_thread_t *th, VALUE defined_class, VALUE obj, ID id,
|
||||||
|
const rb_method_entry_t *me, int argc, const VALUE *argv)
|
||||||
|
{
|
||||||
|
const rb_callable_method_entry_t *cme =
|
||||||
|
prepare_callable_method_entry(defined_class, id, me);
|
||||||
|
const rb_block_t *passed_block = th->passed_block;
|
||||||
|
VALUE result = vm_call0(th, obj, id, argc, argv, cme);
|
||||||
|
th->passed_block = passed_block;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
basic_obj_respond_to_missing(rb_thread_t *th, VALUE klass, VALUE obj,
|
||||||
|
VALUE mid, VALUE priv)
|
||||||
|
{
|
||||||
|
VALUE defined_class, args[2];
|
||||||
|
const ID rtmid = idRespond_to_missing;
|
||||||
|
const rb_method_entry_t *const me =
|
||||||
|
method_entry_get(klass, rtmid, &defined_class);
|
||||||
|
|
||||||
|
if (!me || METHOD_ENTRY_BASIC(me)) return Qfalse;
|
||||||
|
args[0] = mid;
|
||||||
|
args[1] = priv;
|
||||||
|
return call_method_entry(th, defined_class, obj, rtmid, me, 2, args);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
basic_obj_respond_to(VALUE obj, ID id, int pub)
|
basic_obj_respond_to(rb_thread_t *th, VALUE obj, ID id, int pub)
|
||||||
{
|
{
|
||||||
VALUE klass = CLASS_OF(obj);
|
VALUE klass = CLASS_OF(obj);
|
||||||
VALUE args[2];
|
|
||||||
|
|
||||||
switch (rb_method_boundp(klass, id, pub|BOUND_RESPONDS)) {
|
switch (rb_method_boundp(klass, id, pub|BOUND_RESPONDS)) {
|
||||||
case 2:
|
case 2:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
case 0:
|
case 0:
|
||||||
args[0] = ID2SYM(id);
|
return RTEST(basic_obj_respond_to_missing(th, klass, obj, ID2SYM(id),
|
||||||
args[1] = pub ? Qfalse : Qtrue;
|
pub ? Qfalse : Qtrue));
|
||||||
return RTEST(rb_funcall2(obj, idRespond_to_missing, 2, args));
|
|
||||||
default:
|
default:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1837,16 +1862,14 @@ vm_respond_to(rb_thread_t *th, VALUE klass, VALUE obj, ID id, int priv)
|
||||||
const rb_method_entry_t *const me =
|
const rb_method_entry_t *const me =
|
||||||
method_entry_get(klass, resid, &defined_class);
|
method_entry_get(klass, resid, &defined_class);
|
||||||
|
|
||||||
if (!me) return FALSE;
|
if (!me) return TRUE;
|
||||||
if (METHOD_ENTRY_BASIC(me)) {
|
if (METHOD_ENTRY_BASIC(me)) {
|
||||||
return basic_obj_respond_to(obj, id, !priv);
|
return basic_obj_respond_to(th, obj, id, !priv);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int argc = 1;
|
int argc = 1;
|
||||||
VALUE args[2];
|
VALUE args[2];
|
||||||
VALUE result;
|
VALUE result;
|
||||||
const rb_callable_method_entry_t *cme;
|
|
||||||
const rb_block_t *passed_block = th->passed_block;
|
|
||||||
|
|
||||||
args[0] = ID2SYM(id);
|
args[0] = ID2SYM(id);
|
||||||
args[1] = Qtrue;
|
args[1] = Qtrue;
|
||||||
|
@ -1877,9 +1900,7 @@ vm_respond_to(rb_thread_t *th, VALUE klass, VALUE obj, ID id, int priv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cme = prepare_callable_method_entry(defined_class, resid, me);
|
result = call_method_entry(th, defined_class, obj, resid, me, argc, args);
|
||||||
result = vm_call0(th, obj, resid, argc, args, cme);
|
|
||||||
th->passed_block = passed_block;
|
|
||||||
return RTEST(result);
|
return RTEST(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1922,18 +1943,14 @@ obj_respond_to(int argc, VALUE *argv, VALUE obj)
|
||||||
{
|
{
|
||||||
VALUE mid, priv;
|
VALUE mid, priv;
|
||||||
ID id;
|
ID id;
|
||||||
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
|
||||||
rb_scan_args(argc, argv, "11", &mid, &priv);
|
rb_scan_args(argc, argv, "11", &mid, &priv);
|
||||||
if (!(id = rb_check_id(&mid))) {
|
if (!(id = rb_check_id(&mid))) {
|
||||||
if (!rb_method_basic_definition_p(CLASS_OF(obj), idRespond_to_missing)) {
|
return basic_obj_respond_to_missing(th, CLASS_OF(obj), obj,
|
||||||
VALUE args[2];
|
rb_to_symbol(mid), priv);
|
||||||
args[0] = rb_to_symbol(mid);
|
|
||||||
args[1] = priv;
|
|
||||||
return rb_funcall2(obj, idRespond_to_missing, 2, args);
|
|
||||||
}
|
}
|
||||||
return Qfalse;
|
if (basic_obj_respond_to(th, obj, id, !RTEST(priv)))
|
||||||
}
|
|
||||||
if (basic_obj_respond_to(obj, id, !RTEST(priv)))
|
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
return Qfalse;
|
return Qfalse;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue