ext/sender/rb_Global.c in sender-1.3 vs ext/sender/rb_Global.c in sender-1.4
- old
+ new
@@ -1,7 +1,8 @@
#include "rb_Global.h"
+#include "rb_Kernel.h"
// Internals from ruby that aren't included in the ruby lib
#include "RubySourceSupport.h"
#include "eval_intern.h"
@@ -32,21 +33,35 @@
* __sender__ -> object
*
* Return object sending message to receiver.
*/
VALUE rb_RPRuby_Sender___sender__() {
+
+ // we want 3 levels of backtrace:
+ // 1: current call to __method__ (__method__ in context)
+ // 2: the frame we want, unless it is :new (call to context: __sender__)
+ // 3: the frame we want in the case #2 is :new
+ VALUE rb_backtrace_limit = INT2FIX( 3 );
- // get the frame prior to current frame
- rb_control_frame_t* c_sending_frame = RPRuby_internal_framePriorTo( NULL );
+ VALUE rb_backtrace_array = rb_RPRuby_Sender_Kernel_backtrace( 1,
+ & rb_backtrace_limit,
+ rb_mKernel );
+
+ VALUE rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, 1 );
+
+ VALUE rb_caller = rb_hash_aref( rb_backtrace_frame_hash,
+ ID2SYM( rb_intern( "method" ) ) );
- // make sure the current frame wasn't the first frame or return nil
- if ( c_sending_frame == NULL ) {
- return Qnil;
+ if ( rb_caller == ID2SYM( rb_intern( "new" ) ) ) {
+ rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, 2 );
}
+ VALUE rb_sender = rb_hash_aref( rb_backtrace_frame_hash,
+ ID2SYM( rb_intern( "object" ) ) );
+
// assuming we have a previous frame, return its rb_self (our current receiver's sender)
- return c_sending_frame->self;
+ return rb_sender;
}
/***************
* __caller__ *
***************/
@@ -57,16 +72,32 @@
*
* Return method sending message to receiver.
*/
VALUE rb_RPRuby_Sender___caller__() {
- // get the frame prior to current frame
- rb_control_frame_t* c_sending_frame = RPRuby_internal_framePriorTo( NULL );
+
+ // we want 3 levels of backtrace:
+ // 1: current call to __method__ (__method__ in context)
+ // 2: the frame we want, unless it is :new (call to context: __sender__)
+ // 3: the frame we want in the case #2 is :new
+ VALUE rb_backtrace_limit = INT2FIX( 3 );
- // make sure the current frame wasn't the first frame or return nil
- if ( c_sending_frame == NULL ) {
- return Qnil;
+ VALUE rb_backtrace_array = rb_RPRuby_Sender_Kernel_backtrace( 1,
+ & rb_backtrace_limit,
+ rb_mKernel );
+
+ VALUE rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, 1 );
+
+ VALUE rb_caller = rb_hash_aref( rb_backtrace_frame_hash,
+ ID2SYM( rb_intern( "method" ) ) );
+
+ if ( rb_caller == ID2SYM( rb_intern( "new" ) ) ) {
+ rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, 2 );
+
+ rb_caller = rb_hash_aref( rb_backtrace_frame_hash,
+ ID2SYM( rb_intern( "method" ) ) );
}
- return ID2SYM( frame_func_id( c_sending_frame ) );
+ // assuming we have a previous frame, return its rb_self (our current receiver's sender)
+ return rb_caller;
}