Skip to content

Commit

Permalink
Prepend must set method's "defined class" to the new bottom.
Browse files Browse the repository at this point in the history
  • Loading branch information
headius committed Oct 26, 2016
1 parent 9ad2754 commit 9c49a58
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 6 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/AbstractRubyMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public String getMethodName() {

@JRubyMethod(name = "owner")
public IRubyObject owner(ThreadContext context) {
return implementationModule;
return method.getDefinedClass();
}

@JRubyMethod(name = "source_location")
Expand Down
1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/PrependedModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public PrependedModule(Ruby runtime, RubyClass superClass, RubyModule origin) {
for (Map.Entry<String, DynamicMethod> entry : methods.entrySet()) {
DynamicMethod method = entry.getValue();
method.setImplementationClass(this);
method.setDefinedClass(origin);
}
}

Expand Down
7 changes: 3 additions & 4 deletions core/src/main/java/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -1886,10 +1886,10 @@ public IRubyObject newMethod(IRubyObject receiver, final String methodName, bool
}
}

RubyModule implementationModule = method.getImplementationClass();
RubyModule implementationModule = method.getDefinedClass();
RubyModule originModule = this;
while (originModule != implementationModule && originModule.isSingleton()) {
originModule = ((MetaClass)originModule).getRealClass();
while (originModule != implementationModule && (originModule.isSingleton() || originModule.isIncluded())) {
originModule = originModule.getSuperClass();
}

AbstractRubyMethod newMethod;
Expand Down Expand Up @@ -2963,7 +2963,6 @@ private void doIncludeModule(RubyModule baseModule) {
private void doPrependModule(RubyModule baseModule) {
List<RubyModule> modulesToInclude = gatherModules(baseModule);

RubyClass insertBelowSuperClass = null;
if (methodLocation == this) {
// In the current logic, if we getService here we know that module is not an
// IncludedModule, so there's no need to fish out the delegate. But just
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,12 @@
* delegation or callback mechanisms.
*/
public abstract class DynamicMethod {
/** The Ruby module or class in which this method is immediately defined. */
/** The Ruby module or class from which this method should `super`. Referred to as the `owner` in C Ruby. */
protected RubyModule implementationClass;
/** The "protected class" used for calculating protected access. */
protected RubyModule protectedClass;
/** The module or class that originally defined this method. Referred to as the `defined_class` in C Ruby. */
protected RubyModule definedClass;
/** The visibility of this method. This is the ordinal of the Visibility enum value. */
private byte visibility;
/** The serial number for this method object, to globally identify it */
Expand Down Expand Up @@ -316,6 +318,24 @@ public void setImplementationClass(RubyModule implClass) {
protectedClass = calculateProtectedClass(implClass);
}

/**
* Get the original owner of this method/
*/
public RubyModule getDefinedClass() {
RubyModule definedClass = this.definedClass;

if (definedClass != null) return definedClass;

return implementationClass;
}

/**
* Set the defining class for this method, as when restructuring hierarchy for prepend.
*/
public void setDefinedClass(RubyModule definedClass) {
this.definedClass = definedClass;
}

/**
* Get the visibility of this method.
*
Expand Down

0 comments on commit 9c49a58

Please sign in to comment.