/**
* Copyright (c) 2012-2016 André Bargull
* Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms.
*
* <https://github.com/anba/es6draft>
*/
package com.github.anba.es6draft.repl.loader;
import static com.github.anba.es6draft.runtime.AbstractOperations.Construct;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Objects;
import java.util.Set;
import com.github.anba.es6draft.parser.ParserException;
import com.github.anba.es6draft.runtime.Realm;
import com.github.anba.es6draft.runtime.internal.NativeCode;
import com.github.anba.es6draft.runtime.internal.RuntimeContext;
import com.github.anba.es6draft.runtime.internal.ScriptLoader;
import com.github.anba.es6draft.runtime.modules.MalformedNameException;
import com.github.anba.es6draft.runtime.modules.ModuleRecord;
import com.github.anba.es6draft.runtime.modules.ModuleSource;
import com.github.anba.es6draft.runtime.modules.ResolutionException;
import com.github.anba.es6draft.runtime.modules.SourceIdentifier;
import com.github.anba.es6draft.runtime.modules.loader.AbstractFileModuleLoader;
import com.github.anba.es6draft.runtime.modules.loader.FileSourceIdentifier;
import com.github.anba.es6draft.runtime.types.Constructor;
import com.github.anba.es6draft.runtime.types.ScriptObject;
/**
*
*/
public class NodeModuleLoader extends AbstractFileModuleLoader<ModuleRecord> {
private final HashMap<SourceIdentifier, ModuleRecord> modules = new HashMap<>();
private final ScriptLoader scriptLoader;
private Constructor moduleConstructor;
public NodeModuleLoader(RuntimeContext context, ScriptLoader scriptLoader) {
super(context);
this.scriptLoader = scriptLoader;
}
public void setModuleConstructor(Constructor moduleConstructor) {
this.moduleConstructor = moduleConstructor;
}
/**
* Initializes this module loader.
*
* @param realm
* the realm instance
* @throws IOException
* if there was any I/O error
* @throws URISyntaxException
* the URL is not a valid URI
* @throws MalformedNameException
* if any imported module request cannot be normalized
* @throws ResolutionException
* if any export binding cannot be resolved
*/
public void initialize(Realm realm)
throws IOException, URISyntaxException, MalformedNameException, ResolutionException {
ModuleRecord module = NativeCode.loadModule(realm, "module.jsm");
Constructor moduleConstructor = NativeCode.getModuleExport(module, "default", Constructor.class);
setModuleConstructor(moduleConstructor);
}
private ScriptObject createModuleObject(NodeModuleRecord module, Realm realm) {
Path file = module.getSource().getFile();
String fileName = Objects.toString(file, "");
String dirName = file != null ? Objects.toString(file.getParent(), "") : "";
return Construct(realm.defaultContext(), moduleConstructor, fileName, dirName);
}
@Override
protected void defineModule(ModuleRecord module) {
SourceIdentifier identifier = module.getSourceCodeId();
if (modules.containsKey(identifier)) {
throw new IllegalArgumentException();
}
modules.put(identifier, module);
}
@Override
protected ModuleRecord getModule(SourceIdentifier identifier) {
return modules.get(identifier);
}
@Override
protected ModuleRecord parseModule(SourceIdentifier identifier, ModuleSource source) throws IOException {
try {
return NodeModuleRecord.ParseModule(scriptLoader, identifier, source);
} catch (ParserException e) {
// ignore
}
return NodeSourceTextModuleRecord.ParseModule(scriptLoader, identifier, source);
}
@Override
protected void linkModule(ModuleRecord module, Realm realm) {
if (module.getRealm() == null) {
if (module instanceof NodeSourceTextModuleRecord) {
((NodeSourceTextModuleRecord) module).setRealm(realm);
} else if (module instanceof NodeModuleRecord) {
ScriptObject moduleObject = createModuleObject((NodeModuleRecord) module, realm);
((NodeModuleRecord) module).setRealm(realm, moduleObject);
}
}
}
@Override
protected Set<String> getRequestedModules(ModuleRecord module) {
if (module instanceof NodeSourceTextModuleRecord) {
return ((NodeSourceTextModuleRecord) module).getRequestedModules();
}
return Collections.emptySet();
}
@Override
protected Collection<ModuleRecord> getModules() {
return Collections.unmodifiableCollection(modules.values());
}
@Override
public FileSourceIdentifier normalizeName(String unnormalizedName, SourceIdentifier referrerId)
throws MalformedNameException {
return NodeModuleResolution.resolve(getBaseDirectory(), super.normalizeName(unnormalizedName, referrerId),
unnormalizedName, referrerId);
}
}