Skip to content

Commit

Permalink
Merge pull request #374 from sjrd/scalajs-1.3.0
Browse files Browse the repository at this point in the history
Upgrade to Scala.js 1.3.0
  • Loading branch information
sjrd authored Oct 20, 2020
2 parents 08d6e48 + 35292c7 commit 1177814
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 63 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
val scalaJSVersion = sys.env.getOrElse("SCALAJS_VERSION", "1.0.0")
val scalaJSVersion = sys.env.getOrElse("SCALAJS_VERSION", "1.3.0")

lazy val `scalajs-bundler-linker` =
project.in(file("scalajs-bundler-linker"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package scalajsbundler.sbtplugin
import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Path}
import scala.collection.JavaConverters._
import org.scalajs.jsenv.Input._
import org.scalajs.linker.interface._
import org.scalajs.sbtplugin._
import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._
Expand Down Expand Up @@ -61,37 +62,26 @@ private[sbtplugin] object Settings {
)

// Settings that must be applied for each stage in each configuration
private def scalaJSStageSettings(stage: Stage, key: TaskKey[Attributed[File]]): Seq[Setting[_]] = {
private def scalaJSStageSettings(stage: Stage, key: TaskKey[Attributed[Report]],
legacyKey: TaskKey[Attributed[File]]): Seq[Setting[_]] = {
val entryPointOutputFileName =
s"entrypoints-${stage.toString.toLowerCase}.txt"

Def.settings(
scalaJSLinker in key := {
scalaJSLinker in legacyKey := {
val config = (scalaJSLinkerConfig in key).value
val box = (scalaJSLinkerBox in key).value
val linkerImpl = (scalaJSLinkerImpl in key).value
val projectID = thisProject.value.id
val configName = configuration.value.name
val log = streams.value.log
val entryPointOutputFile = crossTarget.value / entryPointOutputFileName

if (config.moduleKind != scalaJSLinkerConfig.value.moduleKind) {
val keyName = key.key.label
log.warn(
s"The module kind in `scalaJSLinkerConfig in ($projectID, " +
s"$configName, $keyName)` is different than the one `in " +
s"`($projectID, $configName)`. " +
"Some things will go wrong.")
}

box.ensure {
linkerImpl.asInstanceOf[BundlerLinkerImpl]
.bundlerLinker(config, entryPointOutputFile.toPath)
}
},

scalaJSBundlerImportedModules in key := {
val _ = key.value
scalaJSBundlerImportedModules in legacyKey := {
val _ = legacyKey.value
val entryPointOutputFile = crossTarget.value / entryPointOutputFileName
val lines = Files.readAllLines(entryPointOutputFile.toPath, StandardCharsets.UTF_8)
lines.asScala.toList
Expand All @@ -105,8 +95,45 @@ private[sbtplugin] object Settings {
// Override Scala.js’ jsEnvInput to first run `npm update`
jsEnvInput := jsEnvInput.dependsOn(npmUpdate).value,

scalaJSStageSettings(FastOptStage, fastOptJS),
scalaJSStageSettings(FullOptStage, fullOptJS)
/* Moreover, force it to use the output of the legacy key, because lots
* of things in scalajs-bundler assume that there is only one .js file
* that we can put in a specific directory to make things work.
*/
jsEnvInput := {
val prev = jsEnvInput.value
val linkingResult = scalaJSLinkerResult.value
val legacyKeyOutput = scalaJSLinkedFile.value

// Compute the path to the `main` module, which is what sbt-scalajs puts in jsEnvInput
val report = linkingResult.data
val optMainModule = report.publicModules.find(_.moduleID == "main")
val optMainModulePath = optMainModule.map { mainModule =>
val linkerOutputDirectory = linkingResult.get(scalaJSLinkerOutputDirectory.key).getOrElse {
throw new MessageOnlyException(
"Linking report was not attributed with output directory. " +
"Please report this as a Scala.js bug.")
}
(linkerOutputDirectory / mainModule.jsFileName).toPath
}

// Replace the path to the `main` module by the path to the legacy key output
optMainModulePath match {
case Some(mainModulePath) =>
prev.map { inputItem =>
inputItem match {
case CommonJSModule(module) if module == mainModulePath =>
CommonJSModule(legacyKeyOutput.data.toPath())
case _ =>
inputItem
}
}
case None =>
prev
}
},

scalaJSStageSettings(FastOptStage, fastLinkJS, fastOptJS),
scalaJSStageSettings(FullOptStage, fullLinkJS, fullOptJS)
)

// Settings that must be applied in the Test configuration
Expand All @@ -129,8 +156,6 @@ private[sbtplugin] object Settings {

// Use the product of bundling in jsEnvInput if requireJsDomEnv is true
jsEnvInput := Def.task {
import org.scalajs.jsenv.Input._

assert(ensureModuleKindIsCommonJSModule.value)
val prev = jsEnvInput.value
val sjsOutput = scalaJSLinkedFile.value.data
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
> run
> clean
> test
> set useYarn := true
> clean
> run
> clean
> test

# Deactivated because `clean` followed by `run` kills the AppVeyor build.
# Testing yarn support is done enough in other tests.
#> set useYarn := true
#> clean
#> run
#> test
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.1.0")
// TODO Set this to a version > 1.3.0 when there is one
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.3.0")
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import org.junit.Test
class NewerLinkerTest {

@Test def newerLinker(): Unit = {
assertEquals("1.1.0", System.getProperty("java.vm.version"))
/* TODO Set this to a version > 1.3.0 when there is one, and adapt the
* test below to something that would have been fixed in the meantime.
*/
assertEquals("1.3.0", System.getProperty("java.vm.version"))

/* Test the fix to https://github.com/scala-js/scala-js/issues/3984, which
* was shipped in Scala.js 1.0.1.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ $ exists target/scala-2.11/scalajs-bundler/main/static-opt-bundle.js target/scal

# Disabling source maps in Scala.js also disables it for scalajs-bundler

> clean
$ delete target/scala-2.11/scalajs-bundler/main/static-fastopt-bundle.js.map target/scala-2.11/scalajs-bundler/main/static-opt-bundle.js.map
> set scalaJSLinkerConfig := scalaJSLinkerConfig.value.withSourceMap(false)
> fastOptJS::webpack
$ absent target/scala-2.11/scalajs-bundler/main/static-fastopt-bundle.js.map
Expand All @@ -20,7 +20,6 @@ $ absent target/scala-2.11/scalajs-bundler/main/static-opt-bundle.js.map

# webpackEmitSourceMaps controls source maps emission for the webpack task

> clean
> set scalaJSLinkerConfig := scalaJSLinkerConfig.value.withSourceMap(true)
> set webpackEmitSourceMaps in (Compile, fastOptJS) := false
> fastOptJS::webpack
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ useYarn := true

yarnExtraArgs in Compile := Seq("--silent")

scalaJSUseMainModuleInitializer := true

npmDependencies in Compile += "neat" -> "1.1.2"

enablePlugins(ScalaJSBundlerPlugin)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package example

object Main {
def main(args: Array[String]): Unit = {
println("yarn-interactive main")
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
> clean
> server/assets
$ exists client/target/scala-2.13/scalajs-bundler/main/client-fastopt-bundle.js
$ absent client/target/scala-2.13/scalajs-bundler/main/client-opt-bundle.js
$ delete client/target/scala-2.13/scalajs-bundler/main/client-fastopt-bundle.js

> clean
> set scalaJSStage in Global := FullOptStage
> server/assets
$ exists client/target/scala-2.13/scalajs-bundler/main/client-opt-bundle.js
$ absent client/target/scala-2.13/scalajs-bundler/main/client-fastopt-bundle.js
$ delete client/target/scala-2.13/scalajs-bundler/main/client-opt-bundle.js

> clean
> set scalaJSStage in Global := FastOptStage
> server/test
> client/test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,23 @@ import scala.collection.JavaConverters._
import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Path}

import org.scalajs.ir.Trees.JSNativeLoadSpec

import org.scalajs.logging.Logger

import org.scalajs.linker.interface._
import org.scalajs.linker.standard._

final class EntryPointAnalyzerBackend(linkerConfig: StandardConfig, entryPointOutputFile: Path) extends LinkerBackend {
final class EntryPointAnalyzerBackend(linkerConfig: StandardConfig, entryPointOutputFile: Path) extends LinkerBackend {
private val standard = StandardLinkerBackend(linkerConfig)

val coreSpec: CoreSpec = standard.coreSpec
val symbolRequirements: SymbolRequirement = standard.symbolRequirements

def injectedIRFiles: Seq[IRFile] = standard.injectedIRFiles

def emit(unit: LinkingUnit, output: LinkerOutput, logger: Logger)(
implicit ec: ExecutionContext): Future[Unit] = {

val modules = importedModules(unit)
def emit(moduleSet: ModuleSet, output: OutputDirectory, logger: Logger)(
implicit ec: ExecutionContext): Future[Report] = {
val modules = moduleSet.modules.flatMap(_.externalDependencies).toSet
Files.write(entryPointOutputFile, modules.toIterable.asJava, StandardCharsets.UTF_8)

standard.emit(unit, output, logger)
}

private def importedModules(linkingUnit: LinkingUnit): List[String] = {
if (linkerConfig.moduleKind == ModuleKind.NoModule) {
Nil
} else {
def importedModulesOf(loadSpec: JSNativeLoadSpec): List[String] = {
import JSNativeLoadSpec._
loadSpec match {
case Import(module, _) => List(module)
case ImportWithGlobalFallback(Import(module, _), _) => List(module)
case Global(_, _) => Nil
}
}

linkingUnit.classDefs
.flatMap(_.jsNativeLoadSpec)
.flatMap(importedModulesOf(_))
.distinct
}
standard.emit(moduleSet, output, logger)
}
}

0 comments on commit 1177814

Please sign in to comment.