ext/sender/rb_Global.c in sender-1.4.2 vs ext/sender/rb_Global.c in sender-1.4.3
- old
+ new
@@ -41,20 +41,42 @@
// 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 );
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 );
+ & rb_backtrace_limit,
+ rb_mKernel );
+
+ int c_backtrace_index = 1;
+
+ VALUE rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, c_backtrace_index );
VALUE rb_caller = rb_hash_aref( rb_backtrace_frame_hash,
ID2SYM( rb_intern( "method" ) ) );
+ // if we get :initialize as our caller and our __method__ is :initialize, we need to go up the chain
+ // until our caller is no longer :initialize or :new
+ while ( rb_caller == ID2SYM( rb_intern( "initialize" ) ) ) {
+ c_backtrace_index++;
+ rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, c_backtrace_index );
+ rb_caller = rb_hash_aref( rb_backtrace_frame_hash,
+ ID2SYM( rb_intern( "method" ) ) );
+
+ // we have one parent past our current method; if that is also :initialize, get the whole backtrace
+ if ( c_backtrace_index == 2 ) {
+ rb_backtrace_array = rb_RPRuby_Sender_Kernel_backtrace( 0, NULL, rb_mKernel );
+ }
+ }
+
+ // if we get "new" as our caller we need to get the next level, as we are in :initialize
+ // and want to know what called :new
+ //
+ // since we might have had to go up the chain from :initialize through parents before getting here we
+ // want to use a separate if statement
if ( rb_caller == ID2SYM( rb_intern( "new" ) ) ) {
- rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, 2 );
+ c_backtrace_index++;
+ rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, c_backtrace_index );
}
VALUE rb_sender = rb_hash_aref( rb_backtrace_frame_hash,
ID2SYM( rb_intern( "object" ) ) );
@@ -80,20 +102,46 @@
// 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 );
VALUE rb_backtrace_array = rb_RPRuby_Sender_Kernel_backtrace( 1,
- & rb_backtrace_limit,
- rb_mKernel );
+ & rb_backtrace_limit,
+ rb_mKernel );
- VALUE rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, 1 );
+ int c_backtrace_index = 1;
+ VALUE rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, c_backtrace_index );
+
VALUE rb_caller = rb_hash_aref( rb_backtrace_frame_hash,
- ID2SYM( rb_intern( "method" ) ) );
+ ID2SYM( rb_intern( "method" ) ) );
- if ( rb_caller == ID2SYM( rb_intern( "new" ) ) ) {
- rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, 2 );
+ // we want to compare our caller as we go up the chain to our first caller to deal with super methods
+ // we have a symbol so no cloning is necessary (or appropriate)
+ VALUE rb_first_caller = rb_hash_aref( rb_ary_entry( rb_backtrace_array, 0 ),
+ ID2SYM( rb_intern( "method" ) ) );
+
+ // if we get :initialize as our caller and our __method__ is :initialize, we need to go up the chain
+ // until our caller is no longer :initialize or :new
+ while ( rb_caller == rb_first_caller ) {
+ c_backtrace_index++;
+ rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, c_backtrace_index );
+ rb_caller = rb_hash_aref( rb_backtrace_frame_hash,
+ ID2SYM( rb_intern( "method" ) ) );
+ // we have one parent past our current method; if that is also :initialize, get the whole backtrace
+ if ( c_backtrace_index == 2 ) {
+ rb_backtrace_array = rb_RPRuby_Sender_Kernel_backtrace( 0, NULL, rb_mKernel );
+ }
+ }
+
+ // if we get "new" as our caller we need to get the next level, as we are in :initialize
+ // and want to know what called :new
+ //
+ // since we might have had to go up the chain from :initialize through parents before getting here we
+ // want to use a separate if statement
+ if ( rb_caller == ID2SYM( rb_intern( "new" ) ) ) {
+ c_backtrace_index++;
+ rb_backtrace_frame_hash = rb_ary_entry( rb_backtrace_array, c_backtrace_index );
rb_caller = rb_hash_aref( rb_backtrace_frame_hash,
ID2SYM( rb_intern( "method" ) ) );
}
// assuming we have a previous frame, return its rb_self (our current receiver's sender)