Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support useECMAScript2015 option in ScalaJSModule #1004

Merged
merged 2 commits into from
Nov 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ import mill.modules.Jvm.createAssembly
object Deps {

object Scalajs_0_6 {
val scalajsJsEnvs = ivy"org.scala-js::scalajs-js-envs:0.6.32"
val scalajsSbtTestAdapter = ivy"org.scala-js::scalajs-sbt-test-adapter:0.6.32"
val scalajsTools = ivy"org.scala-js::scalajs-tools:0.6.32"
val scalajsJsEnvs = ivy"org.scala-js::scalajs-js-envs:0.6.33"
val scalajsSbtTestAdapter = ivy"org.scala-js::scalajs-sbt-test-adapter:0.6.33"
val scalajsTools = ivy"org.scala-js::scalajs-tools:0.6.33"
}

object Scalajs_1 {
val scalajsEnvJsdomNodejs = ivy"org.scala-js::scalajs-env-jsdom-nodejs:1.1.0"
val scalajsEnvNodejs = ivy"org.scala-js::scalajs-env-nodejs:1.1.1"
val scalajsEnvPhantomjs = ivy"org.scala-js::scalajs-env-phantomjs:1.0.0"
val scalajsSbtTestAdapter = ivy"org.scala-js::scalajs-sbt-test-adapter:1.1.1"
val scalajsLinker = ivy"org.scala-js::scalajs-linker:1.1.1"
val scalajsSbtTestAdapter = ivy"org.scala-js::scalajs-sbt-test-adapter:1.3.1"
val scalajsLinker = ivy"org.scala-js::scalajs-linker:1.3.1"
}

object Scalanative_0_3 {
Expand Down
4 changes: 3 additions & 1 deletion scalajslib/api/src/ScalaJSWorkerApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ trait ScalaJSWorkerApi {
main: String,
testBridgeInit: Boolean,
fullOpt: Boolean,
moduleKind: ModuleKind): Result[File]
moduleKind: ModuleKind,
useECMAScript2015: Boolean): Result[File]

def run(config: JsEnvConfig, linkedFile: File): Unit

Expand All @@ -29,6 +30,7 @@ sealed trait ModuleKind
object ModuleKind{
object NoModule extends ModuleKind
object CommonJSModule extends ModuleKind
object ESModule extends ModuleKind
}


Expand Down
17 changes: 12 additions & 5 deletions scalajslib/src/ScalaJSModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer =>
finalMainClassOpt().toOption,
testBridgeInit = false,
FastOpt,
moduleKind()
moduleKind(),
useECMAScript2015()
)
}

Expand All @@ -87,7 +88,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer =>
finalMainClassOpt().toOption,
testBridgeInit = false,
FullOpt,
moduleKind()
moduleKind(),
useECMAScript2015()
)
}

Expand Down Expand Up @@ -121,7 +123,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer =>
mainClass: Option[String],
testBridgeInit: Boolean,
mode: OptimizeMode,
moduleKind: ModuleKind)(implicit ctx: Ctx): Result[PathRef] = {
moduleKind: ModuleKind,
useECMAScript2015: Boolean)(implicit ctx: Ctx): Result[PathRef] = {
val outputPath = ctx.dest / "out.js"

os.makeDir.all(ctx.dest)
Expand All @@ -141,7 +144,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer =>
mainClass,
testBridgeInit,
mode == FullOpt,
moduleKind
moduleKind,
useECMAScript2015
).map(PathRef(_))
}

Expand All @@ -167,6 +171,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer =>
def jsEnvConfig: T[JsEnvConfig] = T { JsEnvConfig.NodeJs() }

def moduleKind: T[ModuleKind] = T { ModuleKind.NoModule }

def useECMAScript2015: T[Boolean] = false
}

trait TestScalaJSModule extends ScalaJSModule with TestModule {
Expand All @@ -190,7 +196,8 @@ trait TestScalaJSModule extends ScalaJSModule with TestModule {
None,
testBridgeInit = true,
FastOpt,
moduleKind()
moduleKind(),
useECMAScript2015()
)
}

