aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog18
-rw-r--r--test/ruby/test_settracefunc.rb18
-rw-r--r--vm_trace.c34
3 files changed, 65 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 2771f94544..d0cab08847 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+Tue Dec 18 04:58:22 2012 Koichi Sasada <ko1@atdot.net>
+
+ * vm_trace.c (fill_id_and_klass): TracePoint#defined_class returns
+ singleton class. `set_trace_func' passed attached class (which is
+ attached/modified by singleton class) by 6th block parameter if it
+ is singleton class. Previous behavior follows this spec.
+ However, this method named `defined_class' should return singleton
+ class directly because singleton methods are defined in singleton
+ class. There are no compatible issue because TracePoint is introduced
+ after 2.0.
+ But compatiblity with `set_trace_func' is brokne. This means that
+ you can not replace all `set_trace_func' code with TracePoint
+ without consideration of this behavior.
+ [Bug #7554]
+
+ * test/ruby/test_settracefunc.rb: change a test to catch up
+ an above chagne.
+
Tue Dec 18 03:03:10 2012 Aaron Patterson <aaron@tenderlovemaking.com>
* ext/psych/lib/psych/visitors/to_ruby.rb: speed up node mapping so
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index c6738494ae..0a30d04c02 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -418,12 +418,28 @@ class TestSetTraceFunc < Test::Unit::TestCase
:nothing
end
}
+ _defined_class = lambda{|tp|
+ klass = tp.defined_class
+ begin
+ # If it is singleton method, then return original class
+ # to make compatible with set_trace_func().
+ # This is very ad-hoc hack. I hope I can make more clean test on it.
+ case klass.inspect
+ when /Class:TracePoint/; return TracePoint
+ when /Class:Exception/; return Exception
+ else klass
+ klass
+ end
+ rescue Exception => e
+ e
+ end if klass
+ }
trace = nil
begin
eval <<-EOF.gsub(/^.*?: /, ""), nil, 'xyzzy'
1: trace = TracePoint.trace(*trace_events){|tp|
- 2: events << [tp.event, tp.lineno, tp.path, tp.defined_class, tp.method_id, tp.self, tp.binding.eval("_local_var"), _get_data.(tp)]
+ 2: events << [tp.event, tp.lineno, tp.path, _defined_class.(tp), tp.method_id, tp.self, tp.binding.eval("_local_var"), _get_data.(tp)]
3: }
4: 1.times{|;_local_var| _local_var = :inner
5: tap{}
diff --git a/vm_trace.c b/vm_trace.c
index 9b8ec40b33..ec5fe4f2dd 100644
--- a/vm_trace.c
+++ b/vm_trace.c
@@ -716,9 +716,6 @@ fill_id_and_klass(rb_trace_arg_t *trace_arg)
if (RB_TYPE_P(trace_arg->klass, T_ICLASS)) {
trace_arg->klass = RBASIC(trace_arg->klass)->klass;
}
- else if (FL_TEST(trace_arg->klass, FL_SINGLETON)) {
- trace_arg->klass = rb_iv_get(trace_arg->klass, "__attached__");
- }
}
else {
trace_arg->klass = Qnil;
@@ -838,7 +835,36 @@ tracepoint_attr_method_id(VALUE tpval)
}
/*
- * Return class or id from +:class+ event
+ * Return class or module the method being called.
+ *
+ * class C; def foo; end; end
+ * trace = TracePoint.new(:call) do |tp|
+ * tp.defined_class #=> C
+ * end.enable do
+ * C.new.foo
+ * end
+ *
+ * If method is defined by a module, then returns that module.
+ *
+ * module M; def foo; end; end
+ * class C; include M; end;
+ * trace = TracePoint.new(:call) do |tp|
+ * tp.defined_class #=> M
+ * end.enable do
+ * C.new.foo
+ * end
+ *
+ * Note that TracePont#defined_class returns singleton class.
+ * 6th block parameter of `set_trace_func' passes original class
+ * of attached by singleton class. This is a difference between
+ * `set_trace_func' and TracePoint.
+ *
+ * class C; def self.foo; end; end
+ * trace = TracePoint.new(:call) do |tp|
+ * tp.defined_class #=> #<Class:C>
+ * end.enable do
+ * C.foo
+ * end
*/
static VALUE
tracepoint_attr_defined_class(VALUE tpval)