diff --git a/linker/shared/src/main/scala/org/scalajs/linker/analyzer/Analyzer.scala b/linker/shared/src/main/scala/org/scalajs/linker/analyzer/Analyzer.scala index 2379ca00c6..22d3752fd4 100644 --- a/linker/shared/src/main/scala/org/scalajs/linker/analyzer/Analyzer.scala +++ b/linker/shared/src/main/scala/org/scalajs/linker/analyzer/Analyzer.scala @@ -31,7 +31,7 @@ import org.scalajs.ir.WellKnownNames._ import org.scalajs.linker._ import org.scalajs.linker.checker.CheckingPhase -import org.scalajs.linker.frontend.{IRLoader, LambdaSynthesizer, SyntheticClassKind} +import org.scalajs.linker.frontend.{IRLoader, LambdaSynthesizer, LinkTimeProperties, SyntheticClassKind} import org.scalajs.linker.interface._ import org.scalajs.linker.interface.unstable.ModuleInitializerImpl import org.scalajs.linker.standard._ @@ -47,6 +47,8 @@ import Infos.{NamespacedMethodName, ReachabilityInfo, ReachabilityInfoInClass} final class Analyzer(config: CommonPhaseConfig, initial: Boolean, checkIRFor: Option[CheckingPhase], failOnError: Boolean, irLoader: IRLoader) { + private val linkTimeProperties = LinkTimeProperties.fromCoreSpec(config.coreSpec) + private val infoLoader: InfoLoader = new InfoLoader(irLoader, checkIRFor) @@ -55,7 +57,7 @@ final class Analyzer(config: CommonPhaseConfig, initial: Boolean, infoLoader.update(logger) - val run = new AnalyzerRun(config, initial, infoLoader)( + val run = new AnalyzerRun(config, initial, infoLoader, linkTimeProperties)( adjustExecutionContextForParallelism(ec, config.parallel)) run @@ -99,7 +101,10 @@ final class Analyzer(config: CommonPhaseConfig, initial: Boolean, } private class AnalyzerRun(config: CommonPhaseConfig, initial: Boolean, - infoLoader: InfoLoader)(implicit ec: ExecutionContext) extends Analysis { + infoLoader: InfoLoader, linkTimeProperties: LinkTimeProperties)( + implicit ec: ExecutionContext) + extends Analysis { + import AnalyzerRun._ private val allowAddingSyntheticMethods = initial @@ -1539,7 +1544,7 @@ private class AnalyzerRun(config: CommonPhaseConfig, initial: Boolean, if (data.referencedLinkTimeProperties.nonEmpty) { for ((name, tpe) <- data.referencedLinkTimeProperties) { - if (!config.coreSpec.linkTimeProperties.validate(name, tpe)) { + if (!linkTimeProperties.get(name).exists(_.tpe == tpe)) { _errors ::= InvalidLinkTimeProperty(name, tpe, from) } } diff --git a/linker/shared/src/main/scala/org/scalajs/linker/frontend/Desugarer.scala b/linker/shared/src/main/scala/org/scalajs/linker/frontend/Desugarer.scala index 44e2f66d09..57f8eeb366 100644 --- a/linker/shared/src/main/scala/org/scalajs/linker/frontend/Desugarer.scala +++ b/linker/shared/src/main/scala/org/scalajs/linker/frontend/Desugarer.scala @@ -28,7 +28,9 @@ import org.scalajs.ir.{Position, Version} final class Desugarer(config: CommonPhaseConfig, checkIR: Boolean) { import Desugarer._ - private val desugarTransformer = new DesugarTransformer(config.coreSpec) + private val linkTimeProperties = LinkTimeProperties.fromCoreSpec(config.coreSpec) + + private val desugarTransformer = new DesugarTransformer(linkTimeProperties) def desugar(unit: LinkingUnit, logger: Logger): LinkingUnit = { val result = logger.time("Desugarer: Desugar") { @@ -118,7 +120,7 @@ final class Desugarer(config: CommonPhaseConfig, checkIR: Boolean) { private[linker] object Desugarer { - private final class DesugarTransformer(coreSpec: CoreSpec) + private final class DesugarTransformer(linkTimeProperties: LinkTimeProperties) extends ClassTransformer { /* Cache the names generated for lambda classes because computing their @@ -135,8 +137,17 @@ private[linker] object Desugarer { override def transform(tree: Tree): Tree = { tree match { - case prop: LinkTimeProperty => - coreSpec.linkTimeProperties.transformLinkTimeProperty(prop) + case LinkTimeProperty(name) => + implicit val pos = tree.pos + val value = linkTimeProperties.get(name).getOrElse { + throw new IllegalArgumentException( + s"link time property not found: '$name' of type ${tree.tpe}") + } + value match { + case LinkTimeProperties.LinkTimeBoolean(value) => BooleanLiteral(value) + case LinkTimeProperties.LinkTimeInt(value) => IntLiteral(value) + case LinkTimeProperties.LinkTimeString(value) => StringLiteral(value) + } case NewLambda(descriptor, fun) => implicit val pos = tree.pos diff --git a/linker/shared/src/main/scala/org/scalajs/linker/standard/LinkTimeProperties.scala b/linker/shared/src/main/scala/org/scalajs/linker/frontend/LinkTimeProperties.scala similarity index 50% rename from linker/shared/src/main/scala/org/scalajs/linker/standard/LinkTimeProperties.scala rename to linker/shared/src/main/scala/org/scalajs/linker/frontend/LinkTimeProperties.scala index 875196c736..d2c12c67d0 100644 --- a/linker/shared/src/main/scala/org/scalajs/linker/standard/LinkTimeProperties.scala +++ b/linker/shared/src/main/scala/org/scalajs/linker/frontend/LinkTimeProperties.scala @@ -10,15 +10,16 @@ * additional information regarding copyright ownership. */ -package org.scalajs.linker.standard +package org.scalajs.linker.frontend -import org.scalajs.ir.{Types => jstpe, Trees => js} import org.scalajs.ir.Trees.LinkTimeProperty._ +import org.scalajs.ir.Types._ import org.scalajs.ir.ScalaJSVersions -import org.scalajs.ir.Position.NoPosition -import org.scalajs.linker.interface.{Semantics, ESFeatures} -private[linker] final class LinkTimeProperties ( +import org.scalajs.linker.interface.{ESVersion => _, _} +import org.scalajs.linker.standard.CoreSpec + +final class LinkTimeProperties private ( semantics: Semantics, esFeatures: ESFeatures, targetIsWebAssembly: Boolean @@ -38,31 +39,24 @@ private[linker] final class LinkTimeProperties ( LinkTimeString(ScalaJSVersions.current) ) - def validate(name: String, tpe: jstpe.Type): Boolean = { - linkTimeProperties.get(name).exists { - case _: LinkTimeBoolean => tpe == jstpe.BooleanType - case _: LinkTimeInt => tpe == jstpe.IntType - case _: LinkTimeString => tpe == jstpe.StringType - } - } + def get(name: String): Option[LinkTimeValue] = + linkTimeProperties.get(name) +} + +object LinkTimeProperties { + sealed abstract class LinkTimeValue(val tpe: Type) - def transformLinkTimeProperty(prop: js.LinkTimeProperty): js.Literal = { - val value = linkTimeProperties.getOrElse(prop.name, - throw new IllegalArgumentException(s"link time property not found: '${prop.name}' of type ${prop.tpe}")) - value match { - case LinkTimeBoolean(value) => - js.BooleanLiteral(value)(prop.pos) - case LinkTimeInt(value) => - js.IntLiteral(value)(prop.pos) - case LinkTimeString(value) => - js.StringLiteral(value)(prop.pos) - } + final case class LinkTimeInt(value: Int) extends LinkTimeValue(IntType) + + final case class LinkTimeBoolean(value: Boolean) extends LinkTimeValue(BooleanType) + + final case class LinkTimeString(value: String) extends LinkTimeValue(StringType) { + // Being extra careful + require(value != null, "LinkTimeString requires a non-null value.") } -} -private[linker] object LinkTimeProperties { - sealed abstract class LinkTimeValue - final case class LinkTimeInt(value: Int) extends LinkTimeValue - final case class LinkTimeBoolean(value: Boolean) extends LinkTimeValue - final case class LinkTimeString(value: String) extends LinkTimeValue + def fromCoreSpec(coreSpec: CoreSpec): LinkTimeProperties = { + new LinkTimeProperties(coreSpec.semantics, coreSpec.esFeatures, + coreSpec.targetIsWebAssembly) + } } diff --git a/linker/shared/src/main/scala/org/scalajs/linker/standard/CoreSpec.scala b/linker/shared/src/main/scala/org/scalajs/linker/standard/CoreSpec.scala index e5e285268f..3c4c979adc 100644 --- a/linker/shared/src/main/scala/org/scalajs/linker/standard/CoreSpec.scala +++ b/linker/shared/src/main/scala/org/scalajs/linker/standard/CoreSpec.scala @@ -96,9 +96,6 @@ final class CoreSpec private ( targetIsWebAssembly ) } - - private[linker] lazy val linkTimeProperties = new LinkTimeProperties( - semantics, esFeatures, targetIsWebAssembly) } private[linker] object CoreSpec { diff --git a/project/BinaryIncompatibilities.scala b/project/BinaryIncompatibilities.scala index 4713fe6bf8..2e94162e72 100644 --- a/project/BinaryIncompatibilities.scala +++ b/project/BinaryIncompatibilities.scala @@ -8,6 +8,9 @@ object BinaryIncompatibilities { ) val Linker = Seq( + // private[linker], not an issue + ProblemFilters.exclude[DirectMissingMethodProblem]("org.scalajs.linker.standard.CoreSpec.linkTimeProperties"), + ProblemFilters.exclude[MissingClassProblem]("org.scalajs.linker.standard.LinkTimeProperties*"), ) val LinkerInterface = Seq(