Expand Down
6 changes: 4 additions & 2 deletions scalajslib/src/ScalaJSWorkerApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ class ScalaJSWorker {
main: Option[String],
testBridgeInit: Boolean,
fullOpt: Boolean,
moduleKind: ModuleKind)
moduleKind: ModuleKind,
useECMAScript2015: Boolean)
(implicit ctx: Ctx.Home): Result[os.Path] = {
bridge(toolsClasspath).link(
sources.items.map(_.toIO).toArray,
Expand All @@ -46,7 +47,8 @@ class ScalaJSWorker {
main.orNull,
testBridgeInit,
fullOpt,
moduleKind
moduleKind,
useECMAScript2015
).map(os.Path(_))
}

Expand Down
69 changes: 36 additions & 33 deletions scalajslib/test/src/HelloJSWorldTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,18 @@ object HelloJSWorldTests extends TestSuite {
}

object HelloJSWorld extends TestUtil.BaseModule {
val scalaVersions = Seq("2.13.2", "2.12.11", "2.11.12")
val scalaJSVersions = Seq("1.1.1", "1.0.1", "0.6.33")
val scalaVersions = Seq("2.13.3", "2.12.12", "2.11.12")
val scalaJSVersionsAndUseECMA2015 = Seq(("1.3.1", false), ("1.3.1", true), ("1.0.1", false), ("0.6.33", false))
val matrix = for {
scala <- scalaVersions
scalaJS <- scalaJSVersions
} yield (scala, scalaJS)
(scalaJS, useECMAScript2015) <- scalaJSVersionsAndUseECMA2015
} yield (scala, scalaJS, useECMAScript2015)

object helloJsWorld extends Cross[BuildModule](matrix:_*)
class BuildModule(val crossScalaVersion: String, sjsVersion0: String) extends HelloJSWorldModule {
class BuildModule(val crossScalaVersion: String, sjsVersion0: String, sjsUseECMA2015: Boolean) extends HelloJSWorldModule {
override def artifactName = "hello-js-world"
def scalaJSVersion = sjsVersion0
def useECMAScript2015 = sjsUseECMA2015
def pomSettings = PomSettings(
organization = "com.lihaoyi",
description = "hello js world ready for real world publishing",
Expand All @@ -47,7 +48,7 @@ object HelloJSWorldTests extends TestSuite {

object buildUTest extends Cross[BuildModuleUtest](matrix:_*)
class BuildModuleUtest(crossScalaVersion: String, sjsVersion0: String)
extends BuildModule(crossScalaVersion, sjsVersion0) {
extends BuildModule(crossScalaVersion, sjsVersion0, sjsUseECMA2015 = false) {
object test extends super.Tests {
override def sources = T.sources{ millSourcePath / 'src / 'utest }
def testFrameworks = Seq("utest.runner.Framework")
Expand All @@ -59,7 +60,7 @@ object HelloJSWorldTests extends TestSuite {

object buildScalaTest extends Cross[BuildModuleScalaTest](matrix:_*)
class BuildModuleScalaTest(crossScalaVersion: String, sjsVersion0: String)
extends BuildModule(crossScalaVersion, sjsVersion0) {
extends BuildModule(crossScalaVersion, sjsVersion0, sjsUseECMA2015 = false) {
object test extends super.Tests {
override def sources = T.sources{ millSourcePath / 'src / 'scalatest }
def testFrameworks = Seq("org.scalatest.tools.Framework")
Expand All @@ -81,10 +82,9 @@ object HelloJSWorldTests extends TestSuite {
def tests: Tests = Tests {
prepareWorkspace()
'compile - {
def testCompileFromScratch(scalaVersion: String,
scalaJSVersion: String): Unit = {
def testCompileFromScratch(scalaVersion: String, scalaJSVersion: String, useECMAScript2015: Boolean): Unit = {
val Right((result, evalCount)) =
helloWorldEvaluator(HelloJSWorld.helloJsWorld(scalaVersion, scalaJSVersion).compile)
helloWorldEvaluator(HelloJSWorld.helloJsWorld(scalaVersion, scalaJSVersion, useECMAScript2015).compile)

val outPath = result.classes.path
val outputFiles = os.walk(outPath)
Expand All @@ -96,40 +96,41 @@ object HelloJSWorldTests extends TestSuite {

// don't recompile if nothing changed
val Right((_, unchangedEvalCount)) =
helloWorldEvaluator(HelloJSWorld.helloJsWorld(scalaVersion, scalaJSVersion).compile)
helloWorldEvaluator(HelloJSWorld.helloJsWorld(scalaVersion, scalaJSVersion, useECMAScript2015).compile)
assert(unchangedEvalCount == 0)
}

testAllMatrix((scala, scalaJS) => testCompileFromScratch(scala, scalaJS))
testAllMatrix((scala, scalaJS, useECMAScript2015) => testCompileFromScratch(scala, scalaJS, useECMAScript2015), skipECMAScript2015 = false)
}

def testRun(scalaVersion: String,
scalaJSVersion: String,
useECMAScript2015: Boolean,
mode: OptimizeMode): Unit = {
val task = mode match {
case FullOpt => HelloJSWorld.helloJsWorld(scalaVersion, scalaJSVersion).fullOpt
case FastOpt => HelloJSWorld.helloJsWorld(scalaVersion, scalaJSVersion).fastOpt
case FullOpt => HelloJSWorld.helloJsWorld(scalaVersion, scalaJSVersion, useECMAScript2015).fullOpt
case FastOpt => HelloJSWorld.helloJsWorld(scalaVersion, scalaJSVersion, useECMAScript2015).fastOpt
}
val Right((result, evalCount)) = helloWorldEvaluator(task)
val jsFile = result.path
val output = ScalaJsUtils.runJS(jsFile)
assert(output == "Hello Scala.js")
assert(output == "Hello Scala.js\n")
val sourceMap= jsFile / os.up / (jsFile.last + ".map")
assert(sourceMap.toIO.exists()) // sourceMap file was generated
assert(os.read(jsFile).contains(s"//# sourceMappingURL=${sourceMap.toNIO.getFileName}")) // jsFile references sourceMap
assert(ujson.read(sourceMap.toIO).obj.get("file").exists(_.str == jsFile.toNIO.getFileName.toString)) // sourceMap references jsFile
}

'fullOpt - {
testAllMatrix((scala, scalaJS) => TestUtil.disableInJava9OrAbove(testRun(scala, scalaJS, FullOpt)))
testAllMatrix((scala, scalaJS, _) => TestUtil.disableInJava9OrAbove(testRun(scala, scalaJS, false, FullOpt)))
}
'fastOpt - {
testAllMatrix((scala, scalaJS) => TestUtil.disableInJava9OrAbove(testRun(scala, scalaJS, FastOpt)))
testAllMatrix((scala, scalaJS, useECMAScript2015) => TestUtil.disableInJava9OrAbove(testRun(scala, scalaJS, useECMAScript2015, FastOpt)), skipECMAScript2015 = false)
}
'jar - {
'containsSJSIRs - {
val (scala, scalaJS) = HelloJSWorld.matrix.head
val Right((result, evalCount)) = helloWorldEvaluator(HelloJSWorld.helloJsWorld(scala, scalaJS).jar)
val (scala, scalaJS, useECMAScript2015) = HelloJSWorld.matrix.head
val Right((result, evalCount)) = helloWorldEvaluator(HelloJSWorld.helloJsWorld(scala, scalaJS, useECMAScript2015).jar)
val jar = result.path
val entries = new JarFile(jar.toIO).entries().asScala.map(_.getName)
assert(entries.contains("Main$.sjsir"))
Expand All @@ -139,12 +140,12 @@ object HelloJSWorldTests extends TestSuite {
def testArtifactId(scalaVersion: String,
scalaJSVersion: String,
artifactId: String): Unit = {
val Right((result, evalCount)) = helloWorldEvaluator(HelloJSWorld.helloJsWorld(scalaVersion, scalaJSVersion).artifactMetadata)
val Right((result, evalCount)) = helloWorldEvaluator(HelloJSWorld.helloJsWorld(scalaVersion, scalaJSVersion, false).artifactMetadata)
assert(result.id == artifactId)
}
'artifactId_06 - testArtifactId(HelloJSWorld.scalaVersions.head, "0.6.33", "hello-js-world_sjs0.6_2.13")
'artifactId_10 - testArtifactId(HelloJSWorld.scalaVersions.head, "1.0.1", "hello-js-world_sjs1_2.13")
'artifactId_1 - testArtifactId(HelloJSWorld.scalaVersions.head, "1.1.1", "hello-js-world_sjs1_2.13")
'artifactId_1 - testArtifactId(HelloJSWorld.scalaVersions.head, "1.3.1", "hello-js-world_sjs1_2.13")
}

def runTests(testTask: define.NamedTask[(String, Seq[TestRunner.Result])]): Map[String, Map[String, TestRunner.Result]] = {
Expand Down Expand Up @@ -199,18 +200,18 @@ object HelloJSWorldTests extends TestSuite {

'test - {
val cached = false
testAllMatrix((scala, scalaJS) => checkUtest(scala, scalaJS, cached), skipScala = _.startsWith("2.11."))
testAllMatrix((scala, scalaJS) => checkScalaTest(scala, scalaJS, cached))
testAllMatrix((scala, scalaJS, _) => checkUtest(scala, scalaJS, cached), skipScala = _.startsWith("2.11."))
testAllMatrix((scala, scalaJS, _) => checkScalaTest(scala, scalaJS, cached))
}

'testCached - {
val cached = false
testAllMatrix((scala, scalaJS) => checkUtest(scala, scalaJS, cached), skipScala = _.startsWith("2.11."))
testAllMatrix((scala, scalaJS) => checkScalaTest(scala, scalaJS, cached))
testAllMatrix((scala, scalaJS, _) => checkUtest(scala, scalaJS, cached), skipScala = _.startsWith("2.11."))
testAllMatrix((scala, scalaJS, _) => checkScalaTest(scala, scalaJS, cached))
}

def checkRun(scalaVersion: String, scalaJSVersion: String): Unit = {
val task = HelloJSWorld.helloJsWorld(scalaVersion, scalaJSVersion).run()
def checkRun(scalaVersion: String, scalaJSVersion: String, useECMAScript2015: Boolean): Unit = {
val task = HelloJSWorld.helloJsWorld(scalaVersion, scalaJSVersion, useECMAScript2015).run()

val Right((_, evalCount)) = helloWorldEvaluator(task)

Expand All @@ -228,7 +229,7 @@ object HelloJSWorldTests extends TestSuite {
}

'run - {
testAllMatrix((scala, scalaJS) => checkRun(scala, scalaJS))
testAllMatrix((scala, scalaJS, useECMAScript2015) => checkRun(scala, scalaJS, useECMAScript2015), skipECMAScript2015 = false)
}
}

Expand Down Expand Up @@ -260,18 +261,20 @@ object HelloJSWorldTests extends TestSuite {
os.copy(millSourcePath, workspacePath)
}

def testAllMatrix(f: (String, String) => Unit,
def testAllMatrix(f: (String, String, Boolean) => Unit,
skipScala: String => Boolean = _ => false,
skipScalaJS: String => Boolean = _ => false): Unit = {
skipScalaJS: String => Boolean = _ => false,
skipECMAScript2015: Boolean = true): Unit = {
for {
(scala, scalaJS) <- HelloJSWorld.matrix
(scala, scalaJS, useECMAScript2015) <- HelloJSWorld.matrix
if !skipScala(scala)
if !skipScalaJS(scalaJS)
if !skipECMAScript2015 && useECMAScript2015
} {
if(scala.startsWith("2.11.")) {
TestUtil.disableInJava9OrAbove(f(scala,scalaJS))
TestUtil.disableInJava9OrAbove(f(scala,scalaJS, useECMAScript2015))
} else {
f(scala,scalaJS)
f(scala,scalaJS, useECMAScript2015)
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions scalajslib/test/src/MultiModuleTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ object MultiModuleTests extends TestSuite {

object MultiModule extends TestUtil.BaseModule {
trait BaseModule extends ScalaJSModule {
def scalaVersion = "2.12.4"
def scalaJSVersion = "0.6.32"
def scalaVersion = "2.13.3"
def scalaJSVersion = "0.6.33"
}

object client extends BaseModule {
Expand All @@ -23,7 +23,7 @@ object MultiModuleTests extends TestSuite {
override def mainClass = Some("Main")
object test extends Tests {
def testFrameworks = Seq("utest.runner.Framework")
override def ivyDeps = Agg(ivy"com.lihaoyi::utest::0.6.3")
override def ivyDeps = Agg(ivy"com.lihaoyi::utest::0.7.5")
}
}

Expand All @@ -49,7 +49,7 @@ object MultiModuleTests extends TestSuite {
val runOutput = ScalaJsUtils.runJS(linked.path)
assert(
evalCount > 0,
runOutput == "Hello from Scala.js, result is: 3"
runOutput == "Hello from Scala.js, result is: 3\n"
)
}

Expand Down
20 changes: 1 addition & 19 deletions scalajslib/test/src/ScalaJsUtils.scala
Original file line number Diff line number Diff line change
@@ -1,25 +1,7 @@
package mill.scalajslib

import java.io.{FileReader, StringWriter}
import javax.script.{ScriptContext, ScriptEngineManager}

object ScalaJsUtils {
/* TODO Using Nashorn means that we do not support ECMAScript 2015, which
* forces ScalaJSWorkerImpl to always use ES 5.1. We should a different
* engine, perhaps Scala.js' own JSEnv, to perform these tests.
*/
def runJS(path: os.Path): String = {
val engineManager = new ScriptEngineManager(null)
val engine = engineManager.getEngineByName("nashorn")
val console = new Console
val bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE)
bindings.put("console", console)
engine.eval(new FileReader(path.toIO))
console.out.toString
os.proc("node", path).call().out.text
}
}

class Console {
val out = new StringWriter()
def log(s: String): Unit = out.append(s)
}
8 changes: 6 additions & 2 deletions scalajslib/worker/0.6/src/ScalaJSWorkerImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ import org.scalajs.jsenv._
import org.scalajs.testadapter.TestAdapter

class ScalaJSWorkerImpl extends mill.scalajslib.api.ScalaJSWorkerApi {

def link(sources: Array[File],
libraries: Array[File],
dest: File,
main: String,
testBridgeInit: Boolean, // ignored in 0.6
fullOpt: Boolean,
moduleKind: ModuleKind) = {
moduleKind: ModuleKind,
useECMAScript2015: Boolean) = {

val semantics = fullOpt match {
case true => Semantics.Defaults.optimized
Expand All @@ -31,12 +32,14 @@ class ScalaJSWorkerImpl extends mill.scalajslib.api.ScalaJSWorkerApi {
val scalaJSModuleKind = moduleKind match {
case ModuleKind.NoModule => ScalaJSModuleKind.NoModule
case ModuleKind.CommonJSModule => ScalaJSModuleKind.CommonJSModule
case ModuleKind.ESModule => ScalaJSModuleKind.ESModule
}
val config = StandardLinker.Config()
.withOptimizer(fullOpt)
.withClosureCompilerIfAvailable(fullOpt)
.withSemantics(semantics)
.withModuleKind(scalaJSModuleKind)
.withESFeatures(_.withUseECMAScript2015(useECMAScript2015))
val linker = StandardLinker(config)
val sourceSJSIRs = sources.map(new FileVirtualScalaJSIRFile(_))
val jars = libraries.map(jar => IRContainer.Jar(new FileVirtualBinaryFile(jar) with VirtualJarFile))
Expand Down Expand Up @@ -71,6 +74,7 @@ class ScalaJSWorkerImpl extends mill.scalajslib.api.ScalaJSWorkerApi {
val tconfig = moduleKind match {
case ModuleKind.NoModule => TestAdapter.Config().withLogger(new ScalaConsoleLogger)
case ModuleKind.CommonJSModule => TestAdapter.Config().withLogger(new ScalaConsoleLogger).withModuleSettings(ScalaJSModuleKind.CommonJSModule, moduleIdentifier)
case ModuleKind.ESModule => TestAdapter.Config().withLogger(new ScalaConsoleLogger).withModuleSettings(ScalaJSModuleKind.ESModule, moduleIdentifier)
}

val adapter =
Expand Down
Loading