summaryrefslogtreecommitdiff
path: root/scalajslib/src/ScalaJSModule.scala
diff options
context:
space:
mode:
Diffstat (limited to 'scalajslib/src/ScalaJSModule.scala')
-rw-r--r--scalajslib/src/ScalaJSModule.scala201
1 files changed, 201 insertions, 0 deletions
diff --git a/scalajslib/src/ScalaJSModule.scala b/scalajslib/src/ScalaJSModule.scala
new file mode 100644
index 00000000..137e8ee2
--- /dev/null
+++ b/scalajslib/src/ScalaJSModule.scala
@@ -0,0 +1,201 @@
+package mill
+package scalajslib
+
+import coursier.Cache
+import coursier.maven.MavenRepository
+import mill.eval.{PathRef, Result}
+import mill.api.Result.Success
+import mill.scalalib.Lib.resolveDependencies
+import mill.scalalib.{DepSyntax, Lib, TestModule, TestRunner}
+import mill.util.Ctx
+import mill.api.Loose
+import mill.scalajslib.api._
+trait ScalaJSModule extends scalalib.ScalaModule { outer =>
+
+ def scalaJSVersion: T[String]
+
+ trait Tests extends TestScalaJSModule {
+ override def zincWorker = outer.zincWorker
+ override def scalaOrganization = outer.scalaOrganization()
+ override def scalaVersion = outer.scalaVersion()
+ override def scalaJSVersion = outer.scalaJSVersion()
+ override def moduleDeps = Seq(outer)
+ }
+
+ def scalaJSBinaryVersion = T { mill.scalalib.api.Util.scalaBinaryVersion(scalaJSVersion()) }
+
+ def scalaJSWorkerVersion = T{ scalaJSVersion().split('.').dropRight(1).mkString(".") }
+
+ def scalaJSWorkerClasspath = T {
+ val workerKey = "MILL_SCALAJS_WORKER_" + scalaJSWorkerVersion().replace('.', '_')
+ mill.modules.Util.millProjectModule(
+ workerKey,
+ s"mill-scalajslib-worker-${scalaJSWorkerVersion()}",
+ repositories,
+ resolveFilter = _.toString.contains("mill-scalajslib-worker")
+ )
+ }
+
+ def scalaJSLinkerClasspath: T[Loose.Agg[PathRef]] = T{
+ val commonDeps = Seq(
+ ivy"org.scala-js::scalajs-tools:${scalaJSVersion()}",
+ ivy"org.scala-js::scalajs-sbt-test-adapter:${scalaJSVersion()}"
+ )
+ val envDep = scalaJSBinaryVersion() match {
+ case v if v.startsWith("0.6") => ivy"org.scala-js::scalajs-js-envs:${scalaJSVersion()}"
+ case v if v.startsWith("1.0") => ivy"org.scala-js::scalajs-env-nodejs:${scalaJSVersion()}"
+ }
+ resolveDependencies(
+ repositories,
+ Lib.depToDependency(_, "2.12.4", ""),
+ commonDeps :+ envDep
+ )
+ }
+
+ def toolsClasspath = T { scalaJSWorkerClasspath() ++ scalaJSLinkerClasspath() }
+
+ def fastOpt = T {
+ link(
+ ScalaJSWorkerApi.scalaJSWorker(),
+ toolsClasspath(),
+ runClasspath(),
+ finalMainClassOpt().toOption,
+ FastOpt,
+ moduleKind()
+ )
+ }
+
+ def fullOpt = T {
+ link(
+ ScalaJSWorkerApi.scalaJSWorker(),
+ toolsClasspath(),
+ runClasspath(),
+ finalMainClassOpt().toOption,
+ FullOpt,
+ moduleKind()
+ )
+ }
+
+ override def runLocal(args: String*) = T.command { run(args:_*) }
+
+ override def run(args: String*) = T.command {
+ finalMainClassOpt() match{
+ case Left(err) => Result.Failure(err)
+ case Right(_) =>
+ ScalaJSWorkerApi.scalaJSWorker().run(
+ toolsClasspath().map(_.path),
+ nodeJSConfig(),
+ fastOpt().path.toIO
+ )
+ Result.Success(())
+ }
+
+ }
+
+ override def runMainLocal(mainClass: String, args: String*) = T.command[Unit] {
+ mill.api.Result.Failure("runMain is not supported in Scala.js")
+ }
+
+ override def runMain(mainClass: String, args: String*) = T.command[Unit] {
+ mill.api.Result.Failure("runMain is not supported in Scala.js")
+ }
+
+ def link(worker: ScalaJSWorker,
+ toolsClasspath: Agg[PathRef],
+ runClasspath: Agg[PathRef],
+ mainClass: Option[String],
+ mode: OptimizeMode,
+ moduleKind: ModuleKind)(implicit ctx: Ctx): Result[PathRef] = {
+ val outputPath = ctx.dest / "out.js"
+
+ os.makeDir.all(ctx.dest)
+ os.remove.all(outputPath)
+
+ val classpath = runClasspath.map(_.path)
+ val sjsirFiles = classpath
+ .filter(path => os.exists(path) && os.isDir(path))
+ .flatMap(os.walk(_))
+ .filter(_.ext == "sjsir")
+ val libraries = classpath.filter(_.ext == "jar")
+ worker.link(
+ toolsClasspath.map(_.path),
+ sjsirFiles,
+ libraries,
+ outputPath.toIO,
+ mainClass,
+ mode == FullOpt,
+ moduleKind
+ ).map(PathRef(_))
+ }
+
+ override def scalacPluginIvyDeps = T{
+ super.scalacPluginIvyDeps() ++
+ Seq(ivy"org.scala-js:::scalajs-compiler:${scalaJSVersion()}")
+ }
+ override def scalaLibraryIvyDeps = T{
+ Seq(ivy"org.scala-js::scalajs-library:${scalaJSVersion()}")
+ }
+
+ // publish artifact with name "mill_sjs0.6.4_2.12" instead of "mill_sjs0.6_2.12"
+ def crossFullScalaJSVersion: T[Boolean] = false
+ def artifactScalaJSVersion: T[String] = T {
+ if (crossFullScalaJSVersion()) scalaJSVersion()
+ else scalaJSBinaryVersion()
+ }
+
+ override def artifactSuffix: T[String] = s"${platformSuffix()}_${artifactScalaVersion()}"
+
+ override def platformSuffix = s"_sjs${artifactScalaJSVersion()}"
+
+ def nodeJSConfig = T { NodeJSConfig() }
+
+ def moduleKind: T[ModuleKind] = T { ModuleKind.NoModule }
+}
+
+trait TestScalaJSModule extends ScalaJSModule with TestModule {
+ def scalaJSTestDeps = T {
+ resolveDeps(T.task {
+ Loose.Agg(
+ ivy"org.scala-js::scalajs-library:${scalaJSVersion()}",
+ ivy"org.scala-js::scalajs-test-interface:${scalaJSVersion()}"
+ )
+ })
+ }
+
+ def fastOptTest = T {
+ link(
+ ScalaJSWorkerApi.scalaJSWorker(),
+ toolsClasspath(),
+ scalaJSTestDeps() ++ runClasspath(),
+ None,
+ FastOpt,
+ moduleKind()
+ )
+ }
+
+ override def testLocal(args: String*) = T.command { test(args:_*) }
+
+ override def test(args: String*) = T.command {
+ val (close, framework) = mill.scalajslib.ScalaJSWorkerApi.scalaJSWorker().getFramework(
+ toolsClasspath().map(_.path),
+ nodeJSConfig(),
+ testFrameworks().head,
+ fastOptTest().path.toIO
+ )
+
+ val (doneMsg, results) = TestRunner.runTests(
+ _ => Seq(framework),
+ runClasspath().map(_.path),
+ Agg(compile().classes.path),
+ args
+ )
+ val res = TestModule.handleResults(doneMsg, results)
+ // Hack to try and let the Node.js subprocess finish streaming it's stdout
+ // to the JVM. Without this, the stdout can still be streaming when `close()`
+ // is called, and some of the output is dropped onto the floor.
+ Thread.sleep(100)
+ close()
+ res
+ }
+
+}