Skip to content

Commit

Permalink
Merge pull request #5489 from headius/module_autoload
Browse files Browse the repository at this point in the history
Autoload fixes
  • Loading branch information
enebo committed Feb 11, 2019
2 parents fb1e542 + b0feb09 commit 915e9db
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 117 deletions.
10 changes: 10 additions & 0 deletions core/src/main/java/org/jruby/IncludedModuleWrapper.java
Expand Up @@ -186,6 +186,16 @@ protected IRubyObject constantTableRemove(String name) {
return origin.constantTableRemove(name);
}

@Override
protected Map<String, Autoload> getAutoloadMap() {
return origin.getAutoloadMap();
}

@Override
protected synchronized Map<String, Autoload> getAutoloadMapForWrite() {
return origin.getAutoloadMapForWrite();
}

@Override
@Deprecated
public List<String> getStoredConstantNameList() {
Expand Down
64 changes: 23 additions & 41 deletions core/src/main/java/org/jruby/RubyKernel.java
Expand Up @@ -62,9 +62,11 @@
import org.jruby.exceptions.CatchThrow;
import org.jruby.exceptions.MainExitException;
import org.jruby.exceptions.RaiseException;
import org.jruby.exceptions.TypeError;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.internal.runtime.methods.JavaMethod.JavaMethodNBlock;
import org.jruby.ir.interpreter.Interpreter;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.java.proxies.ConcreteJavaProxy;
import org.jruby.platform.Platform;
import org.jruby.runtime.Arity;
Expand Down Expand Up @@ -165,66 +167,46 @@ static void recacheBuiltinMethods(Ruby runtime) {
runtime.setRespondToMissingMethod(module.searchMethod("respond_to_missing?"));
}

@JRubyMethod(module = true, visibility = PRIVATE)
@JRubyMethod(module = true, visibility = PRIVATE, reads = {CLASS})
public static IRubyObject at_exit(ThreadContext context, IRubyObject recv, Block block) {
return context.runtime.pushExitBlock(context.runtime.newProc(Block.Type.PROC, block));
}

@JRubyMethod(name = "autoload?", required = 1, module = true, visibility = PRIVATE)
@JRubyMethod(name = "autoload?", required = 1, module = true, visibility = PRIVATE, reads = {CLASS})
public static IRubyObject autoload_p(ThreadContext context, final IRubyObject recv, IRubyObject symbol) {
final Ruby runtime = context.runtime;
final RubyModule module = getModuleForAutoload(runtime, recv);
final RubyString file = module.getAutoloadFile(symbol.asJavaString());
return file == null ? context.nil : file;
}

@JRubyMethod(required = 2, module = true, visibility = PRIVATE)
public static IRubyObject autoload(ThreadContext context, final IRubyObject recv, IRubyObject symbol, IRubyObject file) {
final Ruby runtime = context.runtime;
final String nonInternedName = symbol.asJavaString();
final RubyModule module = getModuleForAutoload(context, recv);

if (!IdUtil.isValidConstantName(nonInternedName)) {
throw runtime.newNameError("autoload must be constant name", nonInternedName);
if (module == null) {
return context.nil;
}

final RubyString fileString =
StringSupport.checkEmbeddedNulls(runtime, RubyFile.get_path(context, file));

if (fileString.isEmpty()) throw runtime.newArgumentError("empty file name");

final String baseName = nonInternedName.intern(); // interned, OK for "fast" methods
final RubyModule module = getModuleForAutoload(runtime, recv);

IRubyObject existingValue = module.fetchConstant(baseName);
if (existingValue != null && existingValue != RubyObject.UNDEF) return context.nil;
return module.autoload_p(context, symbol);
}

module.defineAutoload(baseName, new RubyModule.AutoloadMethod() {
@JRubyMethod(required = 2, module = true, visibility = PRIVATE, reads = {CLASS})
public static IRubyObject autoload(ThreadContext context, final IRubyObject recv, IRubyObject symbol, IRubyObject file) {
final RubyModule module = getModuleForAutoload(context, recv);

public RubyString getFile() { return fileString; }
if (module == null) {
throw context.runtime.newTypeError("Can not set autoload on singleton class");
}

public void load(final Ruby runtime) {
final String file = getFile().asJavaString();
if (runtime.getLoadService().autoloadRequire(file)) {
// Do not finish autoloading by cyclic autoload
module.finishAutoload(baseName);
}
}
});
return context.nil;
return module.autoload(context, symbol, file);
}

@Deprecated
public static IRubyObject autoload(final IRubyObject recv, IRubyObject symbol, IRubyObject file) {
return autoload(recv.getRuntime().getCurrentContext(), recv, symbol, file);
}

static RubyModule getModuleForAutoload(Ruby runtime, IRubyObject recv) {
RubyModule module = recv instanceof RubyModule ? (RubyModule) recv : recv.getMetaClass().getRealClass();
if (module == runtime.getKernel()) {
// special behavior if calling Kernel.autoload directly
module = runtime.getObject().getSingletonClass();
static RubyModule getModuleForAutoload(ThreadContext context, IRubyObject recv) {
RubyModule target = IRRuntimeHelpers.findInstanceMethodContainer(context, context.getCurrentScope(), recv);

while (target != null && (target.isSingleton() || target.isIncluded())) {
target = target.getSuperClass();
}
return module;

return target;
}

public static IRubyObject method_missing(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
Expand Down

0 comments on commit 915e9db

Please sign in to comment.