Skip to content

Upgrade to Scala.js 1.2.0. #9758

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

Merged
merged 3 commits into from
Sep 10, 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
60 changes: 57 additions & 3 deletions compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class JSCodeGen()(using genCtx: Context) {
// Some state --------------------------------------------------------------

private val generatedClasses = mutable.ListBuffer.empty[js.ClassDef]
private val generatedStaticForwarderClasses = mutable.ListBuffer.empty[(Symbol, js.ClassDef)]

private val currentClassSym = new ScopedVar[Symbol]
private val currentMethodSym = new ScopedVar[Symbol]
Expand Down Expand Up @@ -111,6 +112,7 @@ class JSCodeGen()(using genCtx: Context) {
genCompilationUnit(ctx.compilationUnit)
} finally {
generatedClasses.clear()
generatedStaticForwarderClasses.clear()
}
}

Expand Down Expand Up @@ -179,6 +181,39 @@ class JSCodeGen()(using genCtx: Context) {

for (tree <- generatedClasses)
genIRFile(cunit, tree)

if (generatedStaticForwarderClasses.nonEmpty) {
/* #4148 Add generated static forwarder classes, except those that
* would collide with regular classes on case insensitive file systems.
*/

/* I could not find any reference anywhere about what locale is used
* by case insensitive file systems to compare case-insensitively.
* In doubt, force the English locale, which is probably going to do
* the right thing in virtually all cases (especially if users stick
* to ASCII class names), and it has the merit of being deterministic,
* as opposed to using the OS' default locale.
* The JVM backend performs a similar test to emit a warning for
* conflicting top-level classes. However, it uses `toLowerCase()`
* without argument, which is not deterministic.
*/
def caseInsensitiveNameOf(classDef: js.ClassDef): String =
classDef.name.name.nameString.toLowerCase(java.util.Locale.ENGLISH)

val generatedCaseInsensitiveNames =
generatedClasses.map(caseInsensitiveNameOf).toSet

for ((site, classDef) <- generatedStaticForwarderClasses) {
if (!generatedCaseInsensitiveNames.contains(caseInsensitiveNameOf(classDef))) {
genIRFile(cunit, classDef)
} else {
report.warning(
s"Not generating the static forwarders of ${classDef.name.name.nameString} " +
"because its name differs only in case from the name of another class or trait in this compilation unit.",
site.srcPos)
}
}
}
}

