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: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3bbaba84b454
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1809625a7ed5
Choose a head ref
  • 4 commits
  • 3 files changed
  • 1 contributor

Commits on Jul 7, 2015

  1. Add spec for Module#prepend

    * When a module is prepended after and affects subclasses.
    eregon committed Jul 7, 2015
    Copy the full SHA
    096125d View commit details
  2. Copy the full SHA
    b61eeb1 View commit details
  3. [Truffle] Always create a PrependMarker.

    * Needed unless we have a linked list outside the RubyModule instance.
    eregon committed Jul 7, 2015
    Copy the full SHA
    c8f9ee8 View commit details
  4. Copy the full SHA
    1809625 View commit details
18 changes: 17 additions & 1 deletion spec/ruby/core/module/prepend_spec.rb
Original file line number Diff line number Diff line change
@@ -117,8 +117,12 @@ def self.prepend_features(mod)
m1 = Module.new { def calc(x) x end }
m2 = Module.new { prepend(m1) }
c1 = Class.new { prepend(m2) }
c2 = Class.new { prepend(m2.dup) }
m2dup = m2.dup
m2dup.ancestors.should == [m2dup,m1,m2]
c2 = Class.new { prepend(m2dup) }
c1.ancestors[0,3].should == [m1,m2,c1]
c1.new.should be_kind_of(m1)
c2.ancestors[0,4].should == [m2dup,m1,m2,c2]
c2.new.should be_kind_of(m1)
end

@@ -127,6 +131,18 @@ def self.prepend_features(mod)
Class.new { prepend(m) }.ancestors.should_not include(m)
end

it "adds the module in the subclass chains" do
parent = Class.new { def chain; [:parent]; end }
child = Class.new(parent) { def chain; super << :child; end }
mod = Module.new { def chain; super << :mod; end }
parent.prepend mod
parent.ancestors[0,2].should == [mod, parent]
child.ancestors[0,3].should == [child, mod, parent]

parent.new.chain.should == [:parent, :mod]
child.new.chain.should == [:parent, :mod, :child]
end

it "inserts a later prepended module into the chain" do
m1 = Module.new { def chain; super << :m1; end }
m2 = Module.new { def chain; super << :m2; end }
1 change: 1 addition & 0 deletions spec/truffle/tags/core/module/prepend_tags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fails:Module#prepend keeps the module in the chain when dupping an intermediate module
Original file line number Diff line number Diff line change
@@ -98,8 +98,7 @@ public void insertAfter(RubyModule module) {
// The context is stored here - objects can obtain it via their class (which is a module)
private final RubyContext context;

/** Either {@code this} or a {@link PrependMarker} */
@CompilationFinal protected ModuleChain start = this;
protected final ModuleChain start = new PrependMarker(this);
@CompilationFinal protected ModuleChain parentModule;

private final RubyModule lexicalParent;
@@ -178,7 +177,7 @@ public void initCopy(RubyModule from) {
this.constants.putAll(from.constants);
this.classVariables.putAll(from.classVariables);

if (from.start instanceof PrependMarker) {
if (from.start.getParentModule() != from) {
this.parentModule = from.start;
} else {
this.parentModule = from.parentModule;
@@ -272,12 +271,6 @@ public void prepend(Node currentNode, RubyModule module) {
throw new RaiseException(getContext().getCoreLibrary().argumentError("cyclic prepend detected", currentNode));
}

if (start == this) {
// Create an PrependMarker pointing to an empty module or class
// serving as an indirection to the first prepended module
start = new PrependMarker(this);
}

Stack<RubyModule> modulesToPrepend = new Stack<>();
modulesToPrepend.push(module);
for (RubyModule includedModule : module.prependedAndIncludedModules()) {