/**
* 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.runtime.internal;
import static com.github.anba.es6draft.runtime.internal.RuntimeWorkerThreadFactory.createThreadPoolExecutor;
import static com.github.anba.es6draft.runtime.internal.RuntimeWorkerThreadFactory.createWorkerThreadPoolExecutor;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.EnumSet;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.ExecutorService;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import com.github.anba.es6draft.compiler.Compiler;
import com.github.anba.es6draft.parser.Parser;
import com.github.anba.es6draft.runtime.ExecutionContext;
import com.github.anba.es6draft.runtime.modules.ModuleLoader;
import com.github.anba.es6draft.runtime.modules.loader.FileModuleLoader;
import com.github.anba.es6draft.runtime.objects.GlobalObject;
/**
* The new runtime options and configuration class.
*/
public final class RuntimeContext {
private final ObjectAllocator<? extends GlobalObject> globalAllocator;
private final BiFunction<RuntimeContext, ScriptLoader, ? extends ModuleLoader> moduleLoader;
private final Locale locale;
private final TimeZone timeZone;
private final Path baseDirectory; // TODO: or/and URI?
// TODO: Replace with Console interface?
private Console console;
private final ScriptCache scriptCache;
private final ExecutorService executor;
private final boolean shutdownExecutorOnFinalization;
private final ExecutorService workerExecutor;
private final boolean shutdownWorkerExecutorOnFinalization;
private final BiConsumer<ExecutionContext, Throwable> workerErrorReporter;
private final Futex futex;
private final EnumSet<CompatibilityOption> options;
private final EnumSet<Parser.Option> parserOptions;
private final EnumSet<Compiler.Option> compilerOptions;
RuntimeContext(ObjectAllocator<? extends GlobalObject> globalAllocator,
BiFunction<RuntimeContext, ScriptLoader, ? extends ModuleLoader> moduleLoader, Locale locale,
TimeZone timeZone, Path baseDirectory, Console console, ScriptCache scriptCache, ExecutorService executor,
ExecutorService workerExecutor, BiConsumer<ExecutionContext, Throwable> workerErrorReporter, Futex futex,
EnumSet<CompatibilityOption> options, EnumSet<Parser.Option> parserOptions,
EnumSet<Compiler.Option> compilerOptions) {
this.globalAllocator = globalAllocator;
this.moduleLoader = moduleLoader;
this.locale = locale;
this.timeZone = timeZone;
this.baseDirectory = baseDirectory;
this.console = console;
this.scriptCache = scriptCache;
this.executor = executor != null ? executor : createThreadPoolExecutor();
this.shutdownExecutorOnFinalization = executor == null;
this.workerExecutor = workerExecutor != null ? workerExecutor : createWorkerThreadPoolExecutor();
this.shutdownWorkerExecutorOnFinalization = workerExecutor == null;
this.workerErrorReporter = workerErrorReporter;
this.futex = futex;
this.options = EnumSet.copyOf(options);
this.parserOptions = EnumSet.copyOf(parserOptions);
this.compilerOptions = EnumSet.copyOf(compilerOptions);
}
@Override
protected void finalize() throws Throwable {
if (shutdownExecutorOnFinalization)
executor.shutdown();
if (shutdownWorkerExecutorOnFinalization)
workerExecutor.shutdown();
super.finalize();
}
/**
* Returns the global object allocator for this instance.
*
* @return the global object allocator
*/
public ObjectAllocator<? extends GlobalObject> getGlobalAllocator() {
return globalAllocator;
}
/**
* Returns the module loader constructor for this instance.
*
* @return the module loader constructor
*/
public BiFunction<RuntimeContext, ScriptLoader, ? extends ModuleLoader> getModuleLoader() {
return moduleLoader;
}
/**
* Returns the locale for this instance.
*
* @return the locale
*/
public Locale getLocale() {
return locale;
}
/**
* Returns the time zone for this instance.
*
* @return the time zone
*/
public TimeZone getTimeZone() {
return timeZone;
}
/**
* Returns the base directory for this instance.
*
* @return the base directory
*/
public Path getBaseDirectory() {
return baseDirectory;
}
/**
* Returns the script cache for this instance.
*
* @return the script cache
*/
public ScriptCache getScriptCache() {
return scriptCache;
}
/**
* Returns the optional console object for this instance.
*
* @return the console object or {@code null}
*/
public Console getConsole() {
return console;
}
/**
* Sets the console object for this instance
*
* @param console
* the new console
*/
public void setConsole(Console console) {
this.console = Objects.requireNonNull(console);
}
/**
* Returns the executor service for parallel compilation.
*
* @return the executor service
*/
public ExecutorService getExecutor() {
return executor;
}
/**
* Returns the executor service for workers.
*
* @return the executor service
*/
public ExecutorService getWorkerExecutor() {
return workerExecutor;
}
/**
* Returns the worker error reporter.
*
* @return the worker error reporter
*/
public BiConsumer<ExecutionContext, Throwable> getWorkerErrorReporter() {
return workerErrorReporter;
}
/**
* Returns the futex object.
*
* @return the futex object
*/
public Futex getFutex() {
return futex;
}
/**
* Returns the compatibility options for this instance.
*
* @return the compatibility options
*/
public EnumSet<CompatibilityOption> getOptions() {
return options;
}
/**
* Returns the parser options for this instance.
*
* @return the parser options
*/
public EnumSet<Parser.Option> getParserOptions() {
return parserOptions;
}
/**
* Returns the compiler options for this instance.
*
* @return the compiler options
*/
public EnumSet<Compiler.Option> getCompilerOptions() {
return compilerOptions;
}
/**
* Builder class to create new runtime contexts.
*/
public static final class Builder {
private ObjectAllocator<? extends GlobalObject> allocator;
private BiFunction<RuntimeContext, ScriptLoader, ? extends ModuleLoader> moduleLoader;
private Locale locale;
private TimeZone timeZone;
private Path baseDirectory;
private Console console;
private ScriptCache scriptCache;
private ExecutorService executor;
private ExecutorService workerExecutor;
private BiConsumer<ExecutionContext, Throwable> workerErrorReporter;
private Futex futex;
private final EnumSet<CompatibilityOption> options = EnumSet.noneOf(CompatibilityOption.class);
private final EnumSet<Parser.Option> parserOptions = EnumSet.noneOf(Parser.Option.class);
private final EnumSet<Compiler.Option> compilerOptions = EnumSet.noneOf(Compiler.Option.class);
public Builder() {
allocator = GlobalObject::new;
moduleLoader = FileModuleLoader::new;
locale = Locale.getDefault();
timeZone = TimeZone.getDefault();
baseDirectory = Paths.get("");
scriptCache = new ScriptCache();
workerErrorReporter = (cx, e) -> {
// empty
};
futex = new Futex();
}
public Builder(RuntimeContext context) {
allocator = context.globalAllocator;
moduleLoader = context.moduleLoader;
locale = context.locale;
timeZone = context.timeZone;
baseDirectory = context.baseDirectory;
console = context.console;
scriptCache = context.scriptCache;
executor = context.executor;
workerExecutor = context.workerExecutor;
workerErrorReporter = context.workerErrorReporter;
futex = context.futex;
options.addAll(context.options);
parserOptions.addAll(context.parserOptions);
compilerOptions.addAll(context.compilerOptions);
}
/**
* Returns a new {@link RuntimeContext} using the fields set by this builder.
*
* @return the new runtime context
*/
public RuntimeContext build() {
return new RuntimeContext(allocator, moduleLoader, locale, timeZone, baseDirectory, console, scriptCache,
executor, workerExecutor, workerErrorReporter, futex, options, parserOptions, compilerOptions);
}
/**
* Sets the global object allocator.
*
* @param allocator
* the global object allocator
* @return this builder
*/
public Builder setGlobalAllocator(ObjectAllocator<? extends GlobalObject> allocator) {
this.allocator = Objects.requireNonNull(allocator);
return this;
}
/**
* Sets the module loader constructor.
*
* @param moduleLoader
* the module loader constructor
* @return this builder
*/
public Builder setModuleLoader(BiFunction<RuntimeContext, ScriptLoader, ? extends ModuleLoader> moduleLoader) {
this.moduleLoader = Objects.requireNonNull(moduleLoader);
return this;
}
/**
* Sets the locale.
*
* @param locale
* the locale
* @return this builder
*/
public Builder setLocale(Locale locale) {
this.locale = Objects.requireNonNull(locale);
return this;
}
/**
* Sets the time zone.
*
* @param timeZone
* the time zone
* @return this builder
*/
public Builder setTimeZone(TimeZone timeZone) {
this.timeZone = Objects.requireNonNull(timeZone);
return this;
}
/**
* Sets the base directory
*
* @param baseDirectory
* the base directory
* @return this builder
*/
public Builder setBaseDirectory(Path baseDirectory) {
this.baseDirectory = Objects.requireNonNull(baseDirectory);
return this;
}
/**
* Sets the script cache.
*
* @param scriptCache
* the script cache
* @return this builder
*/
public Builder setScriptCache(ScriptCache scriptCache) {
this.scriptCache = Objects.requireNonNull(scriptCache);
return this;
}
/**
* Sets the console.
*
* @param console
* the console
* @return this builder
*/
public Builder setConsole(Console console) {
this.console = Objects.requireNonNull(console);
return this;
}
/**
* Sets the executor.
*
* @param executor
* the executor
* @return this builder
*/
public Builder setExecutor(ExecutorService executor) {
this.executor = executor; // null allowed
return this;
}
/**
* Sets the executor for shared workers.
*
* @param executor
* the executor
* @return this builder
*/
public Builder setWorkerExecutor(ExecutorService executor) {
this.workerExecutor = executor; // null allowed
return this;
}
/**
* Sets the worker error reporter.
*
* @param workerErrorReporter
* the worker error reporter
* @return this builder
*/
public Builder setWorkerErrorReporter(BiConsumer<ExecutionContext, Throwable> workerErrorReporter) {
this.workerErrorReporter = Objects.requireNonNull(workerErrorReporter);
return this;
}
/**
* Sets the futex object.
*
* @param futex
* the futex object
* @return this builder
*/
public Builder setFutex(Futex futex) {
this.futex = Objects.requireNonNull(futex);
return this;
}
/**
* Sets the compatibility options.
*
* @param options
* the compatibility options
* @return this builder
*/
public Builder setOptions(Set<CompatibilityOption> options) {
this.options.clear();
this.options.addAll(options);
return this;
}
/**
* Sets the parser options.
*
* @param options
* the parser options
* @return this builder
*/
public Builder setParserOptions(Set<Parser.Option> options) {
this.parserOptions.clear();
this.parserOptions.addAll(options);
return this;
}
/**
* Sets the compiler options.
*
* @param options
* the compiler options
* @return this builder
*/
public Builder setCompilerOptions(Set<Compiler.Option> options) {
this.compilerOptions.clear();
this.compilerOptions.addAll(options);
return this;
}
}
}