Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rubinius/rubinius
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: ba75b60ef43d
Choose a base ref
...
head repository: rubinius/rubinius
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: fcf450d47a33
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Nov 18, 2015

  1. Reset globally cached klass methods in Module#prepend_features

    Consider this example:
    
        class Parent
          def bar
          end
        end
    
        class Child < Parent
          def bar
            super
          end
    
          def foo
          end
        end
    
        Child.new.foo
        Child.new.bar
        # foo and bar are cached in the global cache
    
        prepended_module = Module.new do
          def foo
          end
        end
        Child.prepend(prepended_module)
        # foo is cleared from the global cache, but bar is not
        # Child hierarchy is now Child < IncludedModule(prepended_module) < IncludedModule(Child) < Parent
    
        Child.new.bar
        # When bar is looked up here, being still cached globally, Child#bar is the
        # result of the lookup (normally, it should be IncludedModule(Child)#bar).
        # Now when Child#bar is looking for its super, it goes to the first included
        # module, then the second included module, which has the same method table
        # as Child, returning Child#bar, causing non-ending recursive calls.
    ahmadsherif committed Nov 18, 2015
    Copy the full SHA
    5c4b45f View commit details
  2. Copy the full SHA
    fcf450d View commit details
Showing with 25 additions and 0 deletions.
  1. +3 −0 kernel/delta/module.rb
  2. +22 −0 spec/ruby/core/module/prepend_features_spec.rb
3 changes: 3 additions & 0 deletions kernel/delta/module.rb
Original file line number Diff line number Diff line change
@@ -200,6 +200,9 @@ def prepend_features(klass)
im.superclass = klass.direct_superclass
klass.superclass = im
klass.origin = im
klass.method_table.each do |meth, obj, vis|
Rubinius::VM.reset_method_cache klass, meth
end
end
Rubinius::Type.include_modules_from(self, klass)
Rubinius::Type.infect(klass, self)
22 changes: 22 additions & 0 deletions spec/ruby/core/module/prepend_features_spec.rb
Original file line number Diff line number Diff line change
@@ -40,6 +40,28 @@ def self.prepend_features(mod)
other.untrusted?.should be_true
end

it "clears caches of the given module" do
parent = Class.new do
def bar; :bar; end
end

child = Class.new(parent) do
def foo; :foo; end
def bar; super; end
end

mod = Module.new do
def foo; :fooo; end
end

child.new.foo
child.new.bar

child.prepend(mod)

child.new.bar.should == :bar
end

describe "on Class" do
ruby_bug "GH-376", "2.0.0.312" do
it "is undefined" do