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; }