mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
method in instance_eval
* class.c (rb_special_singleton_class_of): utility function. * vm_eval.c (eval_under): special deal for class variable scope with instance_eval. * vm_eval.c (rb_obj_instance_eval, rb_obj_instance_exec): allow method definition in instance_eval of special constants. [ruby-core:28324] [Bug #2788] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36647 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
353833c466
commit
28827e61d1
6 changed files with 61 additions and 23 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
|||
Tue Aug 7 00:31:09 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* class.c (rb_special_singleton_class_of): utility function.
|
||||
|
||||
* vm_eval.c (eval_under): special deal for class variable scope with
|
||||
instance_eval.
|
||||
|
||||
* vm_eval.c (rb_obj_instance_eval, rb_obj_instance_exec): allow method
|
||||
definition in instance_eval of special constants. [ruby-core:28324]
|
||||
[Bug #2788]
|
||||
|
||||
Tue Aug 7 00:23:58 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* variable.c (CVAR_LOOKUP): split into helper functions.
|
||||
|
|
|
@ -264,24 +264,18 @@ assert_equal 'ok', %q{
|
|||
}, '[ruby-core:16794]'
|
||||
|
||||
assert_equal 'ok', %q{
|
||||
begin
|
||||
nil.instance_eval {
|
||||
def a() :a end
|
||||
}
|
||||
rescue TypeError
|
||||
:ok
|
||||
end
|
||||
}, '[ruby-core:16796]'
|
||||
nil.instance_eval {
|
||||
def defd_using_instance_eval() :ok end
|
||||
}
|
||||
nil.defd_using_instance_eval
|
||||
}, '[ruby-core:28324]'
|
||||
|
||||
assert_equal 'ok', %q{
|
||||
begin
|
||||
nil.instance_exec {
|
||||
def a() :a end
|
||||
}
|
||||
rescue TypeError
|
||||
:ok
|
||||
end
|
||||
}, '[ruby-core:16796]'
|
||||
nil.instance_exec {
|
||||
def defd_using_instance_exec() :ok end
|
||||
}
|
||||
nil.defd_using_instance_exec
|
||||
}, '[ruby-core:28324]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
eval("", method(:proc).call {}.binding)
|
||||
|
|
24
class.c
24
class.c
|
@ -1286,6 +1286,20 @@ rb_undef_method(VALUE klass, const char *name)
|
|||
}\
|
||||
} while (0)
|
||||
|
||||
static inline VALUE
|
||||
special_singleton_class_of(VALUE obj)
|
||||
{
|
||||
SPECIAL_SINGLETON(Qnil, rb_cNilClass);
|
||||
SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
|
||||
SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_special_singleton_class(VALUE obj)
|
||||
{
|
||||
return special_singleton_class_of(obj);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
|
@ -1304,11 +1318,11 @@ singleton_class_of(VALUE obj)
|
|||
if (FIXNUM_P(obj) || SYMBOL_P(obj)) {
|
||||
rb_raise(rb_eTypeError, "can't define singleton");
|
||||
}
|
||||
if (rb_special_const_p(obj)) {
|
||||
SPECIAL_SINGLETON(Qnil, rb_cNilClass);
|
||||
SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
|
||||
SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
|
||||
rb_bug("unknown immediate %p", (void *)obj);
|
||||
if (SPECIAL_CONST_P(obj)) {
|
||||
klass = special_singleton_class_of(obj);
|
||||
if (NIL_P(klass))
|
||||
rb_bug("unknown immediate %p", (void *)obj);
|
||||
return klass;
|
||||
}
|
||||
|
||||
if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) &&
|
||||
|
|
|
@ -60,6 +60,7 @@ VALUE rb_obj_protected_methods(int argc, VALUE *argv, VALUE obj);
|
|||
VALUE rb_obj_private_methods(int argc, VALUE *argv, VALUE obj);
|
||||
VALUE rb_obj_public_methods(int argc, VALUE *argv, VALUE obj);
|
||||
int rb_obj_basic_to_s_p(VALUE);
|
||||
VALUE rb_special_singleton_class(VALUE);
|
||||
void Init_class_hierarchy(void);
|
||||
|
||||
/* compile.c */
|
||||
|
|
|
@ -200,6 +200,21 @@ class TestEval < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_instance_eval_method
|
||||
bug2788 = '[ruby-core:28324]'
|
||||
[Object.new, [], nil, true, false].each do |o|
|
||||
assert_nothing_raised(TypeError, "#{bug2788} (#{o.inspect})") do
|
||||
o.instance_eval {
|
||||
def defd_using_instance_eval() :ok end
|
||||
}
|
||||
end
|
||||
assert_equal(:ok, o.defd_using_instance_eval)
|
||||
class << o
|
||||
remove_method :defd_using_instance_eval
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# From ruby/test/ruby/test_eval.rb
|
||||
#
|
||||
|
|
|
@ -1320,6 +1320,9 @@ eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
|
|||
{
|
||||
NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC, NULL);
|
||||
|
||||
if (FL_TEST(under, FL_SINGLETON) || (SPECIAL_CONST_P(self) && !NIL_P(under))) {
|
||||
cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
|
||||
}
|
||||
if (rb_safe_level() >= 4) {
|
||||
StringValue(src);
|
||||
}
|
||||
|
@ -1387,7 +1390,7 @@ rb_obj_instance_eval(int argc, VALUE *argv, VALUE self)
|
|||
VALUE klass;
|
||||
|
||||
if (SPECIAL_CONST_P(self)) {
|
||||
klass = Qnil;
|
||||
klass = rb_special_singleton_class(self);
|
||||
}
|
||||
else {
|
||||
klass = rb_singleton_class(self);
|
||||
|
@ -1419,7 +1422,7 @@ rb_obj_instance_exec(int argc, VALUE *argv, VALUE self)
|
|||
VALUE klass;
|
||||
|
||||
if (SPECIAL_CONST_P(self)) {
|
||||
klass = Qnil;
|
||||
klass = rb_special_singleton_class(self);
|
||||
}
|
||||
else {
|
||||
klass = rb_singleton_class(self);
|
||||
|
|
Loading…
Reference in a new issue