Skip to content

Commit

Permalink
Re-revert previous fix attempt and then replace const_defined? impl w…
Browse files Browse the repository at this point in the history
…ith the old 1.9 one since we had a 2.x impl in there
enebo committed Apr 24, 2017
1 parent c4198ee commit 45047a7
Showing 3 changed files with 102 additions and 45 deletions.
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/IncludedModuleWrapper.java
Original file line number Diff line number Diff line change
@@ -230,8 +230,8 @@ public Collection<String> getConstantNames(boolean includePrivate) {
}

@Override
public IRubyObject getAutoloadConstant(String name) {
return delegate.getAutoloadConstant(name);
protected IRubyObject getAutoloadConstant(String name, boolean forceLoad) {
return delegate.getAutoloadConstant(name, forceLoad);
}

/** The module to which this include delegates. */
138 changes: 98 additions & 40 deletions core/src/main/java/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
@@ -53,6 +53,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

import org.jcodings.Encoding;
import org.jruby.anno.AnnotationBinder;
import org.jruby.anno.AnnotationHelper;
import org.jruby.anno.FrameField;
@@ -2647,17 +2648,36 @@ public IRubyObject const_get_1_9(ThreadContext context, IRubyObject[] args) {

@JRubyMethod(name = "const_get", required = 1, optional = 1, compat = CompatVersion.RUBY2_0)
public IRubyObject const_get_2_0(ThreadContext context, IRubyObject[] args) {
String symbol = args[0].asJavaString();
boolean inherit = args.length == 1 || (!args[1].isNil() && args[1].isTrue());
final Ruby runtime = context.runtime;
boolean inherit = args.length == 1 || ( ! args[1].isNil() && args[1].isTrue() );

final IRubyObject symbol = args[0];
final String fullName = symbol.asJavaString();
String name = fullName;

int sep = name.indexOf("::");
// symbol form does not allow ::
if (symbol instanceof RubySymbol && sep != -1) {
throw runtime.newNameError("wrong constant name", name);
}

RubyModule mod = this;
int sep;
while((sep = symbol.indexOf("::")) != -1) {
String segment = symbol.substring(0, sep);
symbol = symbol.substring(sep + 2);
IRubyObject obj = mod.getConstant(validateConstant(segment), inherit, inherit);
if(obj instanceof RubyModule) {
mod = (RubyModule)obj;

if (sep == 0) { // ::Foo::Bar
mod = runtime.getObject();
name = name.substring(2);
}

// Bare ::
if (name.length() == 0) {
throw runtime.newNameError("wrong constant name ", fullName);
}

while ( ( sep = name.indexOf("::") ) != -1 ) {
final String segment = name.substring(0, sep);
IRubyObject obj = mod.getConstant(validateConstant(segment, symbol), inherit, inherit);
if (obj instanceof RubyModule) {
mod = (RubyModule) obj;
} else {
throw getRuntime().newTypeError(segment + " does not refer to class/module");
}
@@ -2988,11 +3008,13 @@ public IRubyObject getConstant(String name, boolean inherit) {
}

public IRubyObject getConstant(String name, boolean inherit, boolean includeObject) {
assert IdUtil.isConstant(name);

IRubyObject value = getConstantNoConstMissing(name, inherit, includeObject);
Ruby runtime = getRuntime();

return value == null ? callMethod(runtime.getCurrentContext(), "const_missing",
runtime.newSymbol(name)) : value;
return value != null ? value :
callMethod(runtime.getCurrentContext(), "const_missing", runtime.newSymbol(name));
}

@Deprecated
@@ -3014,23 +3036,35 @@ public IRubyObject getConstantNoConstMissing(String name, boolean inherit) {
}

public IRubyObject getConstantNoConstMissing(String name, boolean inherit, boolean includeObject) {
assert IdUtil.isConstant(name);
IRubyObject constant = iterateConstantNoConstMissing(name, this, inherit, true);

if (constant == null && !isClass() && includeObject) {
constant = iterateConstantNoConstMissing(name, getRuntime().getObject(), inherit, true);
}

IRubyObject constant = iterateConstantNoConstMissing(name, this, inherit);
return constant;
}

// returns UNDEF for un-loaded autoload constants
private IRubyObject getConstantSkipAutoload(String name, boolean inherit, boolean includeObject) {
IRubyObject constant = iterateConstantNoConstMissing(name, this, inherit, false);

if (constant == null && !isClass() && includeObject) {
constant = iterateConstantNoConstMissing(name, getRuntime().getObject(), inherit);
constant = iterateConstantNoConstMissing(name, getRuntime().getObject(), inherit, false);
}

return constant;
}

private IRubyObject iterateConstantNoConstMissing(String name, RubyModule init, boolean inherit) {
for (RubyModule p = init; p != null; p = p.getSuperClass()) {
IRubyObject value = p.getConstantAt(name);
private static IRubyObject iterateConstantNoConstMissing(String name,
RubyModule init, boolean inherit, boolean loadConstant) {
for (RubyModule mod = init; mod != null; mod = mod.getSuperClass()) {
final IRubyObject value = mod.fetchConstant(name, true);

if (value != null) return value == UNDEF ? null : value;
if (!inherit) break;
if ( value == UNDEF ) return mod.getAutoloadConstant(name, loadConstant);
if ( value != null ) return value;

if ( ! inherit ) break;
}
return null;
}
@@ -3053,28 +3087,25 @@ public IRubyObject getConstantFromNoConstMissing(String name) {

public IRubyObject getConstantFromNoConstMissing(String name, boolean includePrivate) {
assert name == name.intern() : name + " is not interned";
assert IdUtil.isConstant(name);
Ruby runtime = getRuntime();
RubyClass objectClass = runtime.getObject();
IRubyObject value;

RubyModule p = this;
final Ruby runtime = getRuntime();
final RubyClass objectClass = runtime.getObject();

while (p != null) {
if ((value = p.fetchConstant(name, false)) != null) {
if (value == UNDEF) {
return p.resolveUndefConstant(name);
}
RubyModule mod = this; IRubyObject value;

while ( mod != null ) {
if ( ( value = mod.fetchConstant(name, includePrivate) ) != null ) {
if ( value == UNDEF ) return mod.resolveUndefConstant(name);

if (p == objectClass && this != objectClass) {
if ( mod == objectClass && this != objectClass ) {
String badCName = getName() + "::" + name;
runtime.getWarnings().warn(ID.CONSTANT_BAD_REFERENCE, "toplevel constant " +
name + " referenced by " + badCName);
runtime.getWarnings().warn(ID.CONSTANT_BAD_REFERENCE,
"toplevel constant " + name + " referenced by " + badCName);
}

return value;
}
p = p.getSuperClass();
mod = mod.getSuperClass();
}
return null;
}
@@ -3094,7 +3125,7 @@ public IRubyObject fastGetConstantFromConstMissing(String internedName) {
return getConstantFromConstMissing(internedName);
}

public IRubyObject resolveUndefConstant(String name) {
public final IRubyObject resolveUndefConstant(String name) {
return getAutoloadConstant(name);
}

@@ -3542,6 +3573,30 @@ protected final String validateConstant(String name) {
throw getRuntime().newNameError("wrong constant name " + name, name);
}

protected final String validateConstant(IRubyObject name) {
return validateConstant(name.asJavaString(), name);
}

protected final String validateConstant(String name, IRubyObject errorName) {
if (IdUtil.isValidConstantName19(name)) return name;

Ruby runtime = getRuntime();

Encoding resultEncoding = runtime.getDefaultInternalEncoding();
if (resultEncoding == null) resultEncoding = runtime.getDefaultExternalEncoding();

// MRI is more complicated than this and distinguishes between ID and non-ID.
RubyString nameString = errorName.asString();

// MRI does strlen to check for \0 vs Ruby string length.
if ((nameString.getEncoding() != resultEncoding && !nameString.isAsciiOnly()) ||
nameString.toString().indexOf('\0') > -1 ) {
nameString = (RubyString) nameString.inspect();
}

throw getRuntime().newNameError("wrong constant name " + nameString, name);
}

protected final void ensureConstantsSettable() {
if (isFrozen()) throw getRuntime().newFrozenError(ERR_FROZEN_CONST_TYPE);
}
@@ -3609,12 +3664,15 @@ protected IRubyObject finishAutoload(String name) {
* If it's first resolution for the constant, it tries to require the defined feature and returns the defined value.
* Multi-threaded accesses are blocked and processed sequentially except if the caller is the autoloading thread.
*/
public IRubyObject getAutoloadConstant(String name) {
Autoload autoload = getAutoloadMap().get(name);
if (autoload == null) {
return null;
}
return autoload.getConstant(getRuntime().getCurrentContext());
public final IRubyObject getAutoloadConstant(String name) {
return getAutoloadConstant(name, true);
}

protected IRubyObject getAutoloadConstant(String name, boolean loadConstant) {
final Autoload autoload = getAutoloadMap().get(name);
if ( autoload == null ) return null;
if ( ! loadConstant ) return UNDEF;
return autoload.getConstant( getRuntime().getCurrentContext() );
}

/**
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
* rights and limitations under the License.
*
* Copyright (C) 2002 Jan Arne Petersen <jpetersen@uni-bonn.de>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -28,10 +28,9 @@
package org.jruby.runtime.load;

import org.jruby.Ruby;
import org.jruby.runtime.builtin.IRubyObject;

/**
*
*
* @author jpetersen
*/
public interface IAutoloadMethod {

0 comments on commit 45047a7

Please sign in to comment.