Skip to content

Commit 760e503

Browse files
authored
Merge pull request #9758 from dotty-staging/scalajs-1.2.0
Upgrade to Scala.js 1.2.0.
2 parents 8639874 + 1ed50db commit 760e503

File tree

4 files changed

+66
-21
lines changed

4 files changed

+66
-21
lines changed

compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class JSCodeGen()(using genCtx: Context) {
6969
// Some state --------------------------------------------------------------
7070

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

7374
private val currentClassSym = new ScopedVar[Symbol]
7475
private val currentMethodSym = new ScopedVar[Symbol]
@@ -111,6 +112,7 @@ class JSCodeGen()(using genCtx: Context) {
111112
genCompilationUnit(ctx.compilationUnit)
112113
} finally {
113114
generatedClasses.clear()
115+
generatedStaticForwarderClasses.clear()
114116
}
115117
}
116118

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

180182
for (tree <- generatedClasses)
181183
genIRFile(cunit, tree)
184+
185+
if (generatedStaticForwarderClasses.nonEmpty) {
186+
/* #4148 Add generated static forwarder classes, except those that
187+
* would collide with regular classes on case insensitive file systems.
188+
*/
189+
190+
/* I could not find any reference anywhere about what locale is used
191+
* by case insensitive file systems to compare case-insensitively.
192+
* In doubt, force the English locale, which is probably going to do
193+
* the right thing in virtually all cases (especially if users stick
194+
* to ASCII class names), and it has the merit of being deterministic,
195+
* as opposed to using the OS' default locale.
196+
* The JVM backend performs a similar test to emit a warning for
197+
* conflicting top-level classes. However, it uses `toLowerCase()`
198+
* without argument, which is not deterministic.
199+
*/
200+
def caseInsensitiveNameOf(classDef: js.ClassDef): String =
201+
classDef.name.name.nameString.toLowerCase(java.util.Locale.ENGLISH)
202+
203+
val generatedCaseInsensitiveNames =
204+
generatedClasses.map(caseInsensitiveNameOf).toSet
205+
206+
for ((site, classDef) <- generatedStaticForwarderClasses) {
207+
if (!generatedCaseInsensitiveNames.contains(caseInsensitiveNameOf(classDef))) {
208+
genIRFile(cunit, classDef)
209+
} else {
210+
report.warning(
211+
s"Not generating the static forwarders of ${classDef.name.name.nameString} " +
212+
"because its name differs only in case from the name of another class or trait in this compilation unit.",
213+
site.srcPos)
214+
}
215+
}
216+
}
182217
}
183218

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

528568
/** Is the given Scala class, interface or module class a candidate for
529569
* static forwarders?
570+
*
571+
* - the flag `-XnoForwarders` is not set to true, and
572+
* - the symbol is static, and
573+
* - either of both of the following is true:
574+
* - the flag `-scalajsGenStaticForwardersForNonTopLevelObjects` is set to true, or
575+
* - the symbol was originally at the package level
576+
*
577+
* Other than the Scala.js-specific flag, and the fact that we also consider
578+
* interfaces, this performs the same tests as the JVM back-end.
530579
*/
531580
def isCandidateForForwarders(sym: Symbol): Boolean = {
532-
// it must be a top level class
533-
sym.isStatic
581+
!ctx.settings.XnoForwarders.value && sym.isStatic && {
582+
ctx.settings.scalajsGenStaticForwardersForNonTopLevelObjects.value || {
583+
atPhase(flattenPhase) {
584+
toDenot(sym).owner.is(PackageClass)
585+
}
586+
}
587+
}
534588
}
535589

536590
/** Gen the static forwarders to the members of a class or interface for

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ class ScalaSettings extends Settings.SettingGroup {
6565
val pluginsDir: Setting[String] = StringSetting ("-Xpluginsdir", "path", "Path to search for plugin archives.", Defaults.scalaPluginPath)
6666
val pluginOptions: Setting[List[String]] = MultiStringSetting ("-P", "plugin:opt", "Pass an option to a plugin, e.g. -P:<plugin>:<opt>")
6767

68+
/** Scala.js-related settings */
69+
val scalajsGenStaticForwardersForNonTopLevelObjects: Setting[Boolean] = BooleanSetting("-scalajs-genStaticForwardersForNonTopLevelObjects", "Generate static forwarders even for non-top-level objects (Scala.js only)")
70+
6871
/** -X "Advanced" settings
6972
*/
7073
val Xhelp: Setting[Boolean] = BooleanSetting("-X", "Print a synopsis of advanced options.")

project/Build.scala

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,8 @@ object Build {
10041004
)
10051005
}.taskValue,
10061006

1007+
scalacOptions in Test += "-scalajs-genStaticForwardersForNonTopLevelObjects",
1008+
10071009
scalaJSLinkerConfig ~= { _.withSemantics(build.TestSuiteLinkerOptions.semantics _) },
10081010
scalaJSModuleInitializers in Test ++= build.TestSuiteLinkerOptions.moduleInitializers,
10091011

@@ -1023,29 +1025,15 @@ object Build {
10231025
(dir / "shared/src/test/scala" ** (("*.scala": FileFilter)
10241026
-- "ReflectiveCallTest.scala" // uses many forms of structural calls that are not allowed in Scala 3 anymore
10251027
-- "EnumerationTest.scala" // scala.Enumeration support for Scala.js is not implemented in dotc (yet)
1026-
-- "SymbolTest.scala" // uses the old literal symbol syntax, pending update upstream
1027-
1028-
// all the following depend on HashSetTest and LinkedHashSetTest ...
1029-
-- "CollectionsOnCheckedCollectionTest.scala"
1030-
-- "CollectionsOnCheckedListTest.scala"
1031-
-- "CollectionsOnCheckedSetTest.scala"
1032-
-- "CollectionsOnSetsTest.scala"
1033-
-- "CollectionsOnSynchronizedCollectionTest.scala"
1034-
-- "CollectionsOnSynchronizedListTest.scala"
1035-
-- "CollectionsOnSynchronizedSetTest.scala"
1036-
1037-
// ... which do not compile because of an abstract method shadowing a concrete method, pending update upstream
1038-
-- "HashSetTest.scala"
1039-
-- "LinkedHashSetTest.scala"
10401028
)).get
10411029

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

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

10831071
++ (dir / "js/src/test/scala/org/scalajs/testsuite/library" ** (("*.scala": FileFilter)
1084-
-- "BigIntTest.scala" // Ambiguous reference because of new non-shadowing rule in Scala 3, pending update upstream
1072+
-- "BigIntTest.scala" // non-native JS classes
10851073
-- "ObjectTest.scala" // compile errors caused by #9588
10861074
-- "StackTraceTest.scala" // would require `npm install source-map-support`
10871075
-- "UnionTypeTest.scala" // requires a Scala 2 macro

project/plugins.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// e.g. addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.1.0")
44

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

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

0 commit comments

Comments
 (0)