aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--lib/forwardable.rb46
-rw-r--r--test/test_forwardable.rb2
3 files changed, 38 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index b535efeb4f..d3118cf40d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Wed Dec 30 11:28:57 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/forwardable.rb (def_instance_delegator): adjust backtrace of
+ method body by tail call optimization. adjusting the delegated
+ target is still done by deleting backtrace.
+
+ * lib/forwardable.rb (def_single_delegator): ditto.
+
Wed Dec 30 11:18:42 2015 Elliot Winkler <elliot.winkler@gmail.com>
* lib/forwardable.rb (def_instance_delegator) fix delegating to
diff --git a/lib/forwardable.rb b/lib/forwardable.rb
index f27437af82..390e1460cf 100644
--- a/lib/forwardable.rb
+++ b/lib/forwardable.rb
@@ -182,23 +182,28 @@ module Forwardable
accessor = "#{accessor}()"
end
- line_no = __LINE__; str = %{
+ line_no = __LINE__; str = %{proc do
def #{ali}(*args, &block)
begin
- #{accessor}.__send__(:#{method}, *args, &block)
- rescue ::Exception
- $@.delete_if{|s| ::Forwardable::FILE_REGEXP =~ s} unless ::Forwardable::debug
- ::Kernel::raise
- end
+ #{accessor}
+ ensure
+ $@.delete_if {|s| ::Forwardable::FILE_REGEXP =~ s} if $@ and !::Forwardable::debug
+ end.__send__(:#{method}, *args, &block)
end
- }
+ end}
+
+ gen = RubyVM::InstructionSequence
+ .compile(str, __FILE__, __FILE__, line_no,
+ trace_instruction: false,
+ tailcall_optimization: true)
+ .eval
+
# If it's not a class or module, it's an instance
begin
- module_eval(str, __FILE__, line_no)
+ module_eval(&gen)
rescue
- instance_eval(str, __FILE__, line_no)
+ instance_eval(&gen)
end
-
end
alias delegate instance_delegate
@@ -278,18 +283,23 @@ module SingleForwardable
accessor = "#{accessor}()"
end
- line_no = __LINE__; str = %{
+ line_no = __LINE__; str = %{proc do
def #{ali}(*args, &block)
begin
- #{accessor}.__send__(:#{method}, *args, &block)
- rescue ::Exception
- $@.delete_if{|s| ::Forwardable::FILE_REGEXP =~ s} unless ::Forwardable::debug
- ::Kernel::raise
- end
+ #{accessor}
+ ensure
+ $@.delete_if {|s| ::Forwardable::FILE_REGEXP =~ s} if $@ and !::Forwardable::debug
+ end.__send__(:#{method}, *args, &block)
end
- }
+ end}
+
+ gen = RubyVM::InstructionSequence
+ .compile(str, __FILE__, __FILE__, line_no,
+ trace_instruction: false,
+ tailcall_optimization: true)
+ .eval
- instance_eval(str, __FILE__, line_no)
+ instance_eval(&gen)
end
alias delegate single_delegate
diff --git a/test/test_forwardable.rb b/test/test_forwardable.rb
index a474e4ad76..550280de19 100644
--- a/test/test_forwardable.rb
+++ b/test/test_forwardable.rb
@@ -187,6 +187,7 @@ class TestForwardable < Test::Unit::TestCase
extend Forwardable
def_delegator :bar, :baz
+ def_delegator :caller, :itself, :c
class Exception
end
@@ -197,6 +198,7 @@ class TestForwardable < Test::Unit::TestCase
Foo.new.baz
}
assert_not_match(/\/forwardable\.rb/, e.backtrace[0])
+ assert_equal(caller(0, 1)[0], Foo.new.c[0])
end
class Foo2 < BasicObject