mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
vm_eval.c: share with rb_obj_respond_to
* vm_eval.c (check_funcall_respond_to): share the behavior with rb_obj_respond_to. [ruby-core:70460] [Bug #11465] * vm_method.c (vm_respond_to): extract from rb_obj_respond_to and merge r39881. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51646 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
24da2db3e1
commit
629d26ef3a
4 changed files with 51 additions and 26 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
Thu Aug 20 14:13:27 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* vm_eval.c (check_funcall_respond_to): share the behavior with
|
||||||
|
rb_obj_respond_to. [ruby-core:70460] [Bug #11465]
|
||||||
|
|
||||||
|
* vm_method.c (vm_respond_to): extract from rb_obj_respond_to and
|
||||||
|
merge r39881.
|
||||||
|
|
||||||
Thu Aug 20 08:53:09 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Thu Aug 20 08:53:09 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* vm_method.c (rb_obj_respond_to): reuse found method entry
|
* vm_method.c (rb_obj_respond_to): reuse found method entry
|
||||||
|
|
|
@ -855,6 +855,28 @@ class TestArray < Test::Unit::TestCase
|
||||||
assert_match(/reentered/, e.message, '[ruby-dev:34798]')
|
assert_match(/reentered/, e.message, '[ruby-dev:34798]')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_flatten_respond_to_missing
|
||||||
|
bug11465 = '[ruby-core:70460] [Bug #11465]'
|
||||||
|
|
||||||
|
obj = Class.new do
|
||||||
|
def respond_to_missing?(method, stuff)
|
||||||
|
return false if method == :to_ary
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def method_missing(*args)
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end.new
|
||||||
|
|
||||||
|
ex = nil
|
||||||
|
trace = TracePoint.new(:raise) do |tp|
|
||||||
|
ex = tp.raised_exception
|
||||||
|
end
|
||||||
|
trace.enable {[obj].flatten}
|
||||||
|
assert_nil(ex, bug11465)
|
||||||
|
end
|
||||||
|
|
||||||
def test_permutation_with_callcc
|
def test_permutation_with_callcc
|
||||||
need_continuation
|
need_continuation
|
||||||
n = 1000
|
n = 1000
|
||||||
|
|
22
vm_eval.c
22
vm_eval.c
|
@ -378,27 +378,7 @@ check_funcall_failed(struct rescue_funcall_args *args, VALUE e)
|
||||||
static int
|
static int
|
||||||
check_funcall_respond_to(rb_thread_t *th, VALUE klass, VALUE recv, ID mid)
|
check_funcall_respond_to(rb_thread_t *th, VALUE klass, VALUE recv, ID mid)
|
||||||
{
|
{
|
||||||
const rb_callable_method_entry_t *me = rb_callable_method_entry(klass, idRespond_to);
|
return vm_respond_to(th, klass, recv, mid, 1);
|
||||||
|
|
||||||
if (me && !METHOD_ENTRY_BASIC(me)) {
|
|
||||||
const rb_block_t *passed_block = th->passed_block;
|
|
||||||
VALUE args[2], result;
|
|
||||||
int arity = rb_method_entry_arity((const rb_method_entry_t *)me);
|
|
||||||
|
|
||||||
if (arity > 2)
|
|
||||||
rb_raise(rb_eArgError, "respond_to? must accept 1 or 2 arguments (requires %d)", arity);
|
|
||||||
|
|
||||||
if (arity < 1) arity = 2;
|
|
||||||
|
|
||||||
args[0] = ID2SYM(mid);
|
|
||||||
args[1] = Qtrue;
|
|
||||||
result = vm_call0(th, recv, idRespond_to, arity, args, me);
|
|
||||||
th->passed_block = passed_block;
|
|
||||||
if (!RTEST(result)) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
25
vm_method.c
25
vm_method.c
|
@ -1829,10 +1829,9 @@ basic_obj_respond_to(VALUE obj, ID id, int pub)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
rb_obj_respond_to(VALUE obj, ID id, int priv)
|
vm_respond_to(rb_thread_t *th, VALUE klass, VALUE obj, ID id, int priv)
|
||||||
{
|
{
|
||||||
VALUE klass = CLASS_OF(obj);
|
|
||||||
VALUE defined_class;
|
VALUE defined_class;
|
||||||
const ID resid = idRespond_to;
|
const ID resid = idRespond_to;
|
||||||
const rb_method_entry_t *const me =
|
const rb_method_entry_t *const me =
|
||||||
|
@ -1845,12 +1844,20 @@ rb_obj_respond_to(VALUE obj, ID id, int priv)
|
||||||
else {
|
else {
|
||||||
int argc = 1;
|
int argc = 1;
|
||||||
VALUE args[2];
|
VALUE args[2];
|
||||||
|
VALUE result;
|
||||||
const rb_callable_method_entry_t *cme;
|
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;
|
||||||
if (priv) {
|
if (priv) {
|
||||||
if (rb_method_entry_arity(me) != 1) {
|
argc = rb_method_entry_arity(me);
|
||||||
|
if (argc > 2) {
|
||||||
|
rb_raise(rb_eArgError,
|
||||||
|
"respond_to? must accept 1 or 2 arguments (requires %d)",
|
||||||
|
argc);
|
||||||
|
}
|
||||||
|
if (argc != 1) {
|
||||||
argc = 2;
|
argc = 2;
|
||||||
}
|
}
|
||||||
else if (!NIL_P(ruby_verbose)) {
|
else if (!NIL_P(ruby_verbose)) {
|
||||||
|
@ -1871,10 +1878,18 @@ rb_obj_respond_to(VALUE obj, ID id, int priv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cme = prepare_callable_method_entry(defined_class, resid, me);
|
cme = prepare_callable_method_entry(defined_class, resid, me);
|
||||||
return RTEST(vm_call0(GET_THREAD(), obj, resid, argc, args, cme));
|
result = vm_call0(th, obj, resid, argc, args, cme);
|
||||||
|
th->passed_block = passed_block;
|
||||||
|
return RTEST(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_obj_respond_to(VALUE obj, ID id, int priv)
|
||||||
|
{
|
||||||
|
return vm_respond_to(GET_THREAD(), CLASS_OF(obj), obj, id, priv);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rb_respond_to(VALUE obj, ID id)
|
rb_respond_to(VALUE obj, ID id)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue