8000 Apply the IR cleaner to the scalalib and the library-aux. · scala-js/scala-js@b35d481 · GitHub
[go: up one dir, main page]

Skip to content

Commit b35d481

Browse files
committed
Apply the IR cleaner to the scalalib and the library-aux.
It is configured differently than for the javalib. We allow references to `scala.*` (obviously) but disallow references to `scala.scalajs.*`. We also avoid rewriting Scala functions to JS functions, since that changes the binary APIs. We use a local copy of `sjs.runtime.AnonFunctionN` classes in `scala.runtime.*` to support the codegen of lambdas.
1 parent 2944d98 commit b35d481

File tree

4 files changed

+199
-25
lines changed

4 files changed

+199
-25
lines changed

linker/shared/src/main/scala/org/scalajs/linker/frontend/optimizer/OptimizerCore.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5906,6 +5906,8 @@ private[optimizer] object OptimizerCore {
59065906
),
59075907
ClassName("scala.collection.mutable.ArrayBuilder$") -> List(
59085908
m("scala$collection$mutable$ArrayBuilder$$zeroOf", List(ClassClassRef), O) -> ArrayBuilderZeroOf,
5909+
m("scala$collection$mutable$ArrayBuilder$$genericArrayBuilderResult", List(ClassClassRef, O), O) -> GenericArrayBuilderResult,
5910+
// and its legacy signature (< v1.13.0)
59095911
m("scala$collection$mutable$ArrayBuilder$$genericArrayBuilderResult", List(ClassClassRef, JSArrayClassRef), O) -> GenericArrayBuilderResult
59105912
),
59115913
ClassName("java.lang.Class") -> List(

project/Build.scala

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -673,9 +673,9 @@ object Build {
673673
}
674674
)
675675

676-
val cleanIRSettings = Def.settings(
676+
def cleanIRSettings(forScalalib: Boolean): Seq[Setting[_]] = Def.settings(
677677
// In order to rewrite anonymous functions and tuples, the code must not be specialized
678-
scalacOptions += "-no-specialization",
678+
scalacOptions ++= (if (forScalalib) Nil else Seq("-no-specialization")),
679679

680680
products in Compile := {
681681
val s = streams.value
@@ -684,7 +684,7 @@ object Build {
684684

685685
val outputDir = crossTarget.value / "cleaned-classes"
686686

687-
val irCleaner = new JavalibIRCleaner((LocalRootProject / baseDirectory).value.toURI())
687+
val irCleaner = new JavalibIRCleaner((LocalRootProject / baseDirectory).value.toURI(), forScalalib)
688688

689689
val libFileMappings = (PathFinder(prevProducts) ** "*.sjsir")
690690
.pair(Path.rebase(prevProducts, outputDir))
@@ -1141,7 +1141,7 @@ object Build {
11411141
name := "Scala.js linker private library",
11421142
publishArtifact in Compile := false,
11431143
delambdafySetting,
1144-
cleanIRSettings
1144+
cleanIRSettings(forScalalib = false),
11451145
).withScalaJSCompiler2_12.withScalaJSJUnitPlugin2_12.dependsOnLibrary2_12.dependsOn(
11461146
jUnitRuntime.v2_12 % "test", testBridge.v2_12 % "test",
11471147
)
@@ -1457,7 +1457,7 @@ object Build {
14571457
Seq(output)
14581458
}.taskValue,
14591459

1460-
cleanIRSettings,
1460+
cleanIRSettings(forScalalib = false),
14611461

14621462
Compile / doc := {
14631463
val dir = (Compile / doc / target).value
@@ -1654,6 +1654,8 @@ object Build {
16541654

16551655
headerSources in Compile := Nil,
16561656
headerSources in Test := Nil,
1657+
1658+
cleanIRSettings(forScalalib = true),
16571659
).withScalaJSCompiler.dependsOnLibraryNoJar
16581660

16591661
lazy val libraryAux: MultiScalaProject = MultiScalaProject(
@@ -1669,6 +1671,8 @@ object Build {
16691671
delambdafySetting,
16701672

16711673
recompileAllOrNothingSettings,
1674+
1675+
cleanIRSettings(forScalalib = true),
16721676
).withScalaJSCompiler.dependsOnLibraryNoJar
16731677

16741678
lazy val library: MultiScalaProject = MultiScalaProject(
@@ -1925,15 +1929,15 @@ object Build {
19251929
scalaVersion.value match {
19261930
case `default212Version` =>
19271931
Some(ExpectedSizes(
1928-
fastLink = 766000 to 767000,
1932+
fastLink = 767000 to 768000,
19291933
fullLink = 144000 to 145000,
19301934
fastLinkGz = 90000 to 91000,
19311935
fullLinkGz = 35000 to 36000,
19321936
))
19331937

19341938
case `default213Version` =>
19351939
Some(ExpectedSizes(
1936-
fastLink = 482000 to 483000,
1940+
fastLink = 483000 to 484000,
19371941
fullLink = 103000 to 104000,
19381942
fastLinkGz = 62000 to 63000,
19391943
fullLinkGz = 27000 to 28000,

project/JavalibIRCleaner.scala

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,13 @@ import sbt.{Logger, MessageOnlyException}
3939
* Afterwards, we check that the IR does not contain any reference to classes
4040
* under the `scala.*` package.
4141
*/
42-
final class JavalibIRCleaner(baseDirectoryURI: URI) {
42+
final class JavalibIRCleaner(baseDirectoryURI: URI, forScalalib: Boolean) {
4343
import JavalibIRCleaner._
4444

45+
private val classNameSubstitutions: Map[ClassName, ClassName] =
46+
if (forScalalib) ClassNameSubstitutionsForScalalib
47+
else ClassNameSubstitutionsForJavalib
48+
4549
def cleanIR(dependencyFiles: Seq[File], libFileMappings: Seq[(File, File)],
4650
logger: Logger): Set[File] = {
4751

@@ -80,11 +84,19 @@ final class JavalibIRCleaner(baseDirectoryURI: URI) {
8084
}
8185

8286
if (errorManager.hasErrors) {
83-
throw new MessageOnlyException(
84-
s"There were ${errorManager.errorCount} errors while " +
85-
"postprocessing the IR of the javalanglib. " +
86-
"The javalanglib must be written in a style that does not leak any " +
87-
"reference to the Scala library.")
87+
if (forScalalib) {
88+
throw new MessageOnlyException(
89+
s"There were ${errorManager.errorCount} errors while " +
90+
"postprocessing the IR of the scalalib. " +
91+
"The scalalib must be written in a style that does not leak any " +
92+
"reference to the Scala.js standard library.")
93+
} else {
94+
throw new MessageOnlyException(
95+
s"There were ${errorManager.errorCount} errors while " +
96+
"postprocessing the IR of the javalib. " +
97+
"The javalib must be written in a style that does not leak any " +
98+
"reference to the Scala library.")
99+
}
88100
}
89101

90102
resultBuilder.result()
@@ -146,10 +158,12 @@ final class JavalibIRCleaner(baseDirectoryURI: URI) {
146158
// Preprocess the super interface list
147159
val newInterfaces = transformInterfaceList(interfaces)
148160

149-
/* Remove the `private def writeReplace__O` generated by scalac 2.13+
150-
* in the companion of serializable classes.
161+
/* javalib only: Remove the `private def writeReplace__O` generated by
162+
* scalac 2.13+ in the companion of serializable classes.
151163
*/
152-
val newMethods = methods.filter(_.name.name != writeReplaceMethodName)
164+
val newMethods =
165+
if (forScalalib) methods
166+
else methods.filter(_.name.name != writeReplaceMethodName)
153167

154168
val preprocessedTree = ClassDef(name, originalName, kind, jsClassCaptures,
155169
superClass, newInterfaces, jsSuperClass, jsNativeLoadSpec, fields,
@@ -177,9 +191,13 @@ final class JavalibIRCleaner(baseDirectoryURI: URI) {
177191
/* Replace references to scala.Serializable by java.io.Serializable.
178192
* This works around the fact that scalac adds scala.Serializable to the
179193
* companion object of any class that extends java.io.Serializable.
194+
*
195+
* Don't do it for the scalalib.
180196
*/
181197

182-
if (!interfaces.exists(_.name == ScalaSerializable)) {
198+
if (forScalalib) {
199+
interfaces
200+
} else if (!interfaces.exists(_.name == ScalaSerializable)) {
183201
interfaces
184202
} else if (interfaces.exists(_.name == JavaIOSerializable)) {
185203
interfaces.filter(_.name != ScalaSerializable)
@@ -321,13 +339,13 @@ final class JavalibIRCleaner(baseDirectoryURI: URI) {
321339
implicit val pos = tree.pos
322340

323341
tree match {
324-
// new AnonFunctionN(closure) --> closure
325-
case New(AnonFunctionNClass(n), _, List(closure)) =>
342+
// javalib only: new AnonFunctionN(closure) --> closure
343+
case New(AnonFunctionNClass(n), _, List(closure)) if !forScalalib =>
326344
closure
327345

328-
// someFunctionN.apply(args) --> someFunctionN(args)
346+
// javalib only: someFunctionN.apply(args) --> someFunctionN(args)
329347
case Apply(ApplyFlags.empty, fun, MethodIdent(FunctionApplyMethodName(n)), args)
330-
if isFunctionNType(n, fun.tpe) =>
348+
if !forScalalib && isFunctionNType(n, fun.tpe) =>
331349
JSFunctionApply(fun, args)
332350

333351
// <= 2.12 : toJSVarArgs(jsArrayOps(jsArray).toSeq) -> jsArray
@@ -582,7 +600,7 @@ final class JavalibIRCleaner(baseDirectoryURI: URI) {
582600
}
583601

584602
private def transformClassName(cls: ClassName)(implicit pos: Position): ClassName = {
585-
ClassNameSubstitutions.getOrElse(cls, {
603+
classNameSubstitutions.getOrElse(cls, {
586604
validateClassName(cls)
587605
cls
588606
})
@@ -600,8 +618,13 @@ final class JavalibIRCleaner(baseDirectoryURI: URI) {
600618
def isAnException: Boolean =
601619
isJavaScriptExceptionWithinItself || isTypedArrayBufferBridgeWithinItself
602620

603-
if (cls.nameString.startsWith("scala.") && !isAnException)
604-
reportError(s"Illegal reference to Scala class ${cls.nameString}")
621+
if (forScalalib) {
622+
if (cls.nameString.startsWith("scala.scalajs."))
623+
reportError(s"Illegal reference to Scala.js class ${cls.nameString}")
624+
} else {
625+
if (cls.nameString.startsWith("scala.") && !isAnException)
626+
reportError(s"Illegal reference to Scala class ${cls.nameString}")
627+
}
605628
}
606629

607630
private def transformNonJSClassName(cls: ClassName)(implicit pos: Position): ClassName = {
@@ -729,7 +752,7 @@ object JavalibIRCleaner {
729752
false
730753
}
731754

732-
private val ClassNameSubstitutions: Map[ClassName, ClassName] = {
755+
private val ClassNameSubstitutionsForJavalib: Map[ClassName, ClassName] = {
733756
val functionTypePairs = for {
734757
funClass <- FunctionNClasses ++ AnonFunctionNClasses
735758
} yield {
@@ -762,4 +785,15 @@ object JavalibIRCleaner {
762785
val allPairs = functionTypePairs ++ refPairs ++ tuplePairs ++ otherPairs
763786
allPairs.toMap
764787
}
788+
789+
private val ClassNameSubstitutionsForScalalib: Map[ClassName, ClassName] = {
790+
val anonFunctionPairs = for {
791+
n <- (0 to 22).toList
792+
} yield {
793+
ClassName(s"scala.scalajs.runtime.AnonFunction$n") -> ClassName(s"scala.runtime.AnonFunction$n")
794+
}
795+
796+
val allPairs = anonFunctionPairs
797+
allPairs.toMap
798+
}
765799
}

0 commit comments

Comments
 (0)
0