private def genIRFile(cunit: CompilationUnit, tree: ir.Trees.ClassDef): Unit = {
Expand Down Expand Up @@ -346,7 +381,7 @@ class JSCodeGen()(using genCtx: Context) {
forwarders,
Nil
)(js.OptimizerHints.empty)
generatedClasses += forwardersClassDef
generatedStaticForwarderClasses += sym -> forwardersClassDef
}
}
allMemberDefsExceptStaticForwarders
Expand Down Expand Up @@ -523,14 +558,33 @@ class JSCodeGen()(using genCtx: Context) {
* `def hashCode(): Int` and a `static def hashCode(Int): Int`. The JVM
* back-end considers them as colliding because they have the same name,
* but we must not.
*
* By default, we only emit forwarders for top-level objects, like the JVM
* back-end. However, if requested via a compiler option, we enable them
* for all static objects. This is important so we can implement static
* methods of nested static classes of JDK APIs (see scala-js/#3950).
*/

/** Is the given Scala class, interface or module class a candidate for
* static forwarders?
*
* - the flag `-XnoForwarders` is not set to true, and
* - the symbol is static, and
* - either of both of the following is true:
* - the flag `-scalajsGenStaticForwardersForNonTopLevelObjects` is set to true, or
* - the symbol was originally at the package level
*
* Other than the Scala.js-specific flag, and the fact that we also consider
* interfaces, this performs the same tests as the JVM back-end.
*/
def isCandidateForForwarders(sym: Symbol): Boolean = {
// it must be a top level class
sym.isStatic
!ctx.settings.XnoForwarders.value && sym.isStatic && {
ctx.settings.scalajsGenStaticForwardersForNonTopLevelObjects.value || {
atPhase(flattenPhase) {
toDenot(sym).owner.is(PackageClass)
}
}
}
}

/** Gen the static forwarders to the members of a class or interface for
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class ScalaSettings extends Settings.SettingGroup {
val pluginsDir: Setting[String] = StringSetting ("-Xpluginsdir", "path", "Path to search for plugin archives.", Defaults.scalaPluginPath)
val pluginOptions: Setting[List[String]] = MultiStringSetting ("-P", "plugin:opt", "Pass an option to a plugin, e.g. -P:<plugin>:<opt>")

/** Scala.js-related settings */
val scalajsGenStaticForwardersForNonTopLevelObjects: Setting[Boolean] = BooleanSetting("-scalajs-genStaticForwardersForNonTopLevelObjects", "Generate static forwarders even for non-top-level objects (Scala.js only)")

/** -X "Advanced" settings
*/
val Xhelp: Setting[Boolean] = BooleanSetting("-X", "Print a synopsis of advanced options.")
Expand Down
22 changes: 5 additions & 17 deletions project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,8 @@ object Build {
)
}.taskValue,

scalacOptions in Test += "-scalajs-genStaticForwardersForNonTopLevelObjects",

scalaJSLinkerConfig ~= { _.withSemantics(build.TestSuiteLinkerOptions.semantics _) },
scalaJSModuleInitializers in Test ++= build.TestSuiteLinkerOptions.moduleInitializers,

Expand All @@ -1023,29 +1025,15 @@ object Build {
(dir / "shared/src/test/scala" ** (("*.scala": FileFilter)
-- "ReflectiveCallTest.scala" // uses many forms of structural calls that are not allowed in Scala 3 anymore
-- "EnumerationTest.scala" // scala.Enumeration support for Scala.js is not implemented in dotc (yet)
-- "SymbolTest.scala" // uses the old literal symbol syntax, pending update upstream

// all the following depend on HashSetTest and LinkedHashSetTest ...
-- "CollectionsOnCheckedCollectionTest.scala"
-- "CollectionsOnCheckedListTest.scala"
-- "CollectionsOnCheckedSetTest.scala"
-- "CollectionsOnSetsTest.scala"
-- "CollectionsOnSynchronizedCollectionTest.scala"
-- "CollectionsOnSynchronizedListTest.scala"
-- "CollectionsOnSynchronizedSetTest.scala"

// ... which do not compile because of an abstract method shadowing a concrete method, pending update upstream
-- "HashSetTest.scala"
-- "LinkedHashSetTest.scala"
)).get

++ (dir / "shared/src/test/require-sam" ** "*.scala").get
++ (dir / "shared/src/test/require-jdk8" ** "*.scala").get
++ (dir / "shared/src/test/require-jdk7" ** "*.scala").get

++ (dir / "js/src/test/scala/org/scalajs/testsuite/compiler" ** (("*.scala": FileFilter)
-- "InteroperabilityTest.scala" // various compile errors, pending update upstream
-- "OptimizerTest.scala" // compile errors: false + string and () + string, pending update upstream
-- "InteroperabilityTest.scala" // compiler crash, related to value classes in JS interop
-- "OptimizerTest.scala" // non-native JS classes
-- "ReflectionTest.scala" // tests fail (wrong load spec for JS globals)
-- "RegressionJSTest.scala" // non-native JS classes
-- "RuntimeTypesTest.scala" // compile errors: no ClassTag for Null and Nothing
Expand Down Expand Up @@ -1081,7 +1069,7 @@ object Build {
)).get

++ (dir / "js/src/test/scala/org/scalajs/testsuite/library" ** (("*.scala": FileFilter)
-- "BigIntTest.scala" // Ambiguous reference because of new non-shadowing rule in Scala 3, pending update upstream
-- "BigIntTest.scala" // non-native JS classes
-- "ObjectTest.scala" // compile errors caused by #9588
-- "StackTraceTest.scala" // would require `npm install source-map-support`
-- "UnionTypeTest.scala" // requires a Scala 2 macro
Expand Down
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// e.g. addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.1.0")

addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.1.1")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.2.0")

addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.6")

Expand Down