Skip to content

Commit

Permalink
Generalize RhinoBasedRun.
Browse files Browse the repository at this point in the history
It can now use any object for the console (or none), which means
it is not tight to an sbt logger anymore.

It can also run a main method in a top-level object.
  • Loading branch information
sjrd committed Dec 14, 2013
1 parent 999deb1 commit ec9992a
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 14 deletions.
Expand Up @@ -31,14 +31,6 @@ object RhinoBasedRun {
private implicit def context2ops(ctx: Context): ContextOps =
new ContextOps(ctx)

/** A proxy for a Logger that looks like a Mozilla console object */
private class LoggingConsole(logger: Logger) {
def log(x: Any): Unit = logger.info(x.toString)
def info(x: Any): Unit = logger.info(x.toString)
def warn(x: Any): Unit = logger.warn(x.toString)
def error(x: Any): Unit = logger.error(x.toString)
}

/** A proxy for a ScalaJS "scope" field that loads scripts lazily
*
* E.g., ScalaJS.c, which is a scope with the Scala.js classes, can be
Expand Down Expand Up @@ -133,15 +125,20 @@ object RhinoBasedRun {
* scripts in the sequence to load them lazily, the first time they are
* required.
*/
def scalaJSRunJavaScript(logger: Logger, inputs: Seq[File],
def scalaJSRunJavaScript(inputs: Seq[File], trace: (=> Throwable) => Unit,
console: Option[AnyRef],
useLazyScalaJSScopes: Boolean = false,
scalaJSClasspath: Seq[File] = Nil): Unit = {
scalaJSClasspath: Seq[File] = Nil,
mainClass: Option[String] = None,
arguments: Array[String] = Array[String]()): Unit = {
val ctx = Context.enter()
try {
val scope = ctx.initStandardObjects()

ScriptableObject.putProperty(scope, "console",
Context.javaToJS(new LoggingConsole(logger), scope))
console foreach { consoleObject =>
ScriptableObject.putProperty(scope, "console",
Context.javaToJS(consoleObject, scope))
}

try {
if (!useLazyScalaJSScopes ||
Expand All @@ -153,9 +150,11 @@ object RhinoBasedRun {
// The smart thing that hijacks ScalaJS-related things
runJavaScriptWithLazyScalaJSScopes(ctx, scope, inputs, scalaJSClasspath)
}

mainClass foreach (runMainClass(ctx, scope, _, arguments))
} catch {
case e: Exception =>
logger.trace(e) // print the stack trace while we're in the Context
trace(e) // print the stack trace while we're in the Context
throw new RuntimeException("Exception while running JS code", e)
}
} finally {
Expand Down Expand Up @@ -219,4 +218,16 @@ object RhinoBasedRun {
}
}
}

private def runMainClass(ctx: Context, scope: Scriptable,
mainClass: String, arguments: Array[String]): Unit = {

val moduleFieldName = mainClass.replace("_", "$und").replace(".", "_")

val script = s"""ScalaJS.modules.$moduleFieldName().main__AT__V(
ScalaJS.makeNativeArrayWrapper(
ScalaJS.data.java_lang_String.getArrayOf(), []))"""

ctx.evaluateString(scope, script, "<top-level>", 1, null)
}
}
Expand Up @@ -88,6 +88,14 @@ object ScalaJSPlugin extends Plugin {
var global = {};
"""

/** A proxy for a Logger that looks like a Mozilla console object */
private class LoggingConsole(logger: Logger) {
def log(x: Any): Unit = logger.info(x.toString)
def info(x: Any): Unit = logger.info(x.toString)
def warn(x: Any): Unit = logger.warn(x.toString)
def error(x: Any): Unit = logger.error(x.toString)
}

val scalaJSExternalCompileConfigSettings: Seq[Setting[_]] = inTask(compile)(
Defaults.runnerTask
) ++ Seq(
Expand Down Expand Up @@ -450,7 +458,8 @@ object ScalaJSPlugin extends Plugin {
sources: TaskKey[Seq[File]], classpath: TaskKey[Classpath]) = Def.task {
val s = streams.value
s.log.info("Running ...")
scalaJSRunJavaScript(s.log, sources.value, true,
val console = new LoggingConsole(s.log)
scalaJSRunJavaScript(sources.value, s.log.trace, Some(console), true,
classpath.value.map(_.data))
}

Expand Down

0 comments on commit ec9992a

Please sign in to comment.