[前][次][番号順一覧][スレッド一覧]

ruby-changes:46014

From: usa <ko1@a...>
Date: Sat, 25 Mar 2017 23:43:26 +0900 (JST)
Subject: [ruby-changes:46014] usa:r58085 (ruby_2_2): merge revision(s) 53383, 55366: [Backport #12478]

usa	2017-03-25 23:43:16 +0900 (Sat, 25 Mar 2017)

  New Revision: 58085

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=58085

  Log:
    merge revision(s) 53383,55366: [Backport #12478]
    
    * 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.
    
    * lib/forwardable.rb (Forwardable._delegator_method): extract
      method generator and deal with non-module objects.
      [ruby-dev:49656] [Bug #12478]

  Modified directories:
    branches/ruby_2_2/
  Modified files:
    branches/ruby_2_2/ChangeLog
    branches/ruby_2_2/lib/forwardable.rb
    branches/ruby_2_2/test/test_forwardable.rb
    branches/ruby_2_2/version.h
Index: ruby_2_2/lib/forwardable.rb
===================================================================
--- ruby_2_2/lib/forwardable.rb	(revision 58084)
+++ ruby_2_2/lib/forwardable.rb	(revision 58085)
@@ -1,3 +1,4 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_2/lib/forwardable.rb#L1
+# frozen_string_literal: false
 #
 #   forwardable.rb -
 #       $Release Version: 1.1$
@@ -177,33 +178,44 @@ module Forwardable https://github.com/ruby/ruby/blob/trunk/ruby_2_2/lib/forwardable.rb#L178
   #   q.push 23  #=> NoMethodError
   #
   def def_instance_delegator(accessor, method, ali = method)
-    accessor = accessor.to_s
-    if method_defined?(accessor) || private_method_defined?(accessor)
-      accessor = "#{accessor}()"
-    end
+    gen = Forwardable._delegator_method(self, accessor, method, ali)
 
-    line_no = __LINE__; str = %{
-      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
-      end
-    }
     # If it's not a class or module, it's an instance
-    begin
-      module_eval(str, __FILE__, line_no)
-    rescue
-      instance_eval(str, __FILE__, line_no)
-    end
-
+    (Module === self ? self : singleton_class).module_eval(&gen)
   end
 
   alias delegate instance_delegate
   alias def_delegators def_instance_delegators
   alias def_delegator def_instance_delegator
+
+  def self._delegator_method(obj, accessor, method, ali)
+    accessor = accessor.to_s unless Symbol === accessor
+
+    if Module === obj ?
+         obj.method_defined?(accessor) || obj.private_method_defined?(accessor) :
+         obj.respond_to?(accessor, true)
+      accessor = "#{accessor}()"
+    end
+
+    line_no = __LINE__+1; str = "#{<<-"begin;"}\n#{<<-"end;"}"
+    begin;
+      proc do
+        def #{ali}(*args, &block)
+          begin
+            #{accessor}
+          ensure
+            $@.delete_if {|s| ::Forwardable::FILE_REGEXP =~ s} if $@ and !::Forwardable::debug
+          end.__send__ :#{method}, *args, &block
+        end
+      end
+    end;
+
+    RubyVM::InstructionSequence
+      .compile(str, __FILE__, __FILE__, line_no,
+               trace_instruction: false,
+               tailcall_optimization: true)
+      .eval
+  end
 end
 
 # SingleForwardable can be used to setup delegation at the object level as well.
@@ -274,23 +286,9 @@ module SingleForwardable https://github.com/ruby/ruby/blob/trunk/ruby_2_2/lib/forwardable.rb#L286
   # the method of the same name in _accessor_).  If _new_name_ is
   # provided, it is used as the name for the delegate method.
   def def_single_delegator(accessor, method, ali = method)
-    accessor = accessor.to_s
-    if method_defined?(accessor) || private_method_defined?(accessor)
-      accessor = "#{accessor}()"
-    end
-
-    line_no = __LINE__; str = %{
-      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
-      end
-    }
+    gen = Forwardable._delegator_method(self, accessor, method, ali)
 
-    instance_eval(str, __FILE__, line_no)
+    instance_eval(&gen)
   end
 
   alias delegate single_delegate
Index: ruby_2_2/version.h
===================================================================
--- ruby_2_2/version.h	(revision 58084)
+++ ruby_2_2/version.h	(revision 58085)
@@ -1,10 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_2/version.h#L1
 #define RUBY_VERSION "2.2.7"
-#define RUBY_RELEASE_DATE "2017-01-04"
-#define RUBY_PATCHLEVEL 418
+#define RUBY_RELEASE_DATE "2017-03-25"
+#define RUBY_PATCHLEVEL 419
 
 #define RUBY_RELEASE_YEAR 2017
-#define RUBY_RELEASE_MONTH 1
-#define RUBY_RELEASE_DAY 4
+#define RUBY_RELEASE_MONTH 3
+#define RUBY_RELEASE_DAY 25
 
 #include "ruby/version.h"
 
Index: ruby_2_2/ChangeLog
===================================================================
--- ruby_2_2/ChangeLog	(revision 58084)
+++ ruby_2_2/ChangeLog	(revision 58085)
@@ -1,3 +1,17 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_2/ChangeLog#L1
+Sat Mar 25 23:35:54 2017  Nobuyoshi Nakada  <nobu@r...>
+
+	* lib/forwardable.rb (Forwardable._delegator_method): extract
+	  method generator and deal with non-module objects.
+	  [ruby-dev:49656] [Bug #12478]
+
+Sat Mar 25 23:35:54 2017  Nobuyoshi Nakada  <nobu@r...>
+
+	* 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.
+
 Tue Dec 27 20:43:54 2016  Nobuyoshi Nakada  <nobu@r...>
 
 	* time.c (usec2subsecx): fix return type, which is a numeric object but
Index: ruby_2_2/test/test_forwardable.rb
===================================================================
--- ruby_2_2/test/test_forwardable.rb	(revision 58084)
+++ ruby_2_2/test/test_forwardable.rb	(revision 58085)
@@ -144,7 +144,7 @@ class TestForwardable < Test::Unit::Test https://github.com/ruby/ruby/blob/trunk/ruby_2_2/test/test_forwardable.rb#L144
     end
   end
 
-  def test_def_single_delegator
+  def test_class_single_delegator
     %i[def_delegator def_single_delegator].each do |m|
       cls = single_forwardable_class do
         __send__ m, :@receiver, :delegated1
@@ -154,7 +154,7 @@ class TestForwardable < Test::Unit::Test https://github.com/ruby/ruby/blob/trunk/ruby_2_2/test/test_forwardable.rb#L154
     end
   end
 
-  def test_def_single_delegators
+  def test_class_single_delegators
     %i[def_delegators def_single_delegators].each do |m|
       cls = single_forwardable_class do
         __send__ m, :@receiver, :delegated1, :delegated2
@@ -165,7 +165,7 @@ class TestForwardable < Test::Unit::Test https://github.com/ruby/ruby/blob/trunk/ruby_2_2/test/test_forwardable.rb#L165
     end
   end
 
-  def test_single_delegate
+  def test_class_single_delegate
     %i[delegate single_delegate].each do |m|
       cls = single_forwardable_class do
         __send__ m, delegated1: :@receiver, delegated2: :@receiver
@@ -183,6 +183,45 @@ class TestForwardable < Test::Unit::Test https://github.com/ruby/ruby/blob/trunk/ruby_2_2/test/test_forwardable.rb#L183
     end
   end
 
+  def test_obj_single_delegator
+    %i[def_delegator def_single_delegator].each do |m|
+      obj = single_forwardable_object do
+        __send__ m, :@receiver, :delegated1
+      end
+
+      assert_same RETURNED1, obj.delegated1
+    end
+  end
+
+  def test_obj_single_delegators
+    %i[def_delegators def_single_delegators].each do |m|
+      obj = single_forwardable_object do
+        __send__ m, :@receiver, :delegated1, :delegated2
+      end
+
+      assert_same RETURNED1, obj.delegated1
+      assert_same RETURNED2, obj.delegated2
+    end
+  end
+
+  def test_obj_single_delegate
+    %i[delegate single_delegate].each do |m|
+      obj = single_forwardable_object do
+        __send__ m, delegated1: :@receiver, delegated2: :@receiver
+      end
+
+      assert_same RETURNED1, obj.delegated1
+      assert_same RETURNED2, obj.delegated2
+
+      obj = single_forwardable_object do
+        __send__ m, %i[delegated1 delegated2] => :@receiver
+      end
+
+      assert_same RETURNED1, obj.delegated1
+      assert_same RETURNED2, obj.delegated2
+    end
+  end
+
   class Foo
     extend Forwardable
 
@@ -193,6 +232,27 @@ class TestForwardable < Test::Unit::Test https://github.com/ruby/ruby/blob/trunk/ruby_2_2/test/test_forwardable.rb#L232
     end
   end
 
+  def test_backtrace_adjustment
+    e = assert_raise(NameError) {
+      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
+    extend ::Forwardable
+
+    def_delegator :bar, :baz
+  end
+
+  def test_basicobject_subclass
+    bug11616 = '[ruby-core:71176] [Bug #11616]'
+    assert_raise_with_message(NameError, /`bar'/, bug11616) {
+      Foo2.new.baz
+    }
+  end
+
   private
 
   def forwardable_class(
@@ -226,4 +286,11 @@ class TestForwardable < Test::Unit::Test https://github.com/ruby/ruby/blob/trunk/ruby_2_2/test/test_forwardable.rb#L286
       class_exec(&block)
     end
   end
+
+  def single_forwardable_object(&block)
+    obj = Object.new.extend SingleForwardable
+    obj.instance_variable_set(:@receiver, RECEIVER)
+    obj.instance_eval(&block)
+    obj
+  end
 end

Property changes on: ruby_2_2
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /trunk:r53383


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]