scala-js
b31a3034697f
Merge pull request #2893 from sjrd/no-jsenv-load-libs
S├ębastien Doeraene
15 days ago
Fix #2875: Remove JSEnv.loadLibs, resolvedJSEnv and loadedJSEnv.

231 232 233 234 235 236 237 238 239 240 231 232 233 234 235 236 237 238 239 240 241
cd sbt-plugin-test && sbt noDOM/run noDOM/testHtmlFastOpt noDOM/testHtmlFullOpt \ withDOM/run withDOM/testHtmlFastOpt withDOM/testHtmlFullOpt \ multiTestJS/testHtmlFastOpt multiTestJS/testHtmlFullOpt \ jetty9/run test \
noDOM/clean noDOM/concurrentUseOfLinkerTest \
jsDependenciesTest/packageJSDependencies \ jsDependenciesTest/packageMinifiedJSDependencies \ jsDependenciesTest/regressionTestForIssue2243 \ jsNoDependenciesTest/regressionTestForIssue2243 \ multiTestJS/test:testScalaJSSourceMapAttribute

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 11 12 13 14 15 16
import org.scalajs.core.tools.io.VirtualJSFile trait AsyncJSEnv extends JSEnv { def asyncRunner(files: Seq[VirtualJSFile]): AsyncJSRunner
override def loadLibs(libs: Seq[VirtualJSFile]): AsyncJSEnv = new AsyncLoadedLibs { val loadedLibs = libs } private[jsenv] trait AsyncLoadedLibs extends LoadedLibs with AsyncJSEnv { def asyncRunner(files: Seq[VirtualJSFile]): AsyncJSRunner = { AsyncJSEnv.this.asyncRunner(loadedLibs ++ files) } }
}

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 26 27 28 29 30 31 32 33 34 35
* scalajsCom.close(); * }}} */ trait ComJSEnv extends AsyncJSEnv { def comRunner(files: Seq[VirtualJSFile]): ComJSRunner
override def loadLibs(libs: Seq[VirtualJSFile]): ComJSEnv = new ComLoadedLibs { val loadedLibs = libs } private[jsenv] trait ComLoadedLibs extends AsyncLoadedLibs with ComJSEnv { def comRunner(files: Seq[VirtualJSFile]): ComJSRunner = { ComJSEnv.this.comRunner(loadedLibs ++ files) } }
} object ComJSEnv { private final val defaultMsg = "JSCom has been closed"

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 15 16 17 18 19 20
/** Human-readable name for this [[JSEnv]] */ def name: String /** Prepare a runner with the specified JavaScript files. */ def jsRunner(files: Seq[VirtualJSFile]): JSRunner
/** Return this [[JSEnv]] with the given libraries already loaded. * * The following two are equivalent: * {{{ * jsEnv.loadLibs(a).jsRunner(b) * jsEnv.jsRunner(a ++ b) * }}} */ def loadLibs(libs: Seq[VirtualJSFile]): JSEnv = new LoadedLibs { val loadedLibs = libs } private[jsenv] trait LoadedLibs extends JSEnv { val loadedLibs: Seq[VirtualJSFile] def name: String = JSEnv.this.name def jsRunner(files: Seq[VirtualJSFile]): JSRunner = JSEnv.this.jsRunner(loadedLibs ++ files) }
}

634 635 636 637 638 639 640 641 642 643 644 634 635 636 637 638 639 640 641 642 643 644
"org.webjars" % "jszip" % "2.4.0" % "test" / "jszip.min.js" commonJSName "JSZip", inConfig(Test) { // Redefine test to run Node.js and link HelloWorld test := {
if (!resolvedJSEnv.value.isInstanceOf[NodeJSEnv])
if (!jsEnv.value.isInstanceOf[NodeJSEnv])
sys.error("toolsJS/test must be run with Node.js") /* Collect IR relevant files from the classpath * We assume here that the classpath is valid. This is checked by the * the scalaJSIR task.
...
694 695 696 697 698 699 700 701 702 703 704 694 695 696 697 698 699 700 701 702 703 704
} val launcher = new MemVirtualJSFile("Generated launcher file") .withContent(code)
val runner = loadedJSEnv.value.jsRunner(launcher :: Nil)
val runner = jsEnv.value.jsRunner(jsExecutionFiles.value :+ launcher)
runner.run(sbtLogger2ToolsLogger(streams.value.log), scalaJSConsole.value) } } ).withScalaJSCompiler.dependsOn(
...
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285
throw new AssertionError( s"Unknown JSEnv of class ${env.getClass.getName}: " + "don't know what tags to specify for the test suite") }
val envTags = envTagsFor((resolvedJSEnv in Test).value)
val envTags = envTagsFor((jsEnv in Test).value)
val stage = (scalaJSStage in Test).value val sems = stage match { case FastOptStage => (scalaJSSemantics in (Test, fastOptJS)).value

1 2 3 4 5 6 7 1 2 3 4 5 6 7 8 9 10 11 12 13
import org.scalajs.core.tools.io._
import org.scalajs.core.tools.jsdep.ManifestFilters import org.scalajs.jsenv.nodejs.JSDOMNodeJSEnv
import org.scalajs.sbtplugin.ScalaJSPluginInternal._ import org.scalajs.sbtplugin.Loggers.sbtLogger2ToolsLogger lazy val concurrentFakeFullOptJS = taskKey[Any]("") lazy val concurrentUseOfLinkerTest = taskKey[Any]("")
name := "Scala.js sbt test" version := scalaJSVersion
...
54 55 56 57 58 59 60 61 62 63 64 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
scalaJSUseMainModuleInitializer := true ). /* This hopefully exposes concurrent uses of the linker. If it fails/gets * flaky, there is a bug somewhere - #2202 */
settings(inConfig(Compile)(run <<= run.dependsOn(fastOptJS, loadedJSEnv)): _*)
settings(inConfig(Compile)(Seq( // A fake fullOptJS that we will run concurrently with the true fullOptJS concurrentFakeFullOptJS := Def.taskDyn { val s = (streams in fullOptJS).value val log = s.log val ir = (scalaJSIR in fullOptJS).value.data val moduleInitializers = scalaJSModuleInitializers.value Def.task { log.info("Fake full optimizing") val linker = (scalaJSLinker in fullOptJS).value linker.link(ir, moduleInitializers, WritableMemVirtualJSFile("fake-fastopt.js"), sbtLogger2ToolsLogger(log)) }.tag((usesScalaJSLinkerTag in fullOptJS).value) }.value, /* Depend on both fullOptJS and concurrentFakeFullOptJS, so that they * are hopefully executed in parallel (potentially, but they should be * blocked from actually doing so by the concurrent restrictions on * usesScalaJSLinkerTag). */ concurrentUseOfLinkerTest := { (fullOptJS.value, concurrentFakeFullOptJS.value) } )))
lazy val withDOM = project.settings(baseSettings: _*). enablePlugins(ScalaJSPlugin). enablePlugins(ScalaJSJUnitPlugin). settings(

19 20 21 22 23 24 25 26 27 28 29 19 20 21 22 23 24 25 26 27 28 29 30
object Jetty9Test { private val jettyPort = 23548 val runSetting = run <<= Def.inputTask {
val jsEnv = (loadedJSEnv in Compile).value.asInstanceOf[ComJSEnv]
val env = (jsEnv in Compile).value.asInstanceOf[ComJSEnv] val files = (jsExecutionFiles in Compile).value
val jsConsole = scalaJSConsole.value val code = new MemVirtualJSFile("runner.js").withContent( """ scalajsCom.init(function(msg) {
...
40 41 42 43 44 45 46 47 48 49 50 41 42 43 44 45 46 47 48 49 50 51
xhr.send(); }); """ )
val runner = jsEnv.comRunner(code :: Nil)
val runner = env.comRunner(files :+ code)
runner.start(streams.value.log, jsConsole) val jetty = setupJetty((resourceDirectory in Compile).value)

10 11 12 13 14 15 16 17 18 19 20 10 11 12 13 14 15 16 17 18 19 20 21
import org.scalajs.jsenv._ import scala.collection.mutable private[sbtplugin] final class FrameworkDetector(jsEnv: JSEnv,
moduleKind: ModuleKind, moduleIdentifier: Option[String]) {
jsFiles: Seq[VirtualJSFile], moduleKind: ModuleKind, moduleIdentifier: Option[String]) {
import FrameworkDetector._ /** * Detects which of the test frameworks in `frameworks` exists on
...
65 66 67 68 69 70 71 72 73 74 75 66 67 68 69 70 71 72 73 74 75 76
""" val vf = new MemVirtualJSFile("frameworkDetector.js").withContent(code) val console = new StoreConsole
val runner = jsEnv.jsRunner(vf :: Nil)
val runner = jsEnv.jsRunner(jsFiles :+ vf)
runner.run(logger, console) // Filter jsDependencies unexpected output val results = console.buf collect { case s if s.startsWith(ConsoleFrameworkPrefix) =>

178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 178 179 180 181 182 183 184 185 186 187 188 189
val scalaJSConsole = TaskKey[JSConsole]("scalaJSConsole", "The JS console used by the Scala.js runner/tester", DTask) val jsEnv = TaskKey[JSEnv]("jsEnv",
"A JVM-like environment where Scala.js files can be run and tested.", AMinusTask) val resolvedJSEnv = TaskKey[JSEnv]("resolvedJSEnv", "The JSEnv used for execution. This equals the setting of jsEnv or a " + "reasonable default value if jsEnv is not set.", DTask) @deprecated("Use jsEnv instead.", "0.6.6") val preLinkJSEnv = jsEnv @deprecated("Use jsEnv instead.", "0.6.6") val postLinkJSEnv = jsEnv
"The JavaScript environment in which to run and test Scala.js applications.", AMinusTask)
val requiresDOM = SettingKey[Boolean]("requiresDOM", "Whether this projects needs the DOM. Overrides anything inherited through dependencies.", AMinusSetting) val relativeSourceMaps = SettingKey[Boolean]("relativeSourceMaps",
...
240 241 242 243 244 245 246 247 248 249 250 251 252 231 232 233 234 235 236 237 238 239 240
"Whether to check that the current semantics meet compliance " + "requirements of dependencies.", CSetting) val scalaJSOptimizerOptions = SettingKey[OptimizerOptions]("scalaJSOptimizerOptions", "All kinds of options for the Scala.js optimizer stages", DSetting)
val loadedJSEnv = TaskKey[JSEnv]("loadedJSEnv", "A JSEnv already loaded up with library and Scala.js code. Ready to run.", DTask)
/** Prints the content of a .sjsir file in human readable form. */ val scalajsp = InputKey[Unit]("scalajsp", "Prints the content of a .sjsir file in human readable form.", CTask)

542 543 544 545 546 547 548 549 550 551 552 542 543 544 545 546 547 548 549 550 551 552
/* Implement the behavior of commonJSName without having to burn it * inside NodeJSEnv, and hence in the JSEnv API. * Since this matches against NodeJSEnv specifically, it obviously * breaks the OO approach, but oh well ... */
resolvedJSEnv.value match {
jsEnv.value match {
case _: org.scalajs.jsenv.nodejs.NodeJSEnv => val libCache = new VirtualFileMaterializer(false) for (dep <- deps) yield { dep.info.commonJSName.fold {
...
575 576 577 578 579 580 581 582 583 584 585 586 575 576 577 578 579 580 581 582 583 584
scalaJSRequestsDOM := { requiresDOM.?.value.getOrElse( jsDependencyManifests.value.data.exists(_.requiresDOM)) },
resolvedJSEnv := jsEnv.?.value.getOrElse(new NodeJSEnv()),
scalaJSJavaSystemProperties ++= { val javaSysPropsPattern = "-D([^=]*)=(.*)".r javaOptions.value.map { case javaSysPropsPattern(propName, propValue) => (propName, propValue) case opt =>
...
607 608 609 610 611 612 613 614 615 616 617 618 605 606 607 608 609 610 611 612 613 614
} }, // Crucially, add the Scala.js linked file to the JS files jsExecutionFiles += scalaJSLinkedFile.value,
loadedJSEnv := resolvedJSEnv.value.loadLibs(jsExecutionFiles.value),
scalaJSModuleIdentifier := Def.taskDyn[Option[String]] { scalaJSModuleKind.value match { case ModuleKind.NoModule => Def.task {
...
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
throw new MessageOnlyException("`run` is only supported with " + "scalaJSUseMainModuleInitializer := true") } val log = streams.value.log
val jsEnv = loadedJSEnv.value
val env = jsEnv.value val files = jsExecutionFiles.value
log.info("Running " + mainClass.value.getOrElse("<unknown class>"))
log.debug(s"with JSEnv ${jsEnv.name}")
log.debug(s"with JSEnv ${env.name}")
jsEnv.jsRunner(Nil).run(
env.jsRunner(files).run(
sbtLogger2ToolsLogger(log), scalaJSConsole.value) }, runMain := { throw new MessageOnlyException("`runMain` is not supported in Scala.js")
...
726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757
val console = scalaJSConsole.value val logger = streams.value.log val toolsLogger = sbtLogger2ToolsLogger(logger) val frameworks = testFrameworks.value
val jsEnv = loadedJSEnv.value match { case jsEnv: ComJSEnv => jsEnv
val env = jsEnv.value match { case env: ComJSEnv => env
case jsEnv => sys.error(s"You need a ComJSEnv to test (found ${jsEnv.name})")
case env => sys.error(s"You need a ComJSEnv to test (found ${env.name})")
}
val files = jsExecutionFiles.value
val moduleKind = scalaJSModuleKind.value val moduleIdentifier = scalaJSModuleIdentifier.value val detector =
new FrameworkDetector(jsEnv, moduleKind, moduleIdentifier)
new FrameworkDetector(env, files, moduleKind, moduleIdentifier)
detector.detect(frameworks, toolsLogger) map { case (tf, name) =>
(tf, new ScalaJSFramework(name, jsEnv, moduleKind, moduleIdentifier, toolsLogger, console))
(tf, new ScalaJSFramework(name, env, files, moduleKind, moduleIdentifier, toolsLogger, console))
} }, // Override default to avoid triggering a test:fastOptJS in a test:compile // without loosing autocompletion. definedTestNames := { definedTests.map(_.map(_.name).distinct)
.storeAs(definedTestNames).triggeredBy(loadedJSEnv).value
.storeAs(definedTestNames).triggeredBy(loadedTestFrameworks).value
} ) val scalaJSTestBuildSettings = ( scalaJSConfigSettings
...
887 888 889 890 891 892 893 894 895 896 886 887 888 889 890 891 892 893 894 895 896 897
scalaJSModuleInitializers in Test := scalaJSModuleInitializers.value, scalaJSUseMainModuleInitializer := false, scalaJSUseMainModuleInitializer in Test := false,
jsEnv := new NodeJSEnv(),
jsExecutionFiles := Nil, jsExecutionFiles in Compile := jsExecutionFiles.value, // Do not inherit jsExecutionFiles in Test from Compile jsExecutionFiles in Test := jsExecutionFiles.value,

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
import sbt.testing.{Logger => _, _} final class ScalaJSFramework( private[testadapter] val frameworkName: String,
private[testadapter] val libEnv: ComJSEnv,
private val jsEnv: ComJSEnv, private val jsFiles: Seq[VirtualJSFile],
private[testadapter] val moduleKind: ModuleKind, private[testadapter] val moduleIdentifier: Option[String], private[testadapter] val logger: Logger, private[testadapter] val jsConsole: JSConsole ) extends Framework {
def this(frameworkName: String, libEnv: ComJSEnv, logger: Logger, jsConsole: JSConsole) = { this(frameworkName, libEnv, ModuleKind.NoModule, None, logger, jsConsole)
def this(frameworkName: String, jsEnv: ComJSEnv, jsFiles: Seq[VirtualJSFile], logger: Logger, jsConsole: JSConsole) = { this(frameworkName, jsEnv, jsFiles, ModuleKind.NoModule, None, logger, jsConsole)
} private[this] val frameworkInfo = fetchFrameworkInfo() private[this] var _isRunning = false
...
55 56 57 58 59 60 61 62 63 64 65 66 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
new ScalaJSRunner(this, args, remoteArgs) } private[testadapter] def runDone(): Unit = synchronized(_isRunning = false)
private[testadapter] def newComRunner(files: Seq[VirtualJSFile]): ComJSRunner = jsEnv.comRunner(jsFiles ++ files)
private def fetchFrameworkInfo() = {
val runner = libEnv.comRunner(frameworkInfoLauncher :: Nil)
val runner = newComRunner(frameworkInfoLauncher :: Nil)
runner.start(logger, jsConsole) try { val msg = readJSON(runner.receive()) fromJSON[FrameworkInfo](msg)

175 176 177 178 179 180 181 182 183 184 185 175 176 177 178 179 180 181 182 183 184 185
private def createSlave(): ComJSRunner = { // We don't want to create new slaves when we're closing/closed ensureNotDone() // Launch the slave
val slave = framework.libEnv.comRunner(slaveLauncher :: Nil)
val slave = framework.newComRunner(slaveLauncher :: Nil)
slave.start(framework.logger, framework.jsConsole) // Create a runner on the slave slave.send("newRunner") ComUtils.receiveLoop(slave)(msgHandler(slave) orElse ComUtils.doneHandler)
...
216 217 218 219 220 221 222 223 224 225 226 216 217 218 219 220 221 222 223 224 225 226
} private def createRemoteRunner(): Unit = { assert(master == null)
master = framework.libEnv.comRunner(masterLauncher :: Nil)
master = framework.newComRunner(masterLauncher :: Nil)
master.start(framework.logger, framework.jsConsole) val data = { val bld = new JSONObjBuilder bld.fld("args", args.toList)
About FluentSend Feedback