summaryrefslogtreecommitdiff
path: root/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs
diff options
context:
space:
mode:
Diffstat (limited to 'examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs')
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/AbstractJSDeps.scala81
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/Implicits.scala34
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/JSUtils.scala35
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/LoggerJSConsole.scala18
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/OptimizerOptions.scala74
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/ScalaJSCrossVersion.scala48
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/ScalaJSPlugin.scala179
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/ScalaJSPluginInternal.scala598
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/Stage.scala18
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/ExternalJSEnv.scala200
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/VirtualFileMaterializer.scala67
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/nodejs/NodeJSEnv.scala306
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/JettyWebsocketManager.scala126
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/PhantomJSEnv.scala466
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/PhantomJettyClassLoader.scala63
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/WebsocketListener.scala10
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/WebsocketManager.scala10
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/LazyScalaJSScope.scala96
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/RhinoJSEnv.scala303
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/ScalaJSCoreLib.scala173
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/package.scala42
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/impl/DependencyBuilders.scala99
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/Events.scala35
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/JSClasspathLoader.scala15
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/SbtTestLoggerAccWrapper.scala22
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestException.scala9
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestFramework.scala52
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestOutputConsole.scala190
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestRunner.scala37
-rw-r--r--examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestTask.scala110
30 files changed, 0 insertions, 3516 deletions
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/AbstractJSDeps.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/AbstractJSDeps.scala
deleted file mode 100644
index 9eb7f69..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/AbstractJSDeps.scala
+++ /dev/null
@@ -1,81 +0,0 @@
-package scala.scalajs.sbtplugin
-
-import sbt._
-
-import StringUtilities.nonEmpty
-
-import scala.scalajs.tools.jsdep.JSDependency
-
-/** Something JavaScript related a project may depend on. Either a JavaScript
- * module/library, or the DOM at runtime. */
-sealed trait AbstractJSDep {
- def configurations: Option[String]
-
- protected def withConfigs(configs: Option[String]): AbstractJSDep
-
- def %(configurations: Configuration): AbstractJSDep = %(configurations.name)
- def %(configurations: String): AbstractJSDep = {
- require(this.configurations.isEmpty,
- "Configurations already specified for jsModule " + this)
- nonEmpty(configurations, "Configurations")
- withConfigs(Some(configurations))
- }
-
-}
-
-/** A JavaScript module/library a Scala.js project may depend on */
-sealed trait JSModuleID extends AbstractJSDep {
- def jsDep: JSDependency
-
- protected def withJSDep(jsDep: JSDependency): JSModuleID
-
- def commonJSName(name: String): JSModuleID =
- withJSDep(jsDep = jsDep.commonJSName(name))
-
- def dependsOn(names: String*): JSModuleID =
- withJSDep(jsDep = jsDep.dependsOn(names: _*))
-}
-
-/** A JavaScript module that resides inside a jar (probably webjar) */
-final case class JarJSModuleID(
- module: ModuleID,
- jsDep: JSDependency) extends JSModuleID {
-
- def configurations: Option[String] = module.configurations
-
- protected def withConfigs(configs: Option[String]): JSModuleID =
- copy(module = module.copy(configurations = configs))
- protected def withJSDep(jsDep: JSDependency): JSModuleID =
- copy(jsDep = jsDep)
-}
-
-object JarJSModuleID {
- def apply(module: ModuleID, name: String): JarJSModuleID =
- JarJSModuleID(module, new JSDependency(name, Nil))
-}
-
-/** A JavaScript module that we depend on, but is provided externally or
- * by the project itself */
-final case class ProvidedJSModuleID(
- jsDep: JSDependency,
- configurations: Option[String]) extends JSModuleID {
-
- protected def withConfigs(configs: Option[String]): JSModuleID =
- copy(configurations = configs)
- protected def withJSDep(jsDep: JSDependency): JSModuleID =
- copy(jsDep = jsDep)
-}
-
-object ProvidedJSModuleID {
- def apply(name: String, configurations: Option[String]): ProvidedJSModuleID =
- ProvidedJSModuleID(new JSDependency(name, Nil), configurations)
-}
-
-sealed case class RuntimeDOM(
- configurations: Option[String]) extends AbstractJSDep {
-
- protected def withConfigs(configs: Option[String]): RuntimeDOM =
- copy(configurations = configs)
-}
-
-object RuntimeDOM extends RuntimeDOM(None)
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/Implicits.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/Implicits.scala
deleted file mode 100644
index 0c1559f..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/Implicits.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-package scala.scalajs.sbtplugin
-
-import scala.language.implicitConversions
-
-import scala.scalajs.tools.logging._
-import sbt.{Logger => SbtLogger, Level => SbtLevel}
-
-object Implicits {
- private class SbtLoggerWrapper(underlying: SbtLogger) extends Logger {
- def log(level: Level, message: => String): Unit =
- underlying.log(level, message)
- def success(message: => String): Unit =
- underlying.success(message)
- def trace(t: => Throwable): Unit =
- underlying.trace(t)
- }
-
- implicit def sbtLogger2ToolsLogger(logger: SbtLogger): Logger =
- new SbtLoggerWrapper(logger)
-
- implicit def sbtLevel2ToolsLevel(level: SbtLevel.Value): Level = level match {
- case SbtLevel.Error => Level.Error
- case SbtLevel.Warn => Level.Warn
- case SbtLevel.Info => Level.Info
- case SbtLevel.Debug => Level.Debug
- }
-
- implicit def toolsLevel2sbtLevel(level: Level): SbtLevel.Value = level match {
- case Level.Error => SbtLevel.Error
- case Level.Warn => SbtLevel.Warn
- case Level.Info => SbtLevel.Info
- case Level.Debug => SbtLevel.Debug
- }
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/JSUtils.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/JSUtils.scala
deleted file mode 100644
index a59f105..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/JSUtils.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package scala.scalajs.sbtplugin
-
-object JSUtils {
- def listToJS(xs: List[String]): String =
- xs.map(toJSstr _).mkString("[",",","]")
-
- /** (almost) stolen from scala.scalajs.compiler.JSPrinters */
- def toJSstr(str: String): String = {
- /* Note that Java and JavaScript happen to use the same encoding for
- * Unicode, namely UTF-16, which means that 1 char from Java always equals
- * 1 char in JavaScript. */
- val builder = new StringBuilder()
- builder.append('"')
- str foreach {
- case '\\' => builder.append("\\\\")
- case '"' => builder.append("\\\"")
- case '\u0007' => builder.append("\\a")
- case '\u0008' => builder.append("\\b")
- case '\u0009' => builder.append("\\t")
- case '\u000A' => builder.append("\\n")
- case '\u000B' => builder.append("\\v")
- case '\u000C' => builder.append("\\f")
- case '\u000D' => builder.append("\\r")
- case c =>
- if (c >= 32 && c <= 126) builder.append(c.toChar) // ASCII printable characters
- else builder.append(f"\\u$c%04x")
- }
- builder.append('"')
- builder.result()
- }
-
- def dot2bracket(name: String): String = {
- name.split('.').map(s => s"""[${toJSstr(s)}]""").mkString
- }
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/LoggerJSConsole.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/LoggerJSConsole.scala
deleted file mode 100644
index ecfb546..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/LoggerJSConsole.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin
-
-import sbt.Logger
-import scala.scalajs.tools.env.JSConsole
-
-/** A proxy for a Logger that looks like a Mozilla console object */
-class LoggerJSConsole(logger: Logger) extends JSConsole {
- def log(msg: Any): Unit = logger.info(msg.toString)
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/OptimizerOptions.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/OptimizerOptions.scala
deleted file mode 100644
index 25d6178..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/OptimizerOptions.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin
-
-import OptimizerOptions._
-
-/** Various options for the Scala.js optimizer tool chain
- *
- * This is not a case class and does have a private constructor so that we
- * can add fields in a binary-compatible manner.
- *
- * Use [[OptimizerOptions.apply]] and the `with` methods to create a configured
- * instance.
- */
-final class OptimizerOptions private (
- /** Whether to parallelize the optimizer (currently fastOptJS only) **/
- val parallel: Boolean = true,
- /** Whether to run the optimizer in batch (i.e. non-incremental) mode */
- val batchMode: Boolean = false,
- /** Whether to run the Scala.js optimizer */
- val disableOptimizer: Boolean = false,
- /** Whether to pretty-print in fullOptJS */
- val prettyPrintFullOptJS: Boolean = false,
- /** Perform expensive checks of the sanity of the Scala.js IR */
- val checkScalaJSIR: Boolean = false
-) {
-
- def withParallel(parallel: Boolean): OptimizerOptions = {
- new OptimizerOptions(parallel, batchMode,
- disableOptimizer, prettyPrintFullOptJS, checkScalaJSIR)
- }
-
- def withBatchMode(batchMode: Boolean): OptimizerOptions = {
- new OptimizerOptions(parallel, batchMode,
- disableOptimizer, prettyPrintFullOptJS, checkScalaJSIR)
- }
-
- def withDisableOptimizer(disableOptimizer: Boolean): OptimizerOptions = {
- new OptimizerOptions(parallel, batchMode,
- disableOptimizer, prettyPrintFullOptJS, checkScalaJSIR)
- }
-
- def withPrettyPrintFullOptJS(prettyPrintFullOptJS: Boolean): OptimizerOptions = {
- new OptimizerOptions(parallel, batchMode,
- disableOptimizer, prettyPrintFullOptJS, checkScalaJSIR)
- }
-
- def withCheckScalaJSIR(checkScalaJSIR: Boolean): OptimizerOptions = {
- new OptimizerOptions(parallel, batchMode,
- disableOptimizer, prettyPrintFullOptJS, checkScalaJSIR)
- }
-
- override def toString: String = {
- s"""OptimizerOptions(
- | parallel = $parallel
- | batchMode = $batchMode
- | disableOptimizer = $disableOptimizer
- | prettyPrintFullOptJS = $prettyPrintFullOptJS
- | checkScalaJSIR = $checkScalaJSIR
- |)""".stripMargin
- }
-
-}
-
-object OptimizerOptions {
- def apply() = new OptimizerOptions()
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/ScalaJSCrossVersion.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/ScalaJSCrossVersion.scala
deleted file mode 100644
index d813622..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/ScalaJSCrossVersion.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin
-
-import sbt._
-
-import scala.scalajs.ir.ScalaJSVersions
-
-object ScalaJSCrossVersion {
- private val scalaJSVersionUnmapped: String => String =
- _ => s"sjs$currentBinaryVersion"
-
- private val scalaJSVersionMap: String => String =
- version => s"sjs${currentBinaryVersion}_$version"
-
- private final val ReleaseVersion =
- raw"""(\d+)\.(\d+)\.(\d+)""".r
- private final val MinorSnapshotVersion =
- raw"""(\d+)\.(\d+)\.([1-9]\d*)-SNAPSHOT""".r
-
- val currentBinaryVersion = binaryScalaJSVersion(ScalaJSVersions.current)
-
- def binaryScalaJSVersion(full: String): String = full match {
- case ReleaseVersion(major, minor, release) => s"$major.$minor"
- case MinorSnapshotVersion(major, minor, _) => s"$major.$minor"
- case _ => full
- }
-
- def scalaJSMapped(cross: CrossVersion): CrossVersion = cross match {
- case CrossVersion.Disabled =>
- CrossVersion.binaryMapped(scalaJSVersionUnmapped)
- case cross: CrossVersion.Binary =>
- CrossVersion.binaryMapped(cross.remapVersion andThen scalaJSVersionMap)
- case cross: CrossVersion.Full =>
- CrossVersion.fullMapped(cross.remapVersion andThen scalaJSVersionMap)
- }
-
- def binary: CrossVersion = scalaJSMapped(CrossVersion.binary)
-
- def full: CrossVersion = scalaJSMapped(CrossVersion.full)
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/ScalaJSPlugin.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/ScalaJSPlugin.scala
deleted file mode 100644
index b33e2fb..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/ScalaJSPlugin.scala
+++ /dev/null
@@ -1,179 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin
-
-import sbt._
-
-import scala.scalajs.tools.sem.Semantics
-import scala.scalajs.tools.classpath._
-import scala.scalajs.tools.io.VirtualJSFile
-import scala.scalajs.tools.env.{JSEnv, JSConsole}
-import scala.scalajs.tools.optimizer.ScalaJSOptimizer
-
-import scala.scalajs.ir.ScalaJSVersions
-
-import scala.scalajs.sbtplugin.env.nodejs.NodeJSEnv
-import scala.scalajs.sbtplugin.env.phantomjs.PhantomJSEnv
-
-object ScalaJSPlugin extends AutoPlugin {
- override def requires = plugins.JvmPlugin
-
- object autoImport extends impl.DependencyBuilders {
- import KeyRanks._
-
- // Some constants
- val scalaJSVersion = ScalaJSVersions.current
- val scalaJSIsSnapshotVersion = ScalaJSVersions.currentIsSnapshot
- val scalaJSBinaryVersion = ScalaJSCrossVersion.currentBinaryVersion
-
- // Stage values
- val PreLinkStage = Stage.PreLink
- val FastOptStage = Stage.FastOpt
- val FullOptStage = Stage.FullOpt
-
- // Factory methods for JSEnvs
-
- /**
- * Creates a [[Def.Initialize]] for a NodeJSEnv. Use this to explicitly
- * specify in your build that you would like to run with Node.js:
- *
- * {{{
- * postLinkJSEnv := NodeJSEnv().value
- * }}}
- *
- * Note that the resulting [[Setting]] is not scoped at all, but must be
- * scoped in a project that has the ScalaJSPlugin enabled to work properly.
- * Therefore, either put the upper line in your project settings (common
- * case) or scope it manually, using [[Project.inScope]].
- */
- def NodeJSEnv(
- executable: String = "node",
- args: Seq[String] = Seq.empty,
- env: Map[String, String] = Map.empty
- ): Def.Initialize[Task[NodeJSEnv]] = Def.task {
- new NodeJSEnv(executable, args, env)
- }
-
- /**
- * Creates a [[Def.Initialize]] for a PhantomJSEnv. Use this to explicitly
- * specify in your build that you would like to run with PhantomJS:
- *
- * {{{
- * postLinkJSEnv := PhantomJSEnv().value
- * }}}
- *
- * Note that the resulting [[Setting]] is not scoped at all, but must be
- * scoped in a project that has the ScalaJSPlugin enabled to work properly.
- * Therefore, either put the upper line in your project settings (common
- * case) or scope it manually, using [[Project.inScope]].
- */
- def PhantomJSEnv(
- executable: String = "phantomjs",
- args: Seq[String] = Seq.empty,
- env: Map[String, String] = Map.empty,
- autoExit: Boolean = true
- ): Def.Initialize[Task[PhantomJSEnv]] = Def.task {
- val loader = scalaJSPhantomJSClassLoader.value
- new PhantomJSEnv(executable, args, env, autoExit, loader)
- }
-
- // All our public-facing keys
-
- val fastOptJS = TaskKey[Attributed[File]]("fastOptJS",
- "Quickly link all compiled JavaScript into a single file", APlusTask)
- val fullOptJS = TaskKey[Attributed[File]]("fullOptJS",
- "Link all compiled JavaScript into a single file and fully optimize", APlusTask)
-
- val scalaJSStage = SettingKey[Stage]("scalaJSStage",
- "The optimization stage at which run and test are executed", APlusSetting)
-
- val packageScalaJSLauncher = TaskKey[Attributed[File]]("packageScalaJSLauncher",
- "Writes the persistent launcher file. Fails if the mainClass is ambigous", CTask)
-
- val packageJSDependencies = TaskKey[File]("packageJSDependencies",
- "Packages all dependencies of the preLink classpath in a single file. " +
- "Set skip in packageJSDependencies := false to run automatically", AMinusTask)
-
- val jsDependencyManifest = TaskKey[File]("jsDependencyManifest",
- "Writes the JS_DEPENDENCIES file.", DTask)
-
- val scalaJSPreLinkClasspath = TaskKey[IRClasspath]("scalaJSPreLinkClasspath",
- "Completely resolved classpath just after compilation", DTask)
-
- val scalaJSExecClasspath = TaskKey[CompleteClasspath]("scalaJSExecClasspath",
- "The classpath used for running and testing", DTask)
-
- val scalaJSLauncher = TaskKey[Attributed[VirtualJSFile]]("scalaJSLauncher",
- "Code used to run. (Attributed with used class name)", DTask)
-
- val scalaJSConsole = TaskKey[JSConsole]("scalaJSConsole",
- "The JS console used by the Scala.js runner/tester", DTask)
-
- val preLinkJSEnv = TaskKey[JSEnv]("preLinkJSEnv",
- "The jsEnv used to execute before linking (packaging / optimizing) Scala.js files", BSetting)
- val postLinkJSEnv = TaskKey[JSEnv]("postLinkJSEnv",
- "The jsEnv used to execute after linking (packaging / optimizing) Scala.js files", AMinusSetting)
-
- val jsEnv = TaskKey[JSEnv]("jsEnv",
- "A JVM-like environment where Scala.js files can be run and tested", DTask)
-
- val requiresDOM = SettingKey[Boolean]("requiresDOM",
- "Whether this projects needs the DOM. Overrides anything inherited through dependencies.", AMinusSetting)
-
- val scalaJSTestFramework = SettingKey[String]("scalaJSTestFramework",
- "The Scala.js class that is used as a test framework, for example a class that wraps Jasmine", ASetting)
-
- val relativeSourceMaps = SettingKey[Boolean]("relativeSourceMaps",
- "Make the referenced paths on source maps relative to target path", BPlusSetting)
-
- val emitSourceMaps = SettingKey[Boolean]("emitSourceMaps",
- "Whether package and optimize stages should emit source maps at all", BPlusSetting)
-
- val jsDependencies = SettingKey[Seq[AbstractJSDep]]("jsDependencies",
- "JavaScript libraries this project depends upon. Also used to depend on the DOM.", APlusSetting)
-
- val scalaJSSemantics = SettingKey[Semantics]("scalaJSSemantics",
- "Configurable semantics of Scala.js.", BPlusSetting)
-
- val jsDependencyFilter = SettingKey[PartialClasspath.DependencyFilter]("jsDependencyFilter",
- "The filter applied to the raw JavaScript dependencies before execution", CSetting)
-
- val checkScalaJSSemantics = SettingKey[Boolean]("checkScalaJSSemantics",
- "Whether to check that the current semantics meet compliance " +
- "requirements of dependencies.", CSetting)
-
- val persistLauncher = SettingKey[Boolean]("persistLauncher",
- "Tell optimize/package tasks to write the laucher file to disk. " +
- "If this is set, your project may only have a single mainClass or you must explicitly set it", AMinusSetting)
-
- val scalaJSOptimizerOptions = SettingKey[OptimizerOptions]("scalaJSOptimizerOptions",
- "All kinds of options for the Scala.js optimizer stages", DSetting)
-
- /** Class loader for PhantomJSEnv. Used to load jetty8. */
- val scalaJSPhantomJSClassLoader = TaskKey[ClassLoader]("scalaJSPhantomJSClassLoader",
- "Private class loader to load jetty8 without polluting classpath. Only use this " +
- "as the `jettyClassLoader` argument of the PhantomJSEnv",
- KeyRanks.Invisible)
- }
-
- import autoImport._
- import ScalaJSPluginInternal._
-
- override def globalSettings: Seq[Setting[_]] = {
- super.globalSettings ++ Seq(
- scalaJSStage := Stage.PreLink
- )
- }
-
- override def projectSettings: Seq[Setting[_]] = (
- scalaJSAbstractSettings ++
- scalaJSEcosystemSettings
- )
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/ScalaJSPluginInternal.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/ScalaJSPluginInternal.scala
deleted file mode 100644
index fe97f0b..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/ScalaJSPluginInternal.scala
+++ /dev/null
@@ -1,598 +0,0 @@
-package scala.scalajs.sbtplugin
-
-import sbt._
-import sbt.inc.{IncOptions, ClassfileManager}
-import Keys._
-
-import Implicits._
-import JSUtils._
-
-import scala.scalajs.tools.sem.Semantics
-import scala.scalajs.tools.io.{IO => toolsIO, _}
-import scala.scalajs.tools.classpath._
-import scala.scalajs.tools.classpath.builder._
-import scala.scalajs.tools.jsdep._
-import scala.scalajs.tools.optimizer.{
- ScalaJSOptimizer,
- ScalaJSClosureOptimizer,
- IncOptimizer,
- ParIncOptimizer
-}
-import scala.scalajs.tools.corelib.CoreJSLibs
-
-import scala.scalajs.tools.env._
-import scala.scalajs.sbtplugin.env.rhino.RhinoJSEnv
-import scala.scalajs.sbtplugin.env.nodejs.NodeJSEnv
-import scala.scalajs.sbtplugin.env.phantomjs.{PhantomJSEnv, PhantomJettyClassLoader}
-
-import scala.scalajs.ir.ScalaJSVersions
-
-import scala.scalajs.sbtplugin.testing.{TestFramework, JSClasspathLoader}
-
-import scala.util.Try
-
-import java.nio.charset.Charset
-import java.net.URLClassLoader
-
-/** Contains settings used by ScalaJSPlugin that should not be automatically
- * be in the *.sbt file's scope.
- */
-object ScalaJSPluginInternal {
-
- import ScalaJSPlugin.autoImport._
-
- /** Dummy setting to ensure we do not fork in Scala.js run & test. */
- val scalaJSEnsureUnforked = SettingKey[Boolean]("ensureUnforked",
- "Scala.js internal: Fails if fork is true.", KeyRanks.Invisible)
-
- /** Dummy setting to persist Scala.js optimizer */
- val scalaJSOptimizer = SettingKey[ScalaJSOptimizer]("scalaJSOptimizer",
- "Scala.js internal: Setting to persist the optimizer", KeyRanks.Invisible)
-
- /** Internal task to calculate whether a project requests the DOM
- * (through jsDependencies or requiresDOM) */
- val scalaJSRequestsDOM = TaskKey[Boolean]("scalaJSRequestsDOM",
- "Scala.js internal: Whether a project really wants the DOM. " +
- "Calculated using requiresDOM and jsDependencies", KeyRanks.Invisible)
-
- /** Default post link environment */
- val scalaJSDefaultPostLinkJSEnv = TaskKey[JSEnv]("scalaJSDefaultPostLinkJSEnv",
- "Scala.js internal: Default for postLinkJSEnv", KeyRanks.Invisible)
-
- /** Lookup key for CompleteClasspath in attribute maps */
- val scalaJSCompleteClasspath =
- AttributeKey[CompleteClasspath]("scalaJSCompleteClasspath")
-
- /** Patches the IncOptions so that .sjsir files are pruned as needed.
- *
- * This complicated logic patches the ClassfileManager factory of the given
- * IncOptions with one that is aware of .sjsir files emitted by the Scala.js
- * compiler. This makes sure that, when a .class file must be deleted, the
- * corresponding .sjsir file are also deleted.
- */
- def scalaJSPatchIncOptions(incOptions: IncOptions): IncOptions = {
- val inheritedNewClassfileManager = incOptions.newClassfileManager
- val newClassfileManager = () => new ClassfileManager {
- private[this] val inherited = inheritedNewClassfileManager()
-
- def delete(classes: Iterable[File]): Unit = {
- inherited.delete(classes flatMap { classFile =>
- val scalaJSFiles = if (classFile.getPath endsWith ".class") {
- val f = FileVirtualFile.withExtension(classFile, ".class", ".sjsir")
- if (f.exists) List(f)
- else Nil
- } else Nil
- classFile :: scalaJSFiles
- })
- }
-
- def generated(classes: Iterable[File]): Unit = inherited.generated(classes)
- def complete(success: Boolean): Unit = inherited.complete(success)
- }
- incOptions.copy(newClassfileManager = newClassfileManager)
- }
-
- private def scalaJSOptimizerSetting(key: TaskKey[_]): Setting[_] = (
- scalaJSOptimizer in key := {
- val semantics = (scalaJSSemantics in key).value
- if ((scalaJSOptimizerOptions in key).value.parallel)
- new ScalaJSOptimizer(semantics, new ParIncOptimizer(_))
- else
- new ScalaJSOptimizer(semantics, new IncOptimizer(_))
- }
- )
-
- val scalaJSConfigSettings: Seq[Setting[_]] = Seq(
- incOptions ~= scalaJSPatchIncOptions
- ) ++ Seq(
-
- scalaJSPreLinkClasspath := {
- val cp = fullClasspath.value
- val pcp = PartialClasspathBuilder.build(Attributed.data(cp).toList)
- val ccp = pcp.resolve(jsDependencyFilter.value)
-
- if (checkScalaJSSemantics.value)
- ccp.checkCompliance(scalaJSSemantics.value)
-
- ccp
- },
-
- artifactPath in fastOptJS :=
- ((crossTarget in fastOptJS).value /
- ((moduleName in fastOptJS).value + "-fastopt.js")),
-
- scalaJSOptimizerSetting(fastOptJS),
-
- fastOptJS := {
- val s = streams.value
- val output = (artifactPath in fastOptJS).value
- val taskCache =
- WritableFileVirtualTextFile(s.cacheDirectory / "fastopt-js")
-
- IO.createDirectory(output.getParentFile)
-
- val relSourceMapBase =
- if ((relativeSourceMaps in fastOptJS).value)
- Some(output.getParentFile.toURI())
- else None
-
- val opts = (scalaJSOptimizerOptions in fastOptJS).value
-
- import ScalaJSOptimizer._
- val outCP = (scalaJSOptimizer in fastOptJS).value.optimizeCP(
- Inputs(input = (scalaJSPreLinkClasspath in fastOptJS).value),
- OutputConfig(
- output = WritableFileVirtualJSFile(output),
- cache = Some(taskCache),
- wantSourceMap = (emitSourceMaps in fastOptJS).value,
- relativizeSourceMapBase = relSourceMapBase,
- checkIR = opts.checkScalaJSIR,
- disableOptimizer = opts.disableOptimizer,
- batchMode = opts.batchMode),
- s.log)
-
- Attributed.blank(output).put(scalaJSCompleteClasspath, outCP)
- },
- fastOptJS <<=
- fastOptJS.dependsOn(packageJSDependencies, packageScalaJSLauncher),
-
- artifactPath in fullOptJS :=
- ((crossTarget in fullOptJS).value /
- ((moduleName in fullOptJS).value + "-opt.js")),
-
- scalaJSSemantics in fullOptJS :=
- (scalaJSSemantics in fastOptJS).value.optimized,
-
- scalaJSOptimizerSetting(fullOptJS),
-
- fullOptJS := {
- val s = streams.value
- val output = (artifactPath in fullOptJS).value
- val taskCache =
- WritableFileVirtualTextFile(s.cacheDirectory / "fullopt-js")
-
- IO.createDirectory(output.getParentFile)
-
- val relSourceMapBase =
- if ((relativeSourceMaps in fullOptJS).value)
- Some(output.getParentFile.toURI())
- else None
-
- val opts = (scalaJSOptimizerOptions in fullOptJS).value
-
- val semantics = (scalaJSSemantics in fullOptJS).value
-
- import ScalaJSClosureOptimizer._
- val outCP = new ScalaJSClosureOptimizer(semantics).optimizeCP(
- (scalaJSOptimizer in fullOptJS).value,
- Inputs(ScalaJSOptimizer.Inputs(
- input = (scalaJSPreLinkClasspath in fullOptJS).value)),
- OutputConfig(
- output = WritableFileVirtualJSFile(output),
- cache = Some(taskCache),
- wantSourceMap = (emitSourceMaps in fullOptJS).value,
- relativizeSourceMapBase = relSourceMapBase,
- checkIR = opts.checkScalaJSIR,
- disableOptimizer = opts.disableOptimizer,
- batchMode = opts.batchMode,
- prettyPrint = opts.prettyPrintFullOptJS),
- s.log)
-
- Attributed.blank(output).put(scalaJSCompleteClasspath, outCP)
- },
-
- artifactPath in packageScalaJSLauncher :=
- ((crossTarget in packageScalaJSLauncher).value /
- ((moduleName in packageScalaJSLauncher).value + "-launcher.js")),
-
- skip in packageScalaJSLauncher := !persistLauncher.value,
-
- packageScalaJSLauncher <<= Def.taskDyn {
- if ((skip in packageScalaJSLauncher).value)
- Def.task(Attributed.blank((artifactPath in packageScalaJSLauncher).value))
- else Def.task {
- mainClass.value map { mainCl =>
- val file = (artifactPath in packageScalaJSLauncher).value
- IO.write(file, launcherContent(mainCl), Charset.forName("UTF-8"))
-
- // Attach the name of the main class used, (ab?)using the name key
- Attributed(file)(AttributeMap.empty.put(name.key, mainCl))
- } getOrElse {
- sys.error("Cannot write launcher file, since there is no or multiple mainClasses")
- }
- }
- },
-
- artifactPath in packageJSDependencies :=
- ((crossTarget in packageJSDependencies).value /
- ((moduleName in packageJSDependencies).value + "-jsdeps.js")),
-
- packageJSDependencies <<= Def.taskDyn {
- if ((skip in packageJSDependencies).value)
- Def.task((artifactPath in packageJSDependencies).value)
- else Def.task {
- val cp = scalaJSPreLinkClasspath.value
- val output = (artifactPath in packageJSDependencies).value
- val taskCache = WritableFileVirtualJSFile(
- streams.value.cacheDirectory / "package-js-deps")
-
- IO.createDirectory(output.getParentFile)
-
- val outFile = WritableFileVirtualTextFile(output)
- CacheUtils.cached(cp.version, outFile, Some(taskCache)) {
- toolsIO.concatFiles(outFile, cp.jsLibs.map(_.lib))
- }
-
- output
- }
- },
-
- jsDependencyManifest := {
- val myModule = thisProject.value.id
- val config = configuration.value.name
-
- // Collect all libraries
- val jsDeps = jsDependencies.value.collect {
- case dep: JSModuleID if dep.configurations.forall(_ == config) =>
- dep.jsDep
- }
-
- val requiresDOM = jsDependencies.value.exists {
- case RuntimeDOM(configurations) =>
- configurations.forall(_ == config)
- case _ => false
- }
-
- val compliantSemantics = scalaJSSemantics.value.compliants
-
- val manifest = new JSDependencyManifest(new Origin(myModule, config),
- jsDeps.toList, requiresDOM, compliantSemantics)
-
- // Write dependency file to class directory
- val targetDir = classDirectory.value
- IO.createDirectory(targetDir)
-
- val file = targetDir / JSDependencyManifest.ManifestFileName
- val vfile = WritableFileVirtualTextFile(file)
-
- // Prevent writing if unnecessary to not invalidate dependencies
- val needWrite = !vfile.exists || {
- Try {
- val readManifest = JSDependencyManifest.read(vfile)
- readManifest != manifest
- } getOrElse true
- }
-
- if (needWrite)
- JSDependencyManifest.write(manifest, vfile)
-
- file
- },
-
- products <<= products.dependsOn(jsDependencyManifest),
-
- console <<= console.dependsOn(Def.task(
- streams.value.log.warn("Scala REPL doesn't work with Scala.js. You " +
- "are running a JVM REPL. JavaScript things won't work.")
- )),
-
- // Give tasks ability to check we are not forking at build reading time
- scalaJSEnsureUnforked := {
- if (fork.value)
- sys.error("Scala.js cannot be run in a forked JVM")
- else
- true
- },
-
- scalaJSRequestsDOM :=
- requiresDOM.?.value.getOrElse(scalaJSExecClasspath.value.requiresDOM),
-
- // Default jsEnv
- jsEnv <<= Def.taskDyn {
- scalaJSStage.value match {
- case Stage.PreLink =>
- Def.task {
- preLinkJSEnv.?.value.getOrElse {
- new RhinoJSEnv(scalaJSSemantics.value,
- withDOM = scalaJSRequestsDOM.value)
- }
- }
- case Stage.FastOpt | Stage.FullOpt =>
- Def.task(scalaJSDefaultPostLinkJSEnv.value)
- }
- },
-
- // Wire jsEnv and sources for other stages
- scalaJSDefaultPostLinkJSEnv := postLinkJSEnv.?.value.getOrElse {
- if (scalaJSRequestsDOM.value)
- new PhantomJSEnv(jettyClassLoader = scalaJSPhantomJSClassLoader.value)
- else
- new NodeJSEnv
- },
-
- scalaJSExecClasspath <<= Def.taskDyn {
- scalaJSStage.value match {
- case Stage.PreLink =>
- Def.task { scalaJSPreLinkClasspath.value }
- case Stage.FastOpt =>
- Def.task { fastOptJS.value.get(scalaJSCompleteClasspath).get }
- case Stage.FullOpt =>
- Def.task { fullOptJS.value.get(scalaJSCompleteClasspath).get }
- }
- }
- )
-
- /** Run a class in a given environment using a given launcher */
- private def jsRun(env: JSEnv, cp: CompleteClasspath, mainCl: String,
- launcher: VirtualJSFile, jsConsole: JSConsole, log: Logger) = {
-
- log.info("Running " + mainCl)
- log.debug(s"with JSEnv of type ${env.getClass()}")
- log.debug(s"with classpath of type ${cp.getClass}")
-
- // Actually run code
- env.jsRunner(cp, launcher, log, jsConsole).run()
- }
-
- private def launcherContent(mainCl: String) = {
- // If we are running in Node.js, we need to bracket select on
- // global rather than this
- """((typeof global === "object" && global &&
- global["Object"] === Object) ? global : this)""" +
- s"${dot2bracket(mainCl)}().main();\n"
- }
-
- private def memLauncher(mainCl: String) = {
- new MemVirtualJSFile("Generated launcher file")
- .withContent(launcherContent(mainCl))
- }
-
- // These settings will be filtered by the stage dummy tasks
- val scalaJSRunSettings = Seq(
- mainClass in scalaJSLauncher := (mainClass in run).value,
- scalaJSLauncher <<= Def.taskDyn {
- if (persistLauncher.value)
- Def.task(packageScalaJSLauncher.value.map(FileVirtualJSFile))
- else Def.task {
- (mainClass in scalaJSLauncher).value map { mainClass =>
- val memLaunch = memLauncher(mainClass)
- Attributed[VirtualJSFile](memLaunch)(
- AttributeMap.empty.put(name.key, mainClass))
- } getOrElse {
- sys.error("No main class detected.")
- }
- }
- },
-
- /* We do currently not discover objects containing a
- *
- * def main(args: Array[String]): Unit
- *
- * Support will be added again, as soon as we can run them
- * reliably (e.g. without implicitly requiring that an exported
- *
- * def main(): Unit
- *
- * exists alongside.
- */
- discoveredMainClasses := {
- import xsbt.api.{Discovered, Discovery}
-
- val jsApp = "scala.scalajs.js.JSApp"
-
- def isJSApp(discovered: Discovered) =
- discovered.isModule && discovered.baseClasses.contains(jsApp)
-
- Discovery(Set(jsApp), Set.empty)(Tests.allDefs(compile.value)) collect {
- case (definition, discovered) if isJSApp(discovered) =>
- definition.name
- }
- },
-
- run <<= Def.inputTask {
- // use assert to prevent warning about pure expr in stat pos
- assert(scalaJSEnsureUnforked.value)
-
- val launch = scalaJSLauncher.value
- val className = launch.get(name.key).getOrElse("<unknown class>")
- jsRun(jsEnv.value, scalaJSExecClasspath.value, className,
- launch.data, scalaJSConsole.value, streams.value.log)
- },
-
- runMain <<= {
- // Implicits for parsing
- import sbinary.DefaultProtocol.StringFormat
- import Cache.seqFormat
-
- val parser = Defaults.loadForParser(discoveredMainClasses)((s, names) =>
- Defaults.runMainParser(s, names getOrElse Nil))
-
- Def.inputTask {
- // use assert to prevent warning about pure expr in stat pos
- assert(scalaJSEnsureUnforked.value)
-
- val mainCl = parser.parsed._1
- jsRun(jsEnv.value, scalaJSExecClasspath.value, mainCl,
- memLauncher(mainCl), scalaJSConsole.value, streams.value.log)
- }
- }
- )
-
- val scalaJSCompileSettings = (
- scalaJSConfigSettings ++
- scalaJSRunSettings
- )
-
- val scalaJSTestFrameworkSettings = Seq(
- // Copied from Defaults, but scoped. We need a JVM loader in
- // loadedTestFrameworks to find out whether the framework exists.
- testLoader in loadedTestFrameworks := {
- TestFramework.createTestLoader(
- Attributed.data(fullClasspath.value),
- scalaInstance.value,
- IO.createUniqueDirectory(taskTemporaryDirectory.value))
- },
-
- loadedTestFrameworks := {
- // use assert to prevent warning about pure expr in stat pos
- assert(scalaJSEnsureUnforked.value)
-
- val loader = (testLoader in loadedTestFrameworks).value
- val isTestFrameworkDefined = try {
- Class.forName(scalaJSTestFramework.value, false, loader)
- true
- } catch {
- case _: ClassNotFoundException => false
- }
- if (isTestFrameworkDefined) {
- loadedTestFrameworks.value.updated(
- sbt.TestFramework(classOf[TestFramework].getName),
- new TestFramework(
- environment = jsEnv.value,
- jsConsole = scalaJSConsole.value,
- testFramework = scalaJSTestFramework.value)
- )
- } else {
- loadedTestFrameworks.value
- }
- },
-
- // Pseudo loader to pass classpath to test framework
- testLoader := JSClasspathLoader(scalaJSExecClasspath.value)
- )
-
- val scalaJSTestBuildSettings = (
- scalaJSConfigSettings
- ) ++ (
- Seq(fastOptJS, fullOptJS, packageScalaJSLauncher,
- packageJSDependencies) map { packageJSTask =>
- moduleName in packageJSTask := moduleName.value + "-test"
- }
- )
-
- val scalaJSTestSettings = (
- scalaJSTestBuildSettings ++
- scalaJSTestFrameworkSettings
- )
-
- val scalaJSDependenciesSettings = Seq(
- // add all the webjars your jsDependencies depend upon
- libraryDependencies ++= jsDependencies.value.collect {
- case JarJSModuleID(module, _) => module
- }
- )
-
- val scalaJSDefaultBuildConfigs = (
- inConfig(Compile)(scalaJSConfigSettings) ++ // build settings for Compile
- inConfig(Test)(scalaJSTestBuildSettings) ++
- scalaJSDependenciesSettings
- )
-
- val scalaJSDefaultConfigs = (
- inConfig(Compile)(scalaJSCompileSettings) ++
- inConfig(Test)(scalaJSTestSettings) ++
- scalaJSDependenciesSettings
- )
-
- val phantomJSJettyModules = Seq(
- "org.eclipse.jetty" % "jetty-websocket" % "8.1.16.v20140903",
- "org.eclipse.jetty" % "jetty-server" % "8.1.16.v20140903"
- )
-
- val scalaJSProjectBaseSettings = Seq(
- relativeSourceMaps := false,
- persistLauncher := false,
-
- skip in packageJSDependencies := true,
-
- scalaJSTestFramework := "org.scalajs.jasminetest.JasmineTestFramework",
-
- emitSourceMaps := true,
-
- scalaJSOptimizerOptions := OptimizerOptions(),
-
- jsDependencies := Seq(),
- jsDependencyFilter := identity,
-
- scalaJSSemantics := Semantics.Defaults,
- checkScalaJSSemantics := true,
-
- scalaJSConsole := ConsoleJSConsole,
-
- clean <<= clean.dependsOn(Def.task {
- // have clean reset incremental optimizer state
- (scalaJSOptimizer in (Compile, fastOptJS)).value.clean()
- (scalaJSOptimizer in (Test, fastOptJS)).value.clean()
- }),
-
- /* Depend on jetty artifacts in dummy configuration to be able to inject
- * them into the PhantomJS runner if necessary.
- * See scalaJSPhantomJSClassLoader
- */
- ivyConfigurations += config("phantom-js-jetty").hide,
- libraryDependencies ++= phantomJSJettyModules.map(_ % "phantom-js-jetty"),
- scalaJSPhantomJSClassLoader := {
- val report = update.value
- val jars = report.select(configurationFilter("phantom-js-jetty"))
-
- val jettyLoader =
- new URLClassLoader(jars.map(_.toURI.toURL).toArray, null)
-
- new PhantomJettyClassLoader(jettyLoader, getClass.getClassLoader)
- }
- )
-
- val scalaJSAbstractSettings: Seq[Setting[_]] = (
- scalaJSProjectBaseSettings ++
- scalaJSDefaultConfigs
- )
-
- val scalaJSAbstractBuildSettings: Seq[Setting[_]] = (
- scalaJSProjectBaseSettings ++
- scalaJSDefaultBuildConfigs
- )
-
- val scalaJSReleasesResolver = Resolver.url("scala-js-releases",
- url("http://dl.bintray.com/content/scala-js/scala-js-releases"))(
- Resolver.ivyStylePatterns)
- val scalaJSSnapshotsResolver = Resolver.url("scala-js-snapshots",
- url("http://repo.scala-js.org/repo/snapshots/"))(
- Resolver.ivyStylePatterns)
-
- val scalaJSEcosystemSettings = Seq(
- // the resolver to find the compiler and library (and others)
- resolvers ++= Seq(scalaJSReleasesResolver, scalaJSSnapshotsResolver),
-
- // you will need the Scala.js compiler plugin
- autoCompilerPlugins := true,
- addCompilerPlugin(
- "org.scala-lang.modules.scalajs" % "scalajs-compiler" % scalaJSVersion cross CrossVersion.full),
-
- // and of course the Scala.js library
- libraryDependencies += "org.scala-lang.modules.scalajs" %% "scalajs-library" % scalaJSVersion,
-
- // and you will want to be cross-compiled on the Scala.js binary version
- crossVersion := ScalaJSCrossVersion.binary
- )
-
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/Stage.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/Stage.scala
deleted file mode 100644
index 7f7b916..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/Stage.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin
-
-sealed trait Stage
-
-object Stage {
- case object PreLink extends Stage
- case object FullOpt extends Stage
- case object FastOpt extends Stage
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/ExternalJSEnv.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/ExternalJSEnv.scala
deleted file mode 100644
index e0aa557..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/ExternalJSEnv.scala
+++ /dev/null
@@ -1,200 +0,0 @@
-package scala.scalajs.sbtplugin.env
-
-import scala.scalajs.tools.io._
-import scala.scalajs.tools.classpath._
-import scala.scalajs.tools.env._
-import scala.scalajs.tools.logging._
-
-import scala.scalajs.sbtplugin.JSUtils._
-
-import java.io.{ Console => _, _ }
-import scala.io.Source
-
-import scala.concurrent.{Future, Promise}
-import scala.util.Try
-
-abstract class ExternalJSEnv(
- final protected val additionalArgs: Seq[String],
- final protected val additionalEnv: Map[String, String]) extends AsyncJSEnv {
-
- /** Printable name of this VM */
- protected def vmName: String
-
- /** Command to execute (on shell) for this VM */
- protected def executable: String
-
- protected class AbstractExtRunner(protected val classpath: CompleteClasspath,
- protected val code: VirtualJSFile, protected val logger: Logger,
- protected val console: JSConsole) {
-
- /** JS files used to setup VM */
- protected def initFiles(): Seq[VirtualJSFile] = Nil
-
- /** Sends required data to VM Stdin (can throw) */
- protected def sendVMStdin(out: OutputStream): Unit = {}
-
- /** VM arguments excluding executable. Override to adapt.
- * Overrider is responsible to add additionalArgs.
- */
- protected def getVMArgs(): Seq[String] = additionalArgs
-
- /** VM environment. Override to adapt.
- *
- * Default is `sys.env` and [[additionalEnv]]
- */
- protected def getVMEnv(): Map[String, String] =
- sys.env ++ additionalEnv
-
- /** Get files that are a library (i.e. that do not run anything) */
- protected def getLibJSFiles(): Seq[VirtualJSFile] =
- initFiles() ++ classpath.allCode
-
- /** Get all files that are passed to VM (libraries and code) */
- protected def getJSFiles(): Seq[VirtualJSFile] =
- getLibJSFiles() :+ code
-
- /** write a single JS file to a writer using an include fct if appropriate */
- protected def writeJSFile(file: VirtualJSFile, writer: Writer): Unit = {
- // The only platform-independent way to do this in JS is to dump the file.
- writer.write(file.content)
- writer.write('\n')
- }
-
- /** Pipe stdin and stdout from/to VM */
- final protected def pipeVMData(vmInst: Process): Unit = {
- // Send stdin to VM.
- val out = vmInst.getOutputStream()
- try { sendVMStdin(out) }
- finally { out.close() }
-
- // Pipe stdout to console
- pipeToConsole(vmInst.getInputStream(), console)
-
- // We are probably done (stdin is closed). Report any errors
- val errSrc = Source.fromInputStream(vmInst.getErrorStream(), "UTF-8")
- try { errSrc.getLines.foreach(err => logger.error(err)) }
- finally { errSrc.close }
- }
-
- /** Wait for the VM to terminate, verify exit code */
- final protected def waitForVM(vmInst: Process): Unit = {
- // Make sure we are done.
- vmInst.waitFor()
-
- // Get return value and return
- val retVal = vmInst.exitValue
- if (retVal != 0)
- sys.error(s"$vmName exited with code $retVal")
- }
-
- protected def startVM(): Process = {
- val vmArgs = getVMArgs()
- val vmEnv = getVMEnv()
-
- val allArgs = executable +: vmArgs
- val pBuilder = new ProcessBuilder(allArgs: _*)
-
- pBuilder.environment().clear()
- for ((name, value) <- vmEnv)
- pBuilder.environment().put(name, value)
-
- pBuilder.start()
- }
-
- /** send a bunch of JS files to an output stream */
- final protected def sendJS(files: Seq[VirtualJSFile],
- out: OutputStream): Unit = {
- val writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"))
- try sendJS(files, writer)
- finally writer.close()
- }
-
- /** send a bunch of JS files to a writer */
- final protected def sendJS(files: Seq[VirtualJSFile], out: Writer): Unit =
- files.foreach { writeJSFile(_, out) }
-
- /** pipe lines from input stream to JSConsole */
- final protected def pipeToConsole(in: InputStream, console: JSConsole) = {
- val source = Source.fromInputStream(in, "UTF-8")
- try { source.getLines.foreach(console.log _) }
- finally { source.close() }
- }
-
- }
-
- protected class ExtRunner(classpath: CompleteClasspath, code: VirtualJSFile,
- logger: Logger, console: JSConsole
- ) extends AbstractExtRunner(classpath, code, logger, console)
- with JSRunner {
-
- def run(): Unit = {
- val vmInst = startVM()
-
- pipeVMData(vmInst)
- waitForVM(vmInst)
- }
- }
-
- protected class AsyncExtRunner(classpath: CompleteClasspath,
- code: VirtualJSFile, logger: Logger, console: JSConsole
- ) extends AbstractExtRunner(classpath, code, logger, console)
- with AsyncJSRunner {
-
- private[this] var vmInst: Process = null
- private[this] var ioThreadEx: Throwable = null
- private[this] val promise = Promise[Unit]
-
- private[this] val thread = new Thread {
- override def run(): Unit = {
- // This thread should not be interrupted, so it is safe to use Trys
- val pipeResult = Try(pipeVMData(vmInst))
- val vmComplete = Try(waitForVM(vmInst))
-
- // Store IO exception
- pipeResult recover {
- case e => ioThreadEx = e
- }
-
- // Chain Try's the other way: We want VM failure first, then IO failure
- promise.complete(pipeResult orElse vmComplete)
- }
- }
-
- def start(): Future[Unit] = {
- require(vmInst == null, "start() may only be called once")
- vmInst = startVM()
- thread.start()
- promise.future
- }
-
- def stop(): Unit = {
- require(vmInst != null, "start() must have been called")
- vmInst.destroy()
- }
-
- def isRunning(): Boolean = {
- require(vmInst != null, "start() must have been called")
- // Emulate JDK 8 Process.isAlive
- try {
- vmInst.exitValue()
- false
- } catch {
- case e: IllegalThreadStateException =>
- true
- }
- }
-
- def await(): Unit = {
- require(vmInst != null, "start() must have been called")
- thread.join()
- waitForVM(vmInst)
-
- // At this point, the VM itself didn't fail. We need to check if
- // anything bad happened while piping the data from the VM
-
- if (ioThreadEx != null)
- throw ioThreadEx
- }
- }
-
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/VirtualFileMaterializer.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/VirtualFileMaterializer.scala
deleted file mode 100644
index fca1c47..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/VirtualFileMaterializer.scala
+++ /dev/null
@@ -1,67 +0,0 @@
-package scala.scalajs.sbtplugin.env
-
-import scala.scalajs.tools.io.{IO => _, _}
-
-import sbt.IO
-
-import java.io.File
-
-/** A helper class to temporarily store virtual files to the filesystem.
- *
- * Can be used with tools that require real files.
- * @param singleDir if true, forces files to be copied into
- * [[cacheDir]]. Useful to setup include directories for
- * example.
- */
-final class VirtualFileMaterializer(singleDir: Boolean = false) {
-
- val cacheDir = {
- val dir = IO.createTemporaryDirectory
- dir.deleteOnExit()
- dir
- }
-
- /** Create a target file to write/copy to. Will also call
- * deleteOnExit on the file.
- */
- private def trgFile(name: String): File = {
- val f = new File(cacheDir, name)
- f.deleteOnExit()
- f
- }
-
- private def materializeFileVF(vf: FileVirtualFile): File = {
- if (!singleDir) vf.file
- else {
- val trg = trgFile(vf.name)
- IO.copyFile(vf.file, trg)
- trg
- }
- }
-
- def materialize(vf: VirtualTextFile): File = vf match {
- case vf: FileVirtualFile => materializeFileVF(vf)
- case _ =>
- val trg = trgFile(vf.name)
- IO.write(trg, vf.content)
- trg
- }
-
- def materialize(vf: VirtualBinaryFile): File = vf match {
- case vf: FileVirtualFile => materializeFileVF(vf)
- case _ =>
- val trg = trgFile(vf.name)
- IO.write(trg, vf.content)
- trg
- }
-
- /** Removes the cache directory. Any operation on this
- * VirtualFileMaterializer is invalid after [[close]] has been
- * called.
- */
- def close(): Unit = {
- cacheDir.listFiles().foreach(_.delete)
- cacheDir.delete()
- }
-
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/nodejs/NodeJSEnv.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/nodejs/NodeJSEnv.scala
deleted file mode 100644
index dfabe23..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/nodejs/NodeJSEnv.scala
+++ /dev/null
@@ -1,306 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin.env.nodejs
-
-import scala.scalajs.sbtplugin.env._
-import scala.scalajs.sbtplugin.JSUtils.toJSstr
-
-import scala.scalajs.tools.io._
-import scala.scalajs.tools.classpath._
-import scala.scalajs.tools.env._
-import scala.scalajs.tools.jsdep._
-import scala.scalajs.tools.logging._
-
-import scala.scalajs.sbtplugin.JSUtils._
-
-import java.io.{ Console => _, _ }
-import java.net._
-
-import scala.io.Source
-
-class NodeJSEnv(
- nodejsPath: String = "node",
- addArgs: Seq[String] = Seq.empty,
- addEnv: Map[String, String] = Map.empty
-) extends ExternalJSEnv(addArgs, addEnv) with ComJSEnv {
-
- protected def vmName: String = "node.js"
- protected def executable: String = nodejsPath
-
- override def jsRunner(classpath: CompleteClasspath, code: VirtualJSFile,
- logger: Logger, console: JSConsole): JSRunner = {
- new NodeRunner(classpath, code, logger, console)
- }
-
- override def asyncRunner(classpath: CompleteClasspath, code: VirtualJSFile,
- logger: Logger, console: JSConsole): AsyncJSRunner = {
- new AsyncNodeRunner(classpath, code, logger, console)
- }
-
- override def comRunner(classpath: CompleteClasspath, code: VirtualJSFile,
- logger: Logger, console: JSConsole): ComJSRunner = {
- new ComNodeRunner(classpath, code, logger, console)
- }
-
- protected class NodeRunner(classpath: CompleteClasspath,
- code: VirtualJSFile, logger: Logger, console: JSConsole
- ) extends ExtRunner(classpath, code, logger, console)
- with AbstractNodeRunner
-
- protected class AsyncNodeRunner(classpath: CompleteClasspath,
- code: VirtualJSFile, logger: Logger, console: JSConsole
- ) extends AsyncExtRunner(classpath, code, logger, console)
- with AbstractNodeRunner
-
- protected class ComNodeRunner(classpath: CompleteClasspath,
- code: VirtualJSFile, logger: Logger, console: JSConsole
- ) extends AsyncNodeRunner(classpath, code, logger, console)
- with ComJSRunner {
-
- /** Retry-timeout to wait for the JS VM to connect */
- private final val acceptTimeout = 1000
-
- private[this] val serverSocket =
- new ServerSocket(0, 0, InetAddress.getByName(null)) // Loopback address
- private[this] var comSocket: Socket = _
- private[this] var jvm2js: DataOutputStream = _
- private[this] var js2jvm: DataInputStream = _
-
- private def comSetup = new MemVirtualJSFile("comSetup.js").withContent(
- s"""
- (function() {
- // The socket for communication
- var socket = null;
- // The callback where received messages go
- var recvCallback = null;
-
- // Buffers received data
- var inBuffer = new Buffer(0);
-
- function onData(data) {
- inBuffer = Buffer.concat([inBuffer, data]);
- tryReadMsg();
- }
-
- function tryReadMsg() {
- if (inBuffer.length < 4) return;
- var msgLen = inBuffer.readInt32BE(0);
- var byteLen = 4 + msgLen * 2;
-
- if (inBuffer.length < byteLen) return;
- var res = "";
-
- for (var i = 0; i < msgLen; ++i)
- res += String.fromCharCode(inBuffer.readInt16BE(4 + i * 2));
-
- inBuffer = inBuffer.slice(byteLen);
-
- recvCallback(res);
- }
-
- global.scalajsCom = {
- init: function(recvCB) {
- if (socket !== null) throw new Error("Com already open");
-
- var net = require('net');
- recvCallback = recvCB;
- socket = net.connect(${serverSocket.getLocalPort});
- socket.on('data', onData);
- },
- send: function(msg) {
- if (socket === null) throw new Error("Com not open");
-
- var len = msg.length;
- var buf = new Buffer(4 + len * 2);
- buf.writeInt32BE(len, 0);
- for (var i = 0; i < len; ++i)
- buf.writeInt16BE(msg.charCodeAt(i), 4 + i * 2);
- socket.write(buf);
- },
- close: function() {
- if (socket === null) throw new Error("Com not open");
- socket.end();
- }
- }
- }).call(this);
- """
- )
-
- def send(msg: String): Unit = {
- if (awaitConnection()) {
- jvm2js.writeInt(msg.length)
- jvm2js.writeChars(msg)
- jvm2js.flush()
- }
- }
-
- def receive(): String = {
- if (!awaitConnection())
- throw new ComJSEnv.ComClosedException
- try {
- val len = js2jvm.readInt()
- val carr = Array.fill(len)(js2jvm.readChar())
- String.valueOf(carr)
- } catch {
- case e: EOFException =>
- throw new ComJSEnv.ComClosedException
- }
- }
-
- def close(): Unit = {
- serverSocket.close()
- if (jvm2js != null)
- jvm2js.close()
- if (js2jvm != null)
- js2jvm.close()
- if (comSocket != null)
- comSocket.close()
- }
-
- override def stop(): Unit = {
- close()
- super.stop()
- }
-
- /** Waits until the JS VM has established a connection or terminates
- * @return true if the connection was established
- */
- private def awaitConnection(): Boolean = {
- serverSocket.setSoTimeout(acceptTimeout)
- while (comSocket == null && isRunning) {
- try {
- comSocket = serverSocket.accept()
- jvm2js = new DataOutputStream(
- new BufferedOutputStream(comSocket.getOutputStream()))
- js2jvm = new DataInputStream(
- new BufferedInputStream(comSocket.getInputStream()))
- } catch {
- case to: SocketTimeoutException =>
- }
- }
-
- comSocket != null
- }
-
- override protected def initFiles(): Seq[VirtualJSFile] =
- super.initFiles :+ comSetup
-
- override protected def finalize(): Unit = close()
- }
-
- protected trait AbstractNodeRunner extends AbstractExtRunner {
-
- protected[this] val libCache = new VirtualFileMaterializer(true)
-
- /** File(s) to automatically install source-map-support.
- * Is used by [[initFiles]], override to change/disable.
- */
- protected def installSourceMap(): Seq[VirtualJSFile] = Seq(
- new MemVirtualJSFile("sourceMapSupport.js").withContent(
- """
- try {
- require('source-map-support').install();
- } catch (e) {}
- """
- )
- )
-
- /** File(s) to hack console.log to prevent if from changing `%%` to `%`.
- * Is used by [[initFiles]], override to change/disable.
- */
- protected def fixPercentConsole(): Seq[VirtualJSFile] = Seq(
- new MemVirtualJSFile("nodeConsoleHack.js").withContent(
- """
- // Hack console log to duplicate double % signs
- (function() {
- var oldLog = console.log;
- var newLog = function() {
- var args = arguments;
- if (args.length >= 1 && args[0] !== void 0 && args[0] !== null) {
- args[0] = args[0].toString().replace(/%/g, "%%");
- }
- oldLog.apply(console, args);
- };
- console.log = newLog;
- })();
- """
- )
- )
-
- /** File(s) to define `__ScalaJSEnv`. Defines `exitFunction`.
- * Is used by [[initFiles]], override to change/disable.
- */
- protected def runtimeEnv(): Seq[VirtualJSFile] = Seq(
- new MemVirtualJSFile("scalaJSEnvInfo.js").withContent(
- """
- __ScalaJSEnv = {
- exitFunction: function(status) { process.exit(status); }
- };
- """
- )
- )
-
- /** Concatenates results from [[installSourceMap]], [[fixPercentConsole]] and
- * [[runtimeEnv]] (in this order).
- */
- override protected def initFiles(): Seq[VirtualJSFile] =
- installSourceMap() ++ fixPercentConsole() ++ runtimeEnv()
-
- /** Libraries are loaded via require in Node.js */
- override protected def getLibJSFiles(): Seq[VirtualJSFile] = {
- initFiles() ++
- classpath.jsLibs.map(requireLibrary) :+
- classpath.scalaJSCode
- }
-
- /** Rewrites a library virtual file to a require statement if possible */
- protected def requireLibrary(dep: ResolvedJSDependency): VirtualJSFile = {
- dep.info.commonJSName.fold(dep.lib) { varname =>
- val fname = dep.lib.name
- libCache.materialize(dep.lib)
- new MemVirtualJSFile(s"require-$fname").withContent(
- s"""$varname = require(${toJSstr(fname)});"""
- )
- }
- }
-
- // Send code to Stdin
- override protected def sendVMStdin(out: OutputStream): Unit = {
- sendJS(getJSFiles(), out)
- }
-
- /** write a single JS file to a writer using an include fct if appropriate
- * uses `require` if the file exists on the filesystem
- */
- override protected def writeJSFile(file: VirtualJSFile,
- writer: Writer): Unit = {
- file match {
- case file: FileVirtualJSFile =>
- val fname = toJSstr(file.file.getAbsolutePath)
- writer.write(s"require($fname);\n")
- case _ =>
- super.writeJSFile(file, writer)
- }
- }
-
- // Node.js specific (system) environment
- override protected def getVMEnv(): Map[String, String] = {
- val baseNodePath = sys.env.get("NODE_PATH").filter(_.nonEmpty)
- val nodePath = libCache.cacheDir.getAbsolutePath +
- baseNodePath.fold("")(p => File.pathSeparator + p)
-
- sys.env ++ Seq(
- "NODE_MODULE_CONTEXTS" -> "0",
- "NODE_PATH" -> nodePath
- ) ++ additionalEnv
- }
- }
-
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/JettyWebsocketManager.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/JettyWebsocketManager.scala
deleted file mode 100644
index 3dec79c..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/JettyWebsocketManager.scala
+++ /dev/null
@@ -1,126 +0,0 @@
-package scala.scalajs.sbtplugin.env.phantomjs
-
-import javax.servlet.http.HttpServletRequest
-
-import org.eclipse.jetty.server.Server
-import org.eclipse.jetty.server.nio.SelectChannelConnector
-import org.eclipse.jetty.websocket.{WebSocket, WebSocketHandler}
-import org.eclipse.jetty.util.component.{LifeCycle, AbstractLifeCycle}
-import org.eclipse.jetty.util.log
-
-private[phantomjs] final class JettyWebsocketManager(
- wsListener: WebsocketListener) extends WebsocketManager { thisMgr =>
-
- private[this] var webSocketConn: WebSocket.Connection = null
- private[this] var closed = false
-
- // We can just set the logger here, since we are supposed to be protected by
- // the private ClassLoader that loads us reflectively.
- log.Log.setLog(new WSLogger("root"))
-
- private[this] val connector = new SelectChannelConnector
-
- connector.setHost("localhost")
- connector.setPort(0)
-
- private[this] val server = new Server()
-
- server.addConnector(connector)
- server.setHandler(new WebSocketHandler {
- // Support Hixie 76 for Phantom.js
- getWebSocketFactory().setMinVersion(-1)
-
- override def doWebSocketConnect(
- request: HttpServletRequest, protocol: String): WebSocket =
- new ComWebSocketListener
- })
-
- server.addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener {
- override def lifeCycleStarted(event: LifeCycle): Unit = {
- if (event.isRunning())
- wsListener.onRunning()
- }
- })
-
- private class ComWebSocketListener extends WebSocket.OnTextMessage {
- override def onOpen(connection: WebSocket.Connection): Unit = {
- thisMgr.synchronized {
- if (isConnected)
- throw new IllegalStateException("Client connected twice")
- webSocketConn = connection
- }
- wsListener.onOpen()
- }
-
- override def onClose(statusCode: Int, reason: String): Unit = {
- thisMgr.synchronized {
- webSocketConn = null
- closed = true
- }
- wsListener.onClose()
- server.stop()
-
- if (statusCode != 1000) {
- throw new Exception("Abnormal closing of connection. " +
- s"Code: $statusCode, Reason: $reason")
- }
- }
-
- override def onMessage(message: String): Unit =
- wsListener.onMessage(message)
- }
-
- private class WSLogger(fullName: String) extends log.AbstractLogger {
- private[this] var debugEnabled = false
-
- def debug(msg: String, args: Object*): Unit =
- if (debugEnabled) log("DEBUG", msg, args)
-
- def debug(msg: String, thrown: Throwable): Unit =
- if (debugEnabled) log("DEBUG", msg, thrown)
-
- def debug(thrown: Throwable): Unit =
- if (debugEnabled) log("DEBUG", thrown)
-
- def getName(): String = fullName
-
- def ignore(ignored: Throwable): Unit = ()
-
- def info(msg: String, args: Object*): Unit = log("INFO", msg, args)
- def info(msg: String, thrown: Throwable): Unit = log("INFO", msg, thrown)
- def info(thrown: Throwable): Unit = log("INFO", thrown)
-
- def warn(msg: String, args: Object*): Unit = log("WARN", msg, args)
- def warn(msg: String, thrown: Throwable): Unit = log("WARN", msg, thrown)
- def warn(thrown: Throwable): Unit = log("WARN", thrown)
-
- def isDebugEnabled(): Boolean = debugEnabled
- def setDebugEnabled(enabled: Boolean): Unit = debugEnabled = enabled
-
- private def log(lvl: String, msg: String, args: Object*): Unit =
- wsListener.log(s"$lvl: $msg " + args.mkString(", "))
-
- private def log(lvl: String, msg: String, thrown: Throwable): Unit =
- wsListener.log(s"$lvl: $msg $thrown\n{$thrown.getStackStrace}")
-
- private def log(lvl: String, thrown: Throwable): Unit =
- wsListener.log(s"$lvl: $thrown\n{$thrown.getStackStrace}")
-
- protected def newLogger(fullName: String) = new WSLogger(fullName)
- }
-
- def start(): Unit = server.start()
-
- def stop(): Unit = server.stop()
-
- def isConnected: Boolean = webSocketConn != null && !closed
- def isClosed: Boolean = closed
-
- def localPort: Int = connector.getLocalPort()
-
- def sendMessage(msg: String) = synchronized {
- if (webSocketConn != null)
- webSocketConn.sendMessage(msg)
- }
-
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/PhantomJSEnv.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/PhantomJSEnv.scala
deleted file mode 100644
index 7bb47d2..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/PhantomJSEnv.scala
+++ /dev/null
@@ -1,466 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin.env.phantomjs
-
-import scala.scalajs.sbtplugin.env._
-
-import scala.scalajs.tools.io._
-import scala.scalajs.tools.classpath._
-import scala.scalajs.tools.env._
-import scala.scalajs.tools.logging._
-
-import scala.scalajs.sbtplugin.JSUtils._
-
-import java.io.{ Console => _, _ }
-import java.net._
-
-import scala.io.Source
-import scala.collection.mutable
-import scala.annotation.tailrec
-
-class PhantomJSEnv(
- phantomjsPath: String = "phantomjs",
- addArgs: Seq[String] = Seq.empty,
- addEnv: Map[String, String] = Map.empty,
- val autoExit: Boolean = true,
- jettyClassLoader: ClassLoader = getClass().getClassLoader()
-) extends ExternalJSEnv(addArgs, addEnv) with ComJSEnv {
-
- import PhantomJSEnv._
-
- protected def vmName: String = "PhantomJS"
- protected def executable: String = phantomjsPath
-
- override def jsRunner(classpath: CompleteClasspath, code: VirtualJSFile,
- logger: Logger, console: JSConsole): JSRunner = {
- new PhantomRunner(classpath, code, logger, console)
- }
-
- override def asyncRunner(classpath: CompleteClasspath, code: VirtualJSFile,
- logger: Logger, console: JSConsole): AsyncJSRunner = {
- new AsyncPhantomRunner(classpath, code, logger, console)
- }
-
- override def comRunner(classpath: CompleteClasspath, code: VirtualJSFile,
- logger: Logger, console: JSConsole): ComJSRunner = {
- new ComPhantomRunner(classpath, code, logger, console)
- }
-
- protected class PhantomRunner(classpath: CompleteClasspath,
- code: VirtualJSFile, logger: Logger, console: JSConsole
- ) extends ExtRunner(classpath, code, logger, console)
- with AbstractPhantomRunner
-
- protected class AsyncPhantomRunner(classpath: CompleteClasspath,
- code: VirtualJSFile, logger: Logger, console: JSConsole
- ) extends AsyncExtRunner(classpath, code, logger, console)
- with AbstractPhantomRunner
-
- protected class ComPhantomRunner(classpath: CompleteClasspath,
- code: VirtualJSFile, logger: Logger, console: JSConsole
- ) extends AsyncPhantomRunner(classpath, code, logger, console)
- with ComJSRunner with WebsocketListener {
-
- private def loadMgr() = {
- val clazz = jettyClassLoader.loadClass(
- "scala.scalajs.sbtplugin.env.phantomjs.JettyWebsocketManager")
-
- val ctors = clazz.getConstructors()
- assert(ctors.length == 1, "JettyWebsocketManager may only have one ctor")
-
- val mgr = ctors.head.newInstance(this)
-
- mgr.asInstanceOf[WebsocketManager]
- }
-
- val mgr: WebsocketManager = loadMgr()
-
- def onRunning(): Unit = synchronized(notifyAll())
- def onOpen(): Unit = synchronized(notifyAll())
- def onClose(): Unit = synchronized(notifyAll())
-
- def onMessage(msg: String): Unit = synchronized {
- recvBuf.enqueue(msg)
- notifyAll()
- }
-
- def log(msg: String): Unit = logger.debug(s"PhantomJS WS Jetty: $msg")
-
- private[this] val recvBuf = mutable.Queue.empty[String]
-
- mgr.start()
-
- /** The websocket server starts asynchronously, but we need the port it is
- * running on. This method waits until the port is non-negative and
- * returns its value.
- */
- private def waitForPort(): Int = {
- while (mgr.localPort < 0)
- wait()
- mgr.localPort
- }
-
- private def comSetup = {
- def maybeExit(code: Int) =
- if (autoExit)
- s"window.callPhantom({ action: 'exit', returnValue: $code });"
- else
- ""
-
- val serverPort = waitForPort()
-
- val code = s"""
- |(function() {
- | var MaxPayloadSize = $MaxCharPayloadSize;
- |
- | // The socket for communication
- | var websocket = null;
- |
- | // Buffer for messages sent before socket is open
- | var outMsgBuf = null;
- |
- | function sendImpl(msg) {
- | var frags = (msg.length / MaxPayloadSize) | 0;
- |
- | for (var i = 0; i < frags; ++i) {
- | var payload = msg.substring(
- | i * MaxPayloadSize, (i + 1) * MaxPayloadSize);
- | websocket.send("1" + payload);
- | }
- |
- | websocket.send("0" + msg.substring(frags * MaxPayloadSize));
- | }
- |
- | function recvImpl(recvCB) {
- | var recvBuf = "";
- |
- | return function(evt) {
- | var newData = recvBuf + evt.data.substring(1);
- | if (evt.data.charAt(0) == "0") {
- | recvBuf = "";
- | recvCB(newData);
- | } else if (evt.data.charAt(0) == "1") {
- | recvBuf = newData;
- | } else {
- | throw new Error("Bad fragmentation flag in " + evt.data);
- | }
- | };
- | }
- |
- | window.scalajsCom = {
- | init: function(recvCB) {
- | if (websocket !== null) throw new Error("Com already open");
- |
- | outMsgBuf = [];
- |
- | websocket = new WebSocket("ws://localhost:$serverPort");
- |
- | websocket.onopen = function(evt) {
- | for (var i = 0; i < outMsgBuf.length; ++i)
- | sendImpl(outMsgBuf[i]);
- | outMsgBuf = null;
- | };
- | websocket.onclose = function(evt) {
- | websocket = null;
- | ${maybeExit(0)}
- | };
- | websocket.onmessage = recvImpl(recvCB);
- | websocket.onerror = function(evt) {
- | websocket = null;
- | throw new Error("Websocket failed: " + evt);
- | };
- |
- | // Take over responsibility to auto exit
- | window.callPhantom({
- | action: 'setAutoExit',
- | autoExit: false
- | });
- | },
- | send: function(msg) {
- | if (websocket === null)
- | return; // we are closed already. ignore message
- |
- | if (outMsgBuf !== null)
- | outMsgBuf.push(msg);
- | else
- | sendImpl(msg);
- | },
- | close: function() {
- | if (websocket === null)
- | return; // we are closed already. all is well.
- |
- | if (outMsgBuf !== null)
- | // Reschedule ourselves to give onopen a chance to kick in
- | window.setTimeout(window.scalajsCom.close, 10);
- | else
- | websocket.close();
- | }
- | }
- |}).call(this);""".stripMargin
-
- new MemVirtualJSFile("comSetup.js").withContent(code)
- }
-
- def send(msg: String): Unit = synchronized {
- if (awaitConnection()) {
- val fragParts = msg.length / MaxCharPayloadSize
-
- for (i <- 0 until fragParts) {
- val payload = msg.substring(
- i * MaxCharPayloadSize, (i + 1) * MaxCharPayloadSize)
- mgr.sendMessage("1" + payload)
- }
-
- mgr.sendMessage("0" + msg.substring(fragParts * MaxCharPayloadSize))
- }
- }
-
- def receive(): String = synchronized {
- if (recvBuf.isEmpty && !awaitConnection())
- throw new ComJSEnv.ComClosedException
-
- @tailrec
- def loop(acc: String): String = {
- val frag = receiveFrag()
- val newAcc = acc + frag.substring(1)
-
- if (frag(0) == '0')
- newAcc
- else if (frag(0) == '1')
- loop(newAcc)
- else
- throw new AssertionError("Bad fragmentation flag in " + frag)
- }
-
- loop("")
- }
-
- private def receiveFrag(): String = {
- while (recvBuf.isEmpty && !mgr.isClosed)
- wait()
-
- if (recvBuf.isEmpty)
- throw new ComJSEnv.ComClosedException
- else
- recvBuf.dequeue()
- }
-
- def close(): Unit = mgr.stop()
-
- override def stop(): Unit = {
- close()
- super.stop()
- }
-
- /** Waits until the JS VM has established a connection, or the VM
- * terminated. Returns true if a connection was established.
- */
- private def awaitConnection(): Boolean = {
- while (!mgr.isConnected && !mgr.isClosed && isRunning)
- wait(200) // We sleep-wait for isRunning
-
- mgr.isConnected
- }
-
- override protected def initFiles(): Seq[VirtualJSFile] =
- super.initFiles :+ comSetup
- }
-
- protected trait AbstractPhantomRunner extends AbstractExtRunner {
-
- override protected def getVMArgs() =
- // Add launcher file to arguments
- additionalArgs :+ createTmpLauncherFile().getAbsolutePath
-
- /** In phantom.js, we include JS using HTML */
- override protected def writeJSFile(file: VirtualJSFile, writer: Writer) = {
- file match {
- case file: FileVirtualJSFile =>
- val fname = htmlEscape(file.file.getAbsolutePath)
- writer.write(
- s"""<script type="text/javascript" src="$fname"></script>""" + "\n")
- case _ =>
- writer.write("""<script type="text/javascript">""" + "\n")
- writer.write(s"// Virtual File: ${file.path}\n")
- writer.write(file.content)
- writer.write("</script>\n")
- }
- }
-
- /**
- * PhantomJS doesn't support Function.prototype.bind. We polyfill it.
- * https://github.com/ariya/phantomjs/issues/10522
- */
- override protected def initFiles(): Seq[VirtualJSFile] = Seq(
- new MemVirtualJSFile("bindPolyfill.js").withContent(
- """
- |// Polyfill for Function.bind from Facebook react:
- |// https://github.com/facebook/react/blob/3dc10749080a460e48bee46d769763ec7191ac76/src/test/phantomjs-shims.js
- |// Originally licensed under Apache 2.0
- |(function() {
- |
- | var Ap = Array.prototype;
- | var slice = Ap.slice;
- | var Fp = Function.prototype;
- |
- | if (!Fp.bind) {
- | // PhantomJS doesn't support Function.prototype.bind natively, so
- | // polyfill it whenever this module is required.
- | Fp.bind = function(context) {
- | var func = this;
- | var args = slice.call(arguments, 1);
- |
- | function bound() {
- | var invokedAsConstructor = func.prototype && (this instanceof func);
- | return func.apply(
- | // Ignore the context parameter when invoking the bound function
- | // as a constructor. Note that this includes not only constructor
- | // invocations using the new keyword but also calls to base class
- | // constructors such as BaseClass.call(this, ...) or super(...).
- | !invokedAsConstructor && context || this,
- | args.concat(slice.call(arguments))
- | );
- | }
- |
- | // The bound function must share the .prototype of the unbound
- | // function so that any object created by one constructor will count
- | // as an instance of both constructors.
- | bound.prototype = func.prototype;
- |
- | return bound;
- | };
- | }
- |
- |})();
- |""".stripMargin
- ),
- new MemVirtualJSFile("scalaJSEnvInfo.js").withContent(
- """
- |__ScalaJSEnv = {
- | exitFunction: function(status) {
- | window.callPhantom({
- | action: 'exit',
- | returnValue: status | 0
- | });
- | }
- |};
- """.stripMargin
- )
- )
-
- protected def writeWebpageLauncher(out: Writer): Unit = {
- out.write("<html>\n<head>\n<title>Phantom.js Launcher</title>\n")
- sendJS(getLibJSFiles(), out)
- writeCodeLauncher(code, out)
- out.write("</head>\n<body></body>\n</html>\n")
- }
-
- protected def createTmpLauncherFile(): File = {
- val webF = createTmpWebpage()
-
- val launcherTmpF = File.createTempFile("phantomjs-launcher", ".js")
- launcherTmpF.deleteOnExit()
-
- val out = new FileWriter(launcherTmpF)
-
- try {
- out.write(
- s"""// Scala.js Phantom.js launcher
- |var page = require('webpage').create();
- |var url = ${toJSstr(webF.getAbsolutePath)};
- |var autoExit = $autoExit;
- |page.onConsoleMessage = function(msg) {
- | console.log(msg);
- |};
- |page.onError = function(msg, trace) {
- | console.error(msg);
- | if (trace && trace.length) {
- | console.error('');
- | trace.forEach(function(t) {
- | console.error(' ' + t.file + ':' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
- | });
- | }
- |
- | phantom.exit(2);
- |};
- |page.onCallback = function(data) {
- | if (!data.action) {
- | console.error('Called callback without action');
- | phantom.exit(3);
- | } else if (data.action === 'exit') {
- | phantom.exit(data.returnValue || 0);
- | } else if (data.action === 'setAutoExit') {
- | if (typeof(data.autoExit) === 'boolean')
- | autoExit = data.autoExit;
- | else
- | autoExit = true;
- | } else {
- | console.error('Unknown callback action ' + data.action);
- | phantom.exit(4);
- | }
- |};
- |page.open(url, function (status) {
- | if (autoExit || status !== 'success')
- | phantom.exit(status !== 'success');
- |});
- |""".stripMargin)
- } finally {
- out.close()
- }
-
- logger.debug(
- "PhantomJS using launcher at: " + launcherTmpF.getAbsolutePath())
-
- launcherTmpF
- }
-
- protected def createTmpWebpage(): File = {
- val webTmpF = File.createTempFile("phantomjs-launcher-webpage", ".html")
- webTmpF.deleteOnExit()
-
- val out = new BufferedWriter(new FileWriter(webTmpF))
- try {
- writeWebpageLauncher(out)
- } finally {
- out.close()
- }
-
- logger.debug(
- "PhantomJS using webpage launcher at: " + webTmpF.getAbsolutePath())
-
- webTmpF
- }
-
- protected def writeCodeLauncher(code: VirtualJSFile, out: Writer): Unit = {
- out.write("""<script type="text/javascript">""" + "\n")
- out.write("// Phantom.js code launcher\n")
- out.write(s"// Origin: ${code.path}\n")
- out.write("window.addEventListener('load', function() {\n")
- out.write(code.content)
- out.write("}, false);\n")
- out.write("</script>\n")
- }
- }
-
- protected def htmlEscape(str: String): String = str.flatMap {
- case '<' => "&lt;"
- case '>' => "&gt;"
- case '"' => "&quot;"
- case '&' => "&amp;"
- case c => c :: Nil
- }
-
-}
-
-object PhantomJSEnv {
- private final val MaxByteMessageSize = 32768 // 32 KB
- private final val MaxCharMessageSize = MaxByteMessageSize / 2 // 2B per char
- private final val MaxCharPayloadSize = MaxCharMessageSize - 1 // frag flag
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/PhantomJettyClassLoader.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/PhantomJettyClassLoader.scala
deleted file mode 100644
index 02c229b..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/PhantomJettyClassLoader.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package scala.scalajs.sbtplugin.env.phantomjs
-
-import scala.scalajs.tools.io.IO
-
-/** A special [[ClassLoader]] to load the Jetty 8 dependency of [[PhantomJSEnv]]
- * in a private space.
- *
- * It loads everything that belongs to [[JettyWebsocketManager]] itself (while
- * retrieving the requested class file from its parent.
- * For all other classes, it first tries to load them from [[jettyLoader]],
- * which should only contain the Jetty 8 classpath.
- * If this fails, it delegates to its parent.
- *
- * The rationale is, that [[JettyWebsocketManager]] and its dependees can use
- * the classes on the Jetty 8 classpath, while they remain hidden from the rest
- * of the Java world. This allows to load another version of Jetty in the same
- * JVM for the rest of the project.
- */
-private[sbtplugin] class PhantomJettyClassLoader(jettyLoader: ClassLoader,
- parent: ClassLoader) extends ClassLoader(parent) {
-
- def this(loader: ClassLoader) =
- this(loader, ClassLoader.getSystemClassLoader())
-
- /** Classes needed to bridge private jetty classpath and public PhantomJS
- * Basically everything defined in JettyWebsocketManager.
- */
- private val bridgeClasses = Set(
- "scala.scalajs.sbtplugin.env.phantomjs.JettyWebsocketManager",
- "scala.scalajs.sbtplugin.env.phantomjs.JettyWebsocketManager$WSLogger",
- "scala.scalajs.sbtplugin.env.phantomjs.JettyWebsocketManager$ComWebSocketListener",
- "scala.scalajs.sbtplugin.env.phantomjs.JettyWebsocketManager$$anon$1",
- "scala.scalajs.sbtplugin.env.phantomjs.JettyWebsocketManager$$anon$2"
- )
-
- override protected def loadClass(name: String, resolve: Boolean): Class[_] = {
- if (bridgeClasses.contains(name)) {
- // Load bridgeClasses manually since they must be associated to this
- // class loader, rather than the parent class loader in order to find the
- // jetty classes
-
- // First check if we have loaded it already
- Option(findLoadedClass(name)) getOrElse {
- val wsManager =
- parent.getResourceAsStream(name.replace('.', '/') + ".class")
-
- if (wsManager == null) {
- throw new ClassNotFoundException(name)
- } else {
- val buf = IO.readInputStreamToByteArray(wsManager)
- defineClass(name, buf, 0, buf.length)
- }
- }
- } else {
- try {
- jettyLoader.loadClass(name)
- } catch {
- case _: ClassNotFoundException =>
- super.loadClass(name, resolve)
- }
- }
- }
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/WebsocketListener.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/WebsocketListener.scala
deleted file mode 100644
index 4faac64..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/WebsocketListener.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package scala.scalajs.sbtplugin.env.phantomjs
-
-private[phantomjs] trait WebsocketListener {
- def onRunning(): Unit
- def onOpen(): Unit
- def onClose(): Unit
- def onMessage(msg: String): Unit
-
- def log(msg: String): Unit
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/WebsocketManager.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/WebsocketManager.scala
deleted file mode 100644
index a466841..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/phantomjs/WebsocketManager.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package scala.scalajs.sbtplugin.env.phantomjs
-
-private[phantomjs] trait WebsocketManager {
- def start(): Unit
- def stop(): Unit
- def sendMessage(msg: String): Unit
- def localPort: Int
- def isConnected: Boolean
- def isClosed: Boolean
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/LazyScalaJSScope.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/LazyScalaJSScope.scala
deleted file mode 100644
index d4cdaee..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/LazyScalaJSScope.scala
+++ /dev/null
@@ -1,96 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin.env.rhino
-
-import scala.collection.mutable
-
-import org.mozilla.javascript.Scriptable
-
-/** 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
- * turned to a LazyScalaJSScope. Upon first access to a field of ScalaJS.c,
- * say ScalaJS.c.scala_Option, the script defining that particular
- * field will be loaded.
- * This is possible because the relative path to the script can be derived
- * from the name of the property being accessed.
- *
- * It is immensely useful, because it allows to load lazily only the scripts
- * that are actually needed.
- */
-class LazyScalaJSScope(
- coreLib: ScalaJSCoreLib,
- globalScope: Scriptable,
- base: Scriptable,
- isModule: Boolean = false,
- isTraitImpl: Boolean = false) extends Scriptable {
-
- private val fields = mutable.HashMap.empty[String, Any]
- private var prototype: Scriptable = _
- private var parentScope: Scriptable = _
-
- {
- // Pre-fill fields with the properties of `base`
- for (id <- base.getIds()) {
- (id.asInstanceOf[Any]: @unchecked) match {
- case name: String => put(name, this, base.get(name, base))
- case index: Int => put(index, this, base.get(index, base))
- }
- }
- }
-
- private def load(name: String): Unit =
- coreLib.load(globalScope, propNameToEncodedName(name))
-
- private def propNameToEncodedName(name: String): String = {
- if (isTraitImpl) name.split("__")(0)
- else if (isModule) name + "$"
- else name
- }
-
- override def getClassName() = "LazyScalaJSScope"
-
- override def get(name: String, start: Scriptable) = {
- fields.getOrElse(name, {
- load(name)
- fields.getOrElse(name, Scriptable.NOT_FOUND)
- }).asInstanceOf[AnyRef]
- }
- override def get(index: Int, start: Scriptable) =
- get(index.toString, start)
-
- override def has(name: String, start: Scriptable) =
- fields.contains(name)
- override def has(index: Int, start: Scriptable) =
- has(index.toString, start)
-
- override def put(name: String, start: Scriptable, value: Any) = {
- fields(name) = value
- }
- override def put(index: Int, start: Scriptable, value: Any) =
- put(index.toString, start, value)
-
- override def delete(name: String) = ()
- override def delete(index: Int) = ()
-
- override def getPrototype() = prototype
- override def setPrototype(value: Scriptable) = prototype = value
-
- override def getParentScope() = parentScope
- override def setParentScope(value: Scriptable) = parentScope = value
-
- override def getIds() = fields.keys.toArray
-
- override def getDefaultValue(hint: java.lang.Class[_]) = {
- base.getDefaultValue(hint)
- }
-
- override def hasInstance(instance: Scriptable) = false
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/RhinoJSEnv.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/RhinoJSEnv.scala
deleted file mode 100644
index cd35ff6..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/RhinoJSEnv.scala
+++ /dev/null
@@ -1,303 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin.env.rhino
-
-import scala.scalajs.tools.sem.Semantics
-import scala.scalajs.tools.io._
-import scala.scalajs.tools.classpath._
-import scala.scalajs.tools.env._
-import scala.scalajs.tools.logging._
-
-import scala.io.Source
-
-import scala.collection.mutable
-
-import scala.concurrent.{Future, Promise, Await}
-import scala.concurrent.duration.Duration
-
-import org.mozilla.javascript._
-
-class RhinoJSEnv(semantics: Semantics,
- withDOM: Boolean = false) extends ComJSEnv {
-
- import RhinoJSEnv._
-
- /** Executes code in an environment where the Scala.js library is set up to
- * load its classes lazily.
- *
- * Other .js scripts in the inputs are executed eagerly before the provided
- * `code` is called.
- */
- override def jsRunner(classpath: CompleteClasspath, code: VirtualJSFile,
- logger: Logger, console: JSConsole): JSRunner = {
- new Runner(classpath, code, logger, console)
- }
-
- private class Runner(classpath: CompleteClasspath, code: VirtualJSFile,
- logger: Logger, console: JSConsole) extends JSRunner {
- def run(): Unit = internalRunJS(classpath, code, logger, console, None)
- }
-
- override def asyncRunner(classpath: CompleteClasspath, code: VirtualJSFile,
- logger: Logger, console: JSConsole): AsyncJSRunner = {
- new AsyncRunner(classpath, code, logger, console)
- }
-
- private class AsyncRunner(classpath: CompleteClasspath, code: VirtualJSFile,
- logger: Logger, console: JSConsole) extends AsyncJSRunner {
-
- private[this] val promise = Promise[Unit]
-
- private[this] val thread = new Thread {
- override def run(): Unit = {
- try {
- internalRunJS(classpath, code, logger, console, optChannel)
- promise.success(())
- } catch {
- case t: Throwable =>
- promise.failure(t)
- }
- }
- }
-
- def start(): Future[Unit] = {
- thread.start()
- promise.future
- }
-
- def stop(): Unit = thread.interrupt()
-
- def isRunning(): Boolean = !promise.isCompleted
-
- def await(): Unit = Await.result(promise.future, Duration.Inf)
-
- protected def optChannel(): Option[Channel] = None
- }
-
- override def comRunner(classpath: CompleteClasspath, code: VirtualJSFile,
- logger: Logger, console: JSConsole): ComJSRunner = {
- new ComRunner(classpath, code, logger, console)
- }
-
- private class ComRunner(classpath: CompleteClasspath, code: VirtualJSFile,
- logger: Logger, console: JSConsole)
- extends AsyncRunner(classpath, code, logger, console) with ComJSRunner {
-
- private[this] val channel = new Channel
-
- override protected def optChannel(): Option[Channel] = Some(channel)
-
- def send(msg: String): Unit = {
- try {
- channel.sendToJS(msg)
- } catch {
- case _: ChannelClosedException =>
- throw new ComJSEnv.ComClosedException
- }
- }
-
- def receive(): String = {
- try {
- channel.recvJVM()
- } catch {
- case _: ChannelClosedException =>
- throw new ComJSEnv.ComClosedException
- }
- }
-
- def close(): Unit = channel.close()
-
- override def stop(): Unit = {
- close()
- super.stop()
- }
-
- }
-
- private def internalRunJS(classpath: CompleteClasspath, code: VirtualJSFile,
- logger: Logger, console: JSConsole, optChannel: Option[Channel]): Unit = {
-
- val context = Context.enter()
- try {
- val scope = context.initStandardObjects()
-
- if (withDOM) {
- // Fetch env.rhino.js from webjar
- val name = "env.rhino.js"
- val path = "/META-INF/resources/webjars/envjs/1.2/" + name
- val resource = getClass.getResource(path)
- assert(resource != null, s"need $name as resource")
-
- // Rhino can't optimize envjs
- context.setOptimizationLevel(-1)
-
- // Don't print envjs header
- scope.addFunction("print", args => ())
-
- // Pipe file to Rhino
- val reader = Source.fromURL(resource).bufferedReader
- context.evaluateReader(scope, reader, name, 1, null);
-
- // No need to actually define print here: It is captured by envjs to
- // implement console.log, which we'll override in the next statement
- }
-
- // Make sure Rhino does not do its magic for JVM top-level packages (#364)
- val PackagesObject =
- ScriptableObject.getProperty(scope, "Packages").asInstanceOf[Scriptable]
- val topLevelPackageIds = ScriptableObject.getPropertyIds(PackagesObject)
- for (id <- topLevelPackageIds) (id: Any) match {
- case name: String => ScriptableObject.deleteProperty(scope, name)
- case index: Int => ScriptableObject.deleteProperty(scope, index)
- case _ => // should not happen, I think, but with Rhino you never know
- }
-
- // Setup console.log
- val jsconsole = context.newObject(scope)
- jsconsole.addFunction("log", _.foreach(console.log _))
- ScriptableObject.putProperty(scope, "console", jsconsole)
-
- // Optionally setup scalaJSCom
- var recvCallback: Option[String => Unit] = None
- for (channel <- optChannel) {
- val comObj = context.newObject(scope)
-
- comObj.addFunction("send", s =>
- channel.sendToJVM(Context.toString(s(0))))
-
- comObj.addFunction("init", s => s(0) match {
- case f: Function =>
- val cb: String => Unit =
- msg => f.call(context, scope, scope, Array(msg))
- recvCallback = Some(cb)
- case _ =>
- sys.error("First argument to init must be a function")
- })
-
- comObj.addFunction("close", _ => {
- // Tell JVM side we won't send anything
- channel.close()
- // Internally register that we're done
- recvCallback = None
- })
-
- ScriptableObject.putProperty(scope, "scalajsCom", comObj)
- }
-
- try {
- // Make the classpath available. Either through lazy loading or by
- // simply inserting
- classpath match {
- case cp: IRClasspath =>
- // Setup lazy loading classpath and source mapper
- val optLoader = if (cp.scalaJSIR.nonEmpty) {
- val loader = new ScalaJSCoreLib(semantics, cp)
-
- // Setup sourceMapper
- val scalaJSenv = context.newObject(scope)
-
- scalaJSenv.addFunction("sourceMapper", args => {
- val trace = Context.toObject(args(0), scope)
- loader.mapStackTrace(trace, context, scope)
- })
-
- ScriptableObject.putProperty(scope, "__ScalaJSEnv", scalaJSenv)
-
- Some(loader)
- } else {
- None
- }
-
- // Load JS libraries
- cp.jsLibs.foreach(dep => context.evaluateFile(scope, dep.lib))
-
- optLoader.foreach(_.insertInto(context, scope))
- case cp =>
- cp.allCode.foreach(context.evaluateFile(scope, _))
- }
-
- context.evaluateFile(scope, code)
-
- // Callback the com channel if necessary (if comCallback = None, channel
- // wasn't initialized on the client)
- for ((channel, callback) <- optChannel zip recvCallback) {
- try {
- while (recvCallback.isDefined)
- callback(channel.recvJS())
- } catch {
- case _: ChannelClosedException =>
- // the JVM side closed the connection
- }
- }
-
- // Enusre the channel is closed to release JVM side
- optChannel.foreach(_.close)
-
- } catch {
- case e: RhinoException =>
- // Trace here, since we want to be in the context to trace.
- logger.trace(e)
- sys.error(s"Exception while running JS code: ${e.getMessage}")
- }
- } finally {
- Context.exit()
- }
- }
-
-}
-
-object RhinoJSEnv {
-
- /** Communication channel between the Rhino thread and the rest of the JVM */
- private class Channel {
- private[this] var _closed = false
- private[this] val js2jvm = mutable.Queue.empty[String]
- private[this] val jvm2js = mutable.Queue.empty[String]
-
- def sendToJS(msg: String): Unit = synchronized {
- jvm2js.enqueue(msg)
- notify()
- }
-
- def sendToJVM(msg: String): Unit = synchronized {
- js2jvm.enqueue(msg)
- notify()
- }
-
- def recvJVM(): String = synchronized {
- while (js2jvm.isEmpty && ensureOpen())
- wait()
-
- js2jvm.dequeue()
- }
-
- def recvJS(): String = synchronized {
- while (jvm2js.isEmpty && ensureOpen())
- wait()
-
- jvm2js.dequeue()
- }
-
- def close(): Unit = synchronized {
- _closed = true
- notify()
- }
-
- /** Throws if the channel is closed and returns true */
- private def ensureOpen(): Boolean = {
- if (_closed)
- throw new ChannelClosedException
- true
- }
- }
-
- private class ChannelClosedException extends Exception
-
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/ScalaJSCoreLib.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/ScalaJSCoreLib.scala
deleted file mode 100644
index e937e5b..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/ScalaJSCoreLib.scala
+++ /dev/null
@@ -1,173 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin.env.rhino
-
-import scala.collection.mutable
-
-import org.mozilla.javascript.{Context, Scriptable}
-
-import scala.scalajs.ir
-
-import scala.scalajs.tools.sem.Semantics
-import scala.scalajs.tools.javascript.{Printers, ScalaJSClassEmitter}
-import scala.scalajs.tools.io._
-import scala.scalajs.tools.classpath._
-import scala.scalajs.tools.corelib._
-
-class ScalaJSCoreLib(semantics: Semantics, classpath: IRClasspath) {
- import ScalaJSCoreLib._
-
- private val (providers, exportedSymbols) = {
- val providers = mutable.Map.empty[String, VirtualScalaJSIRFile]
- val exportedSymbols = mutable.ListBuffer.empty[String]
-
- for (irFile <- classpath.scalaJSIR) {
- val info = irFile.roughInfo
- providers += info.encodedName -> irFile
- if (info.isExported)
- exportedSymbols += info.encodedName
- }
-
- (providers, exportedSymbols)
- }
-
- def insertInto(context: Context, scope: Scriptable) = {
- CoreJSLibs.libs(semantics).foreach(context.evaluateFile(scope, _))
- lazifyScalaJSFields(scope)
-
- // Make sure exported symbols are loaded
- val ScalaJS = Context.toObject(scope.get("ScalaJS", scope), scope)
- val c = Context.toObject(ScalaJS.get("c", ScalaJS), scope)
- for (encodedName <- exportedSymbols)
- c.get(encodedName, c)
- }
-
- /** Source maps the given stack trace (where possible) */
- def mapStackTrace(stackTrace: Scriptable,
- context: Context, scope: Scriptable): Scriptable = {
- val count = Context.toNumber(stackTrace.get("length", stackTrace)).toInt
-
- // Maps file -> max line (0-based)
- val neededMaps = mutable.Map.empty[String, Int]
-
- // Collect required line counts
- for (i <- 0 until count) {
- val elem = Context.toObject(stackTrace.get(i, stackTrace), scope)
- val fileName = Context.toString(elem.get("fileName", elem))
-
- if (fileName.endsWith(PseudoFileSuffix) &&
- providers.contains(fileName.stripSuffix(PseudoFileSuffix))) {
-
- val curMaxLine = neededMaps.getOrElse(fileName, -1)
- val reqLine = Context.toNumber(elem.get("lineNumber", elem)).toInt - 1
-
- if (reqLine > curMaxLine)
- neededMaps.put(fileName, reqLine)
- }
- }
-
- // Map required files
- val maps =
- for ((fileName, maxLine) <- neededMaps)
- yield (fileName, getSourceMapper(fileName, maxLine))
-
- // Create new stack trace to return
- val res = context.newArray(scope, count)
-
- for (i <- 0 until count) {
- val elem = Context.toObject(stackTrace.get(i, stackTrace), scope)
- val fileName = Context.toString(elem.get("fileName", elem))
- val line = Context.toNumber(elem.get("lineNumber", elem)).toInt - 1
-
- val pos = maps.get(fileName).fold(ir.Position.NoPosition)(_(line))
-
- val newElem =
- if (pos.isDefined) newPosElem(scope, context, elem, pos)
- else elem
-
- res.put(i, res, newElem)
- }
-
- res
- }
-
- private def getSourceMapper(fileName: String, untilLine: Int) = {
- val irFile = providers(fileName.stripSuffix(PseudoFileSuffix))
- val mapper = new Printers.ReverseSourceMapPrinter(untilLine)
- val classDef = irFile.tree
- val desugared = new ScalaJSClassEmitter(semantics).genClassDef(classDef)
- mapper.reverseSourceMap(desugared)
- mapper
- }
-
- private def newPosElem(scope: Scriptable, context: Context,
- origElem: Scriptable, pos: ir.Position): Scriptable = {
- assert(pos.isDefined)
-
- val elem = context.newObject(scope)
-
- elem.put("declaringClass", elem, origElem.get("declaringClass", origElem))
- elem.put("methodName", elem, origElem.get("methodName", origElem))
- elem.put("fileName", elem, pos.source.toString)
- elem.put("lineNumber", elem, pos.line + 1)
- elem.put("columnNumber", elem, pos.column + 1)
-
- elem
- }
-
- private val scalaJSLazyFields = Seq(
- Info("d"),
- Info("c"),
- Info("h"),
- Info("i", isTraitImpl = true),
- Info("n", isModule = true),
- Info("m", isModule = true),
- Info("is"),
- Info("as"),
- Info("isArrayOf"),
- Info("asArrayOf"))
-
- private def lazifyScalaJSFields(scope: Scriptable) = {
- val ScalaJS = Context.toObject(scope.get("ScalaJS", scope), scope)
-
- def makeLazyScalaJSScope(base: Scriptable, isModule: Boolean, isTraitImpl: Boolean) =
- new LazyScalaJSScope(this, scope, base, isModule, isTraitImpl)
-
- for (Info(name, isModule, isTraitImpl) <- scalaJSLazyFields) {
- val base = ScalaJS.get(name, ScalaJS).asInstanceOf[Scriptable]
- val lazified = makeLazyScalaJSScope(base, isModule, isTraitImpl)
- ScalaJS.put(name, ScalaJS, lazified)
- }
- }
-
- private[rhino] def load(scope: Scriptable, encodedName: String): Unit = {
- providers.get(encodedName) foreach { irFile =>
- val codeWriter = new java.io.StringWriter
- val printer = new Printers.JSTreePrinter(codeWriter)
- val classDef = irFile.tree
- val desugared = new ScalaJSClassEmitter(semantics).genClassDef(classDef)
- printer.printTopLevelTree(desugared)
- printer.complete()
- val ctx = Context.getCurrentContext()
- val fakeFileName = encodedName + PseudoFileSuffix
- ctx.evaluateString(scope, codeWriter.toString(),
- fakeFileName, 1, null)
- }
- }
-}
-
-object ScalaJSCoreLib {
- private case class Info(name: String,
- isModule: Boolean = false, isTraitImpl: Boolean = false)
-
- private val EncodedNameLine = raw""""encodedName": *"([^"]+)"""".r.unanchored
-
- private final val PseudoFileSuffix = ".sjsir"
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/package.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/package.scala
deleted file mode 100644
index 926fbb2..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/env/rhino/package.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin.env
-
-import org.mozilla.javascript._
-
-import scala.scalajs.tools.io._
-
-package object rhino {
-
- implicit class ContextOps(val self: Context) extends AnyVal {
- def evaluateFile(scope: Scriptable, file: VirtualJSFile,
- securityDomain: AnyRef = null): Any = {
- self.evaluateString(scope, file.content, file.path, 1, securityDomain)
- }
- }
-
- implicit class ScriptableObjectOps(val self: Scriptable) {
- def addFunction(name: String, function: Array[AnyRef] => Any) = {
- val rhinoFunction =
- new BaseFunction {
- ScriptRuntime.setFunctionProtoAndParent(this, self)
- override def call(context: Context, scope: Scriptable,
- thisObj: Scriptable, args: Array[AnyRef]): AnyRef = {
- function(args) match {
- case () => Undefined.instance
- case r => r.asInstanceOf[AnyRef]
- }
- }
- }
-
- ScriptableObject.putProperty(self, name, rhinoFunction)
- }
- }
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/impl/DependencyBuilders.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/impl/DependencyBuilders.scala
deleted file mode 100644
index 32ffb94..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/impl/DependencyBuilders.scala
+++ /dev/null
@@ -1,99 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin
-package impl
-
-import scala.language.implicitConversions
-import scala.language.experimental.macros
-
-import sbt._
-
-import StringUtilities.nonEmpty
-
-trait DependencyBuilders {
- final implicit def toScalaJSGroupID(groupID: String): ScalaJSGroupID = {
- nonEmpty(groupID, "Group ID")
- new ScalaJSGroupID(groupID)
- }
-
- /** Builder to allow for stuff like:
- *
- * ProvidedJS / "foo.js"
- * ProvidedJS / "foo.js" % "test"
- *
- */
- object ProvidedJS {
- def /(name: String): ProvidedJSModuleID = ProvidedJSModuleID(name, None)
- }
-
- /** Builder to allow for stuff like:
- *
- * "org.webjars" % "jquery" % "1.10.2" / "jquery.js"
- * "org.webjars" % "jquery" % "1.10.2" / "jquery.js" % "test"
- *
- */
- implicit class JSModuleIDBuilder(module: ModuleID) {
- def /(name: String): JarJSModuleID = JarJSModuleID(module, name)
- }
-}
-
-final class ScalaJSGroupID private[sbtplugin] (private val groupID: String) {
- def %%%(artifactID: String): CrossGroupArtifactID =
- macro ScalaJSGroupID.auto_impl
-
- def %%%!(artifactID: String): CrossGroupArtifactID =
- ScalaJSGroupID.withCross(this, artifactID, ScalaJSCrossVersion.binary)
-}
-
-object ScalaJSGroupID {
- import scala.reflect.macros.Context
-
- /** Internal. Used by the macro implementing [[ScalaJSGroupID.%%%]]. Use:
- * {{{
- * ("a" % artifactID % revision).cross(cross)
- * }}}
- * instead.
- */
- def withCross(groupID: ScalaJSGroupID, artifactID: String,
- cross: CrossVersion): CrossGroupArtifactID = {
- nonEmpty(artifactID, "Artifact ID")
- new CrossGroupArtifactID(groupID.groupID, artifactID, cross)
- }
-
- def auto_impl(c: Context { type PrefixType = ScalaJSGroupID })(
- artifactID: c.Expr[String]): c.Expr[CrossGroupArtifactID] = {
- import c.universe._
-
- // Hack to work around bug in sbt macros (wrong way of collecting local
- // definitions)
- val keysSym = rootMirror.staticModule(
- "_root_.scala.scalajs.sbtplugin.ScalaJSPlugin.autoImport")
- val keys = c.Expr[ScalaJSPlugin.autoImport.type](Ident(keysSym))
-
- reify {
- val cross = {
- if (keys.splice.jsDependencies.?.value.isDefined)
- ScalaJSCrossVersion.binary
- else
- CrossVersion.binary
- }
- ScalaJSGroupID.withCross(c.prefix.splice, artifactID.splice, cross)
- }
- }
-
-}
-
-final class CrossGroupArtifactID(groupID: String,
- artifactID: String, crossVersion: CrossVersion) {
- def %(revision: String): ModuleID = {
- nonEmpty(revision, "Revision")
- ModuleID(groupID, artifactID, revision).cross(crossVersion)
- }
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/Events.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/Events.scala
deleted file mode 100644
index f13c195..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/Events.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin.testing
-
-import sbt.testing.{Event => SbtEvent, _}
-
-class Events(taskDef: TaskDef) {
-
- abstract class Event(val status: Status,
- val throwable: OptionalThrowable = new OptionalThrowable) extends SbtEvent {
- val fullyQualifiedName = taskDef.fullyQualifiedName
- val fingerprint = taskDef.fingerprint
- val selector = taskDef.selectors.headOption.getOrElse(new SuiteSelector)
- val duration = -1L
- }
-
- case class Error(exception: Throwable) extends Event(
- Status.Error, new OptionalThrowable(exception))
-
- case class Failure(exception: Throwable) extends Event(
- Status.Failure, new OptionalThrowable(exception))
-
- case object Succeeded extends Event(Status.Success)
- case object Skipped extends Event(Status.Skipped)
- case object Pending extends Event(Status.Pending)
- case object Ignored extends Event(Status.Ignored)
- case object Canceled extends Event(Status.Canceled)
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/JSClasspathLoader.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/JSClasspathLoader.scala
deleted file mode 100644
index bfe0ffc..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/JSClasspathLoader.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin.testing
-
-import scala.scalajs.tools.classpath.CompleteClasspath
-
-/** A dummy ClassLoader to pass on Scala.js ClasspathContents to tests */
-final case class JSClasspathLoader(cp: CompleteClasspath) extends ClassLoader
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/SbtTestLoggerAccWrapper.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/SbtTestLoggerAccWrapper.scala
deleted file mode 100644
index dfebe00..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/SbtTestLoggerAccWrapper.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package scala.scalajs.sbtplugin.testing
-
-import scala.scalajs.tools.logging._
-import sbt.testing.{ Logger => SbtTestLogger }
-
-class SbtTestLoggerAccWrapper(logger: Seq[SbtTestLogger]) extends Logger {
-
- import scala.scalajs.sbtplugin.Implicits._
- import Level._
-
- def log(level: Level, message: => String): Unit = level match {
- case Error => logger.foreach(_.error(message))
- case Warn => logger.foreach(_.warn(message))
- case Info => logger.foreach(_.info(message))
- case Debug => logger.foreach(_.debug(message))
- }
-
- def success(message: => String): Unit = logger.foreach(_.info(message))
-
- def trace(t: => Throwable): Unit = logger.foreach(_.trace(t))
-
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestException.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestException.scala
deleted file mode 100644
index b4cb09b..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestException.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package scala.scalajs.sbtplugin.testing
-
-/** Dummy Exception to wrap stack traces passed to SBT */
-class TestException(
- message: String,
- stackTrace: Array[StackTraceElement]
-) extends Exception(message) {
- override def getStackTrace = stackTrace
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestFramework.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestFramework.scala
deleted file mode 100644
index ab43bfe..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestFramework.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin.testing
-
-import scala.scalajs.tools.env._
-import scala.scalajs.tools.classpath._
-
-import sbt._
-import sbt.testing._
-import sbt.classpath.ClasspathFilter
-
-import java.net.URLClassLoader
-
-class TestFramework(
- environment: JSEnv,
- jsConsole: JSConsole,
- testFramework: String) extends Framework {
-
- val name = "Scala.js Test Framework"
-
- lazy val fingerprints = Array[Fingerprint](f1)
-
- private val f1 = new SubclassFingerprint {
- val isModule = true
- val superclassName = "scala.scalajs.testbridge.Test"
- val requireNoArgConstructor = true
- }
-
- def runner(args: Array[String], remoteArgs: Array[String],
- testClassLoader: ClassLoader): Runner = {
-
- val jsClasspath = extractClasspath(testClassLoader)
- new TestRunner(environment, jsClasspath, jsConsole,
- testFramework, args, remoteArgs)
- }
-
- /** extract classpath from ClassLoader (which must be a JSClasspathLoader) */
- private def extractClasspath(cl: ClassLoader) = cl match {
- case cl: JSClasspathLoader => cl.cp
- case _ =>
- sys.error("The Scala.js framework only works with a class loader of " +
- s"type JSClasspathLoader (${cl.getClass} given)")
- }
-
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestOutputConsole.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestOutputConsole.scala
deleted file mode 100644
index 9aad956..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestOutputConsole.scala
+++ /dev/null
@@ -1,190 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin.testing
-
-import sbt.testing.Logger
-import sbt.testing.EventHandler
-
-import scala.scalajs.tools.env.JSConsole
-import scala.scalajs.tools.sourcemap.SourceMapper
-import scala.scalajs.tools.classpath.{CompleteClasspath, IRClasspath}
-
-import scala.collection.mutable.ArrayBuffer
-
-import scala.util.Try
-
-import java.util.regex._
-
-/** This parses the messages sent from the test bridge and forwards
- * the calls to SBT. It also buffers all log messages and allows to
- * pipe them to multiple loggers in a synchronized fashion. This
- * ensures that log messages aren't interleaved due to parallelism.
- */
-class TestOutputConsole(
- base: JSConsole,
- handler: EventHandler,
- events: Events,
- classpath: CompleteClasspath,
- noSourceMap: Boolean) extends JSConsole {
-
- import TestOutputConsole._
- import events._
-
- private val traceBuf = new ArrayBuffer[StackTraceElement]
- private val logBuffer = new ArrayBuffer[LogElement]
-
- /* See #727: source mapping does not work with CompleteIRClasspath, so
- * don't bother to try.
- */
- private val ignoreSourceMapping =
- noSourceMap || classpath.isInstanceOf[IRClasspath]
-
- private lazy val sourceMapper = new SourceMapper(classpath)
-
- override def log(msg: Any): Unit = {
- val data = msg.toString
- val sepPos = data.indexOf("|")
-
- if (sepPos == -1)
- log(_.error, s"Malformed message: $data")
- else {
- val op = data.substring(0, sepPos)
- val message = unescape(data.substring(sepPos + 1))
-
- op match {
- case "console-log" =>
- base.log(message)
- case "error" =>
- val trace = getTrace()
- logWithEvent(_.error,
- messageWithStack(message, trace),
- Error(new TestException(message, trace))
- )
- case "failure" =>
- val trace = getTrace()
- logWithEvent(_.error,
- messageWithStack(message, trace),
- Failure(new TestException(message, trace))
- )
- case "succeeded" =>
- noTrace()
- logWithEvent(_.info, message, Succeeded)
- case "skipped" =>
- noTrace()
- logWithEvent(_.info, message, Skipped)
- case "pending" =>
- noTrace()
- logWithEvent(_.info, message, Pending)
- case "ignored" =>
- noTrace()
- logWithEvent(_.info, message, Ignored)
- case "canceled" =>
- noTrace()
- logWithEvent(_.info, message, Canceled)
- case "error-log" =>
- noTrace()
- log(_.error, message)
- case "info" =>
- noTrace()
- log(_.info, message)
- case "warn" =>
- noTrace()
- log(_.warn, message)
- case "trace" =>
- val Array(className, methodName, fileName,
- lineNumberStr, columnNumberStr) = message.split('|')
-
- def tryParse(num: String, name: String) = Try(num.toInt).getOrElse {
- log(_.warn, s"Couldn't parse $name number in StackTrace: $num")
- -1
- }
-
- val lineNumber = tryParse(lineNumberStr, "line")
- val columnNumber = tryParse(columnNumberStr, "column")
-
- val ste =
- new StackTraceElement(className, methodName, fileName, lineNumber)
-
- if (ignoreSourceMapping)
- traceBuf += ste
- else
- traceBuf += sourceMapper.map(ste, columnNumber)
- case _ =>
- noTrace()
- log(_.error, s"Unknown op: $op. Originating log message: $data")
- }
- }
- }
-
- private def noTrace() = {
- if (traceBuf.nonEmpty)
- log(_.warn, s"Discarding ${traceBuf.size} stack elements")
- traceBuf.clear()
- }
-
- private def getTrace() = {
- val res = traceBuf.toArray
- traceBuf.clear()
- res
- }
-
- private def messageWithStack(message: String, stack: Array[StackTraceElement]): String =
- message + stack.mkString("\n", "\n", "")
-
- private def log(method: LogMethod, message: String): Unit =
- logBuffer.append(LogElement(method, message))
-
- private def logWithEvent(method: LogMethod,
- message: String, event: Event): Unit = {
- handler handle event
- log(method, message)
- }
-
- def pipeLogsTo(loggers: Array[Logger]): Unit = {
- TestOutputConsole.synchronized {
- for {
- LogElement(method, message) <- logBuffer
- logger <- loggers
- } method(logger) {
- if (logger.ansiCodesSupported) message
- else removeColors(message)
- }
- }
- }
-
- def allLogs: List[LogElement] = logBuffer.toList
-
- private val colorPattern = raw"\033\[\d{1,2}m"
-
- private def removeColors(message: String): String =
- message.replaceAll(colorPattern, "")
-
- private val unEscPat = Pattern.compile("(\\\\\\\\|\\\\n|\\\\r)")
- private def unescape(message: String): String = {
- val m = unEscPat.matcher(message)
- val res = new StringBuffer()
- while (m.find()) {
- val repl = m.group() match {
- case "\\\\" => "\\\\"
- case "\\n" => "\n"
- case "\\r" => "\r"
- }
- m.appendReplacement(res, repl);
- }
- m.appendTail(res);
- res.toString
- }
-
-}
-
-object TestOutputConsole {
- type LogMethod = Logger => (String => Unit)
- case class LogElement(method: LogMethod, message: String)
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestRunner.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestRunner.scala
deleted file mode 100644
index e5ca2a2..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestRunner.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin.testing
-
-import sbt.testing._
-
-import scala.scalajs.tools.env._
-import scala.scalajs.tools.classpath._
-
-class TestRunner(
- environment: JSEnv,
- classpath: CompleteClasspath,
- jsConsole: JSConsole,
- testFramework: String,
- val args: Array[String],
- val remoteArgs: Array[String]) extends Runner {
-
- def tasks(taskDefs: Array[TaskDef]): Array[Task] = if (_done) {
- throw new IllegalStateException("Done has already been called")
- } else {
- taskDefs.map(TestTask(environment, classpath, jsConsole, testFramework, args))
- }
-
- def done(): String = {
- _done = true
- ""
- }
-
- private var _done = false
-}
diff --git a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestTask.scala b/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestTask.scala
deleted file mode 100644
index b1cabb9..0000000
--- a/examples/scala-js/sbt-plugin/src/main/scala/scala/scalajs/sbtplugin/testing/TestTask.scala
+++ /dev/null
@@ -1,110 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ __ ____ Scala.js sbt plugin **
-** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
-** /____/\___/_/ |_/____/_/ | |__/ /____/ **
-** |/____/ **
-\* */
-
-
-package scala.scalajs.sbtplugin.testing
-
-import sbt.testing._
-
-import scala.scalajs.tools.io._
-import scala.scalajs.tools.classpath._
-import scala.scalajs.tools.env._
-
-import scala.scalajs.sbtplugin.JSUtils._
-
-import scala.annotation.tailrec
-import scala.util.control.NonFatal
-
-class TestTask(
- env: JSEnv,
- classpath: CompleteClasspath,
- jsConsole: JSConsole,
- testFramework: String,
- args: Array[String],
- val taskDef: TaskDef) extends Task {
-
- import TestTask._
-
- val tags = Array.empty[String]
- val options = readArgs(args.toList)
-
- def execute(eventHandler: EventHandler,
- loggers: Array[Logger]): Array[Task] = {
-
- val runnerFile = testRunnerFile(options.frameworkArgs)
- val testConsole = new TestOutputConsole(jsConsole, eventHandler,
- new Events(taskDef), classpath, options.noSourceMap)
- val logger = new SbtTestLoggerAccWrapper(loggers)
-
- // Actually execute test
- env.jsRunner(classpath, runnerFile, logger, testConsole).run()
-
- testConsole.pipeLogsTo(loggers)
-
- Array.empty
- }
-
- private def testRunnerFile(args: List[String]) = {
- val testKey = taskDef.fullyQualifiedName
-
- // Note that taskDef does also have the selector, fingerprint and
- // explicitlySpecified value we could pass to the framework. However, we
- // believe that these are only moderately useful. Therefore, we'll silently
- // ignore them.
-
- val jsArgArray = listToJS(args)
- new MemVirtualJSFile("Generated test launcher file").
- withContent(s"""this${dot2bracket(testFramework)}().safeRunTest(
- | scala.scalajs.testbridge.internal.ConsoleTestOutput(),
- | $jsArgArray,
- | this${dot2bracket(testKey)});""".stripMargin)
- }
-
-
-}
-
-object TestTask {
-
- def apply(environment: JSEnv, classpath: CompleteClasspath,
- jsConsole: JSConsole, testFramework: String, args: Array[String]
- )(taskDef: TaskDef) =
- new TestTask(environment, classpath, jsConsole,
- testFramework, args, taskDef)
-
- case class ArgOptions(
- noSourceMap: Boolean,
- frameworkArgs: List[String]
- )
-
- private def readArgs(args0: List[String]) = {
- // State for each option
- var noSourceMap = false
-
- def mkOptions(frameworkArgs: List[String]) =
- ArgOptions(noSourceMap, frameworkArgs)
-
- @tailrec
- def read0(args: List[String]): ArgOptions = args match {
- case "-no-source-map" :: xs =>
- noSourceMap = true
- read0(xs)
-
- // Explicitly end our argument list
- case "--" :: xs =>
- mkOptions(xs)
-
- // Unknown argument
- case xs =>
- mkOptions(xs)
-
- }
-
- read0(args0)
- }
-
-}