diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 432f1fa5e738..e9c310bc17a2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -103,7 +103,7 @@ jobs: - name: Scala.js Test run: | - ./project/scripts/sbt ";sjsSandbox/run ;sjsSandbox/test ;sjsJUnitTests/test ;set sjsJUnitTests/scalaJSLinkerConfig ~= switchToESModules ;sjsJUnitTests/test ;sjsCompilerTests/test" + ./project/scripts/sbt ";sjsSandbox/run ;sjsSandbox/test ;sjsJUnitTests/test ;set sjsJUnitTests/scalaJSLinkerConfig ~= switchToESModules ;sjsJUnitTests/test" test_windows_fast: runs-on: [self-hosted, Windows] @@ -149,7 +149,7 @@ jobs: shell: cmd - name: Scala.js Test - run: sbt ";sjsJUnitTests/test ;set sjsJUnitTests/scalaJSLinkerConfig ~= switchToESModules ;sjsJUnitTests/test ;sjsCompilerTests/test" + run: sbt ";sjsJUnitTests/test ;set sjsJUnitTests/scalaJSLinkerConfig ~= switchToESModules ;sjsJUnitTests/test" shell: cmd test_windows_full: diff --git a/.github/workflows/stdlib.yaml b/.github/workflows/stdlib.yaml index 2c8bd19de543..98c89a76d886 100644 --- a/.github/workflows/stdlib.yaml +++ b/.github/workflows/stdlib.yaml @@ -392,6 +392,24 @@ jobs: - name: Report MiMa issues in `tasty-core-bootstrapped` run: ./project/scripts/sbt tasty-core-bootstrapped-new/mimaReportBinaryIssues + mima-scala-library-sjs: + runs-on: ubuntu-latest + needs: scala-library-sjs + steps: + - name: Git Checkout + uses: actions/checkout@v5 + + - name: Set up JDK 17 + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: 17 + cache: 'sbt' + + - uses: sbt/setup-sbt@v1 + - name: Report MiMa issues in `scala-library-sjs` + run: ./project/scripts/sbt scala-library-sjs/mimaReportBinaryIssues + ################################################################################################# ########################################### TEST JOBS ########################################### ################################################################################################# @@ -499,3 +517,20 @@ jobs: - uses: sbt/setup-sbt@v1 - name: Test `tasty-core-bootstrapped` run: ./project/scripts/sbt tasty-core-bootstrapped-new/test + + test-scala-js: + runs-on: ubuntu-latest + needs: [scala3-compiler-bootstrapped, tasty-core-bootstrapped, scala3-staging, scala3-tasty-inspector, scala-library-sjs] + steps: + - name: Git Checkout + uses: actions/checkout@v5 + + - name: Set up JDK 17 + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: 17 + cache: 'sbt' + - uses: sbt/setup-sbt@v1 + - name: Test `tasty-core-bootstrapped` + run: ./project/scripts/sbt sjsCompilerTests/test \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index 96f720cd4e0c..2949887d2acb 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -32,7 +32,9 @@ object SourceLanguage: SourceLanguage.Java // Scala 2 methods don't have Inline set, except for the ones injected with `patchStdlibClass` // which are really Scala 3 methods. - else if denot.isClass && denot.is(Scala2x) || (denot.maybeOwner.lastKnownDenotation.is(Scala2x) && !denot.is(Inline)) then + else if denot.isClass && denot.is(Scala2x) + || (denot.maybeOwner.lastKnownDenotation.is(Scala2x) && !denot.is(Inline)) + || denot.is(Param) && denot.maybeOwner.is(Method) && denot.maybeOwner.maybeOwner.lastKnownDenotation.is(Scala2x) then SourceLanguage.Scala2 else SourceLanguage.Scala3 diff --git a/compiler/test/dotty/Properties.scala b/compiler/test/dotty/Properties.scala index 8006c515039a..9b2dc22faba1 100644 --- a/compiler/test/dotty/Properties.scala +++ b/compiler/test/dotty/Properties.scala @@ -57,9 +57,6 @@ object Properties { /** dotty-interfaces jar */ def dottyInterfaces: String = sys.props("dotty.tests.classes.dottyInterfaces") - /** dotty-library-js jar */ - def dottyLibraryJS: String = sys.props("dotty.tests.classes.dottyLibraryJS") - /** dotty-compiler jar */ def dottyCompiler: String = sys.props("dotty.tests.classes.dottyCompiler") diff --git a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala index ff589c953c23..1f31045662b8 100644 --- a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala +++ b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala @@ -48,7 +48,6 @@ object TestConfiguration { Properties.scalaJSJavalib, Properties.scalaJSScalalib, Properties.scalaJSLibrary, - Properties.dottyLibraryJS )) def mkClasspath(classpaths: List[String]): String = diff --git a/library-js/src/scala/App.scala b/library-js/src/scala/App.scala index bbba62bbf350..3b4f51267268 100644 --- a/library-js/src/scala/App.scala +++ b/library-js/src/scala/App.scala @@ -12,6 +12,8 @@ package scala +import scala.language.`2.13` + import java.lang.System.{currentTimeMillis => currentTime} import scala.collection.mutable.ListBuffer diff --git a/library-js/src/scala/Array.scala b/library-js/src/scala/Array.scala index a71624a2081e..7810a5c5a6c1 100644 --- a/library-js/src/scala/Array.scala +++ b/library-js/src/scala/Array.scala @@ -12,6 +12,8 @@ package scala +import scala.language.`2.13` + import language.experimental.captureChecking //import scala.collection.generic._ diff --git a/library-js/src/scala/Console.scala b/library-js/src/scala/Console.scala index aa4798400792..7eb19b1012ac 100644 --- a/library-js/src/scala/Console.scala +++ b/library-js/src/scala/Console.scala @@ -12,6 +12,8 @@ package scala +import scala.language.`2.13` + import java.io.{ BufferedReader, InputStream, InputStreamReader, OutputStream, PrintStream, Reader } import scala.io.AnsiColor import scala.util.DynamicVariable diff --git a/library-js/src/scala/Enumeration.scala b/library-js/src/scala/Enumeration.scala index d2d379245d96..94aec25a60f2 100644 --- a/library-js/src/scala/Enumeration.scala +++ b/library-js/src/scala/Enumeration.scala @@ -12,6 +12,8 @@ package scala +import scala.language.`2.13` + import scala.collection.{SpecificIterableFactory, StrictOptimizedIterableOps, View, immutable, mutable} import java.lang.reflect.{Field => JField, Method => JMethod} diff --git a/library-js/src/scala/Symbol.scala b/library-js/src/scala/Symbol.scala index d656129ae2b3..2d9ac33c8480 100644 --- a/library-js/src/scala/Symbol.scala +++ b/library-js/src/scala/Symbol.scala @@ -12,6 +12,8 @@ package scala +import scala.language.`2.13` + import scala.scalajs.js /** This class provides a simple way to get unique objects for equal strings. @@ -37,15 +39,14 @@ final class Symbol private (val name: String) extends Serializable { override def equals(other: Any) = this eq other.asInstanceOf[AnyRef] } -// Modified to use Scala.js specific cache -object Symbol extends JSUniquenessCache[Symbol] { +object Symbol extends UniquenessCache[String, Symbol] { override def apply(name: String): Symbol = super.apply(name) protected def valueFromKey(name: String): Symbol = new Symbol(name) protected def keyFromValue(sym: Symbol): Option[String] = Some(sym.name) } -private[scala] abstract class JSUniquenessCache[V] -{ +// Modified to use Scala.js specific cache +private[scala] abstract class UniquenessCache[K, V >: Null] { private val cache = js.Dictionary.empty[V] protected def valueFromKey(k: String): V @@ -55,59 +56,4 @@ private[scala] abstract class JSUniquenessCache[V] cache.getOrElseUpdate(name, valueFromKey(name)) def unapply(other: V): Option[String] = keyFromValue(other) -} - -/** This is private so it won't appear in the library API, but - * abstracted to offer some hope of reusability. */ -/* DELETED for Scala.js -private[scala] abstract class UniquenessCache[K >: js.String, V >: Null] -{ - - import java.lang.ref.WeakReference - import java.util.WeakHashMap - import java.util.concurrent.locks.ReentrantReadWriteLock - - private[this] val rwl = new ReentrantReadWriteLock() - private[this] val rlock = rwl.readLock - private[this] val wlock = rwl.writeLock - private[this] val map = new WeakHashMap[K, WeakReference[V]] - - protected def valueFromKey(k: K): V - protected def keyFromValue(v: V): Option[K] - - def apply(name: K): V = { - def cached(): V = { - rlock.lock - try { - val reference = map get name - if (reference == null) null - else reference.get // will be null if we were gc-ed - } - finally rlock.unlock - } - def updateCache(): V = { - wlock.lock - try { - val res = cached() - if (res != null) res - else { - // If we don't remove the old String key from the map, we can - // wind up with one String as the key and a different String as - // the name field in the Symbol, which can lead to surprising GC - // behavior and duplicate Symbols. See scala/bug#6706. - map remove name - val sym = valueFromKey(name) - map.put(name, new WeakReference(sym)) - sym - } - } - finally wlock.unlock - } - - val res = cached() - if (res == null) updateCache() - else res - } - def unapply(other: V): Option[K] = keyFromValue(other) -} -*/ +} \ No newline at end of file diff --git a/library-js/src/scala/collection/immutable/NumericRange.scala b/library-js/src/scala/collection/immutable/NumericRange.scala index c12e85e5e349..7c1d408e8287 100644 --- a/library-js/src/scala/collection/immutable/NumericRange.scala +++ b/library-js/src/scala/collection/immutable/NumericRange.scala @@ -12,6 +12,8 @@ package scala.collection.immutable +import scala.language.`2.13` + import scala.collection.Stepper.EfficientSplit import scala.collection.{AbstractIterator, AnyStepper, IterableFactoryDefaults, Iterator, Stepper, StepperShape} diff --git a/library-js/src/scala/collection/immutable/Range.scala b/library-js/src/scala/collection/immutable/Range.scala index 310c45c07918..d15039209070 100644 --- a/library-js/src/scala/collection/immutable/Range.scala +++ b/library-js/src/scala/collection/immutable/Range.scala @@ -13,6 +13,8 @@ package scala package collection.immutable +import scala.language.`2.13` + import scala.collection.Stepper.EfficientSplit import scala.collection.convert.impl.RangeStepper import scala.collection.{AbstractIterator, AnyStepper, IterableFactoryDefaults, Iterator, Stepper, StepperShape} diff --git a/library-js/src/scala/collection/mutable/ArrayBuilder.scala b/library-js/src/scala/collection/mutable/ArrayBuilder.scala index 531a6438a2f1..4a6f81502474 100644 --- a/library-js/src/scala/collection/mutable/ArrayBuilder.scala +++ b/library-js/src/scala/collection/mutable/ArrayBuilder.scala @@ -13,6 +13,8 @@ package scala.collection package mutable +import scala.language.`2.13` + import scala.reflect.ClassTag import scala.runtime.BoxedUnit diff --git a/library-js/src/scala/collection/mutable/Buffer.scala b/library-js/src/scala/collection/mutable/Buffer.scala index b08e6d6506a6..73a88d24377f 100644 --- a/library-js/src/scala/collection/mutable/Buffer.scala +++ b/library-js/src/scala/collection/mutable/Buffer.scala @@ -13,6 +13,8 @@ package scala.collection package mutable +import scala.language.`2.13` + import scala.scalajs.js /** A `Buffer` is a growable and shrinkable `Seq`. */ diff --git a/library-js/src/scala/concurrent/ExecutionContext.scala b/library-js/src/scala/concurrent/ExecutionContext.scala index 38582321cccd..729be2163ece 100644 --- a/library-js/src/scala/concurrent/ExecutionContext.scala +++ b/library-js/src/scala/concurrent/ExecutionContext.scala @@ -12,6 +12,7 @@ package scala.concurrent +import scala.language.`2.13` import java.util.concurrent.{ ExecutorService, Executor } import scala.annotation.implicitNotFound diff --git a/library-js/src/scala/math/ScalaNumber.scala b/library-js/src/scala/math/ScalaNumber.scala index 811346d2f869..e16467e42cb7 100644 --- a/library-js/src/scala/math/ScalaNumber.scala +++ b/library-js/src/scala/math/ScalaNumber.scala @@ -10,6 +10,8 @@ package scala.math +import scala.language.`2.13` + /** A marker class for Number types introduced by Scala * @author Martin Odersky, Paul Phillips * @version 2.8 diff --git a/library-js/src/scala/package.scala b/library-js/src/scala/package.scala index c9f1fdf8314e..9ced6a30f81c 100644 --- a/library-js/src/scala/package.scala +++ b/library-js/src/scala/package.scala @@ -12,6 +12,8 @@ import scala.annotation.migration +import scala.language.`2.13` + /** * Core Scala types. They are always available without an explicit import. * @contentDiagram hideNodes "scala.Serializable" diff --git a/library-js/src/scala/reflect/ClassTag.scala b/library-js/src/scala/reflect/ClassTag.scala index a66a1a6a8e34..c28180be00d2 100644 --- a/library-js/src/scala/reflect/ClassTag.scala +++ b/library-js/src/scala/reflect/ClassTag.scala @@ -13,6 +13,8 @@ package scala package reflect +import scala.language.`2.13` + import scala.annotation.unchecked.uncheckedStable import java.lang.{ Class => jClass } diff --git a/library-js/src/scala/reflect/Manifest.scala b/library-js/src/scala/reflect/Manifest.scala index faa2fe6f6e5e..d6263402aabc 100644 --- a/library-js/src/scala/reflect/Manifest.scala +++ b/library-js/src/scala/reflect/Manifest.scala @@ -13,6 +13,8 @@ package scala package reflect +import scala.language.`2.13` + import scala.collection.mutable.{ArrayBuilder, ArraySeq} /** A `Manifest[T]` is an opaque descriptor for type T. Its supported use diff --git a/library-js/src/scala/runtime/BoxesRunTime.scala b/library-js/src/scala/runtime/BoxesRunTime.scala index 48412eb77846..ec723d2a99c9 100644 --- a/library-js/src/scala/runtime/BoxesRunTime.scala +++ b/library-js/src/scala/runtime/BoxesRunTime.scala @@ -1,5 +1,7 @@ package scala.runtime +import scala.language.`2.13` + import scala.math.ScalaNumber /* The declaration of the class is only to make the JVM back-end happy when diff --git a/library-js/src/scala/runtime/ScalaRunTime.scala b/library-js/src/scala/runtime/ScalaRunTime.scala index 6e3803675608..4247002cce6b 100644 --- a/library-js/src/scala/runtime/ScalaRunTime.scala +++ b/library-js/src/scala/runtime/ScalaRunTime.scala @@ -13,6 +13,8 @@ package scala package runtime +import scala.language.`2.13` + import scala.collection.{AbstractIterator, AnyConstr, SortedOps, StrictOptimizedIterableOps, StringOps, StringView, View} import scala.collection.immutable.{ArraySeq, NumericRange} import scala.collection.mutable.StringBuilder diff --git a/library-js/src/scala/util/DynamicVariable.scala b/library-js/src/scala/util/DynamicVariable.scala index b3eb4048499d..4c531f1ecb99 100644 --- a/library-js/src/scala/util/DynamicVariable.scala +++ b/library-js/src/scala/util/DynamicVariable.scala @@ -13,6 +13,8 @@ package scala package util +import scala.language.`2.13` + import java.lang.InheritableThreadLocal /** `DynamicVariables` provide a binding mechanism where the current diff --git a/library-js/src/scala/util/control/NoStackTrace.scala b/library-js/src/scala/util/control/NoStackTrace.scala index 046abf2fd830..e6023f3738c7 100644 --- a/library-js/src/scala/util/control/NoStackTrace.scala +++ b/library-js/src/scala/util/control/NoStackTrace.scala @@ -13,6 +13,8 @@ package scala package util.control +import scala.language.`2.13` + /** A trait for exceptions which, for efficiency reasons, do not * fill in the stack trace. Stack trace suppression can be disabled * on a global basis via a system property wrapper in diff --git a/project/Build.scala b/project/Build.scala index 0ec8f69698b5..51b1953eae4e 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -23,6 +23,7 @@ import sbt.PublishBinPlugin.autoImport._ import dotty.tools.sbtplugin.RepublishPlugin import dotty.tools.sbtplugin.RepublishPlugin.autoImport._ import dotty.tools.sbtplugin.ScalaLibraryPlugin +import dotty.tools.sbtplugin.ScalaLibraryPlugin.autoImport._ import dotty.tools.sbtplugin.DottyJSPlugin import dotty.tools.sbtplugin.DottyJSPlugin.autoImport._ @@ -1646,6 +1647,8 @@ object Build { mimaForwardIssueFilters := MiMaFilters.Scala3Library.ForwardsBreakingChanges, mimaBackwardIssueFilters := MiMaFilters.Scala3Library.BackwardsBreakingChanges, customMimaReportBinaryIssues("MiMaFilters.Scala3Library"), + // Should we also patch .sjsir files + keepSJSIR := false, ) /* Configuration of the org.scala-lang:scala3-library_3:*.**.**-nonbootstrapped project */ @@ -1768,6 +1771,8 @@ object Build { mimaForwardIssueFilters := MiMaFilters.Scala3Library.ForwardsBreakingChanges, mimaBackwardIssueFilters := MiMaFilters.Scala3Library.BackwardsBreakingChanges, customMimaReportBinaryIssues("MiMaFilters.Scala3Library"), + // Should we also patch .sjsir files + keepSJSIR := false, ) /* Configuration of the org.scala-lang:scala3-library_3:*.**.**-bootstrapped project */ @@ -1816,6 +1821,7 @@ object Build { // We add a dependency to the JVM library to have the classfile available // (as they are not part of this artifact) .dependsOn(`scala3-library-bootstrapped-new`) + .enablePlugins(ScalaLibraryPlugin, DottyJSPlugin) .settings(publishSettings) .settings( name := "scala-library-sjs", @@ -1864,7 +1870,9 @@ object Build { )) .flatMap(_.relativeTo(baseDirectory.value / "src")).toSet - files.filterNot(file => + files.filterNot(_.getPath().contains("BoxesRunTime.scala")) + .filterNot(_.getPath().contains("ScalaNumber.scala")) + .filterNot(file => file.relativeTo((`scala-library-bootstrapped` / baseDirectory).value / "src") .exists(overwrittenSources.contains)) @@ -1922,6 +1930,18 @@ object Build { } }).transform(node).head }, + // Add configuration for MiMa + mimaCheckDirection := (compatMode match { + case CompatMode.BinaryCompatible => "backward" + case CompatMode.SourceAndBinaryCompatible => "both" + }), + mimaExcludeAnnotations += "scala.annotation.experimental", + mimaPreviousArtifacts += ("org.scala-js" % "fat-stdlib_sjs1" % "3.7.3"), + mimaForwardIssueFilters := MiMaFilters.Scala3Library.ForwardsBreakingChanges, + mimaBackwardIssueFilters := MiMaFilters.Scala3Library.BackwardsBreakingChanges, + customMimaReportBinaryIssues("MiMaFilters.Scala3Library"), + // Should we also patch .sjsir files + keepSJSIR := true, ) /* Configuration of the org.scala-lang:scala3-library_sjs1_3:*.**.**-bootstrapped project */ @@ -2442,6 +2462,7 @@ object Build { s"-Ddotty.tests.classes.tastyCore=${(`tasty-core-bootstrapped-new` / Compile / packageBin).value}", s"-Ddotty.tests.classes.compilerInterface=${findArtifactPath(externalDeps, "compiler-interface")}", s"-Ddotty.tests.classes.scalaLibrary=${(`scala-library-bootstrapped` / Compile / packageBin).value}", + s"-Ddotty.tests.classes.scalaJSScalalib=${(`scala-library-sjs` / Compile / packageBin).value}", s"-Ddotty.tests.classes.scalaAsm=${findArtifactPath(externalDeps, "scala-asm")}", s"-Ddotty.tests.classes.jlineTerminal=${findArtifactPath(externalDeps, "jline-terminal")}", s"-Ddotty.tests.classes.jlineReader=${findArtifactPath(externalDeps, "jline-reader")}", @@ -2979,10 +3000,15 @@ object Build { ) lazy val sjsCompilerTests = project.in(file("sjs-compiler-tests")). - dependsOn(`scala3-compiler` % "test->test"). + dependsOn(`scala3-compiler-bootstrapped-new` % "test->test"). settings( - commonNonBootstrappedSettings, - + (Compile / scalaSource) := baseDirectory.value / "src", + (Test / scalaSource) := baseDirectory.value / "test", + (Compile / javaSource) := baseDirectory.value / "src", + (Test / javaSource) := baseDirectory.value / "test", + (Compile / resourceDirectory) := baseDirectory.value / "resources", + (Test / resourceDirectory) := baseDirectory.value / "test-resources", + scalaVersion := (`scala3-compiler-bootstrapped-new` / scalaVersion).value, libraryDependencies ++= Seq( "org.scala-js" %% "scalajs-linker" % scalaJSVersion % Test cross CrossVersion.for3Use2_13, "org.scala-js" %% "scalajs-env-nodejs" % "1.3.0" % Test cross CrossVersion.for3Use2_13, @@ -2991,18 +3017,63 @@ object Build { // Change the baseDirectory when running the tests Test / baseDirectory := baseDirectory.value.getParentFile, - javaOptions ++= (`scala3-compiler` / javaOptions).value, + javaOptions ++= (`scala3-compiler-bootstrapped-new` / javaOptions).value, javaOptions ++= { - val externalJSDeps = (`scala3-library-bootstrappedJS` / Compile / externalDependencyClasspath).value - val dottyLibraryJSJar = (`scala3-library-bootstrappedJS` / Compile / packageBin).value.getAbsolutePath + val externalJSDeps = (`scala-library-sjs` / Compile / externalDependencyClasspath).value + + val managedSrcDir = { + // Populate the directory + (`scala3-compiler-bootstrapped-new` / Compile / managedSources).value + + (`scala3-compiler-bootstrapped-new` / Compile / sourceManaged).value + } + + val externalDeps = (`scala3-compiler-bootstrapped-new` / Runtime / externalDependencyClasspath).value Seq( - "-Ddotty.tests.classes.dottyLibraryJS=" + dottyLibraryJSJar, + s"-Ddotty.tests.dottyCompilerManagedSources=${managedSrcDir}", + s"-Ddotty.tests.classes.dottyInterfaces=${(`scala3-interfaces` / Compile / packageBin).value}", + s"-Ddotty.tests.classes.dottyCompiler=${(ThisProject / Compile / packageBin).value}", + s"-Ddotty.tests.classes.tastyCore=${(`tasty-core-nonbootstrapped` / Compile / packageBin).value}", + s"-Ddotty.tests.classes.compilerInterface=${findArtifactPath(externalDeps, "compiler-interface")}", + s"-Ddotty.tests.classes.scalaLibrary=${(`scala-library-nonbootstrapped` / Compile / packageBin).value}", + s"-Ddotty.tests.classes.scalaAsm=${findArtifactPath(externalDeps, "scala-asm")}", + s"-Ddotty.tests.classes.jlineTerminal=${findArtifactPath(externalDeps, "jline-terminal")}", + s"-Ddotty.tests.classes.jlineReader=${findArtifactPath(externalDeps, "jline-reader")}", + s"-Ddotty.tools.dotc.semanticdb.test=${(ThisBuild / baseDirectory).value/"tests"/"semanticdb"}", + "-Ddotty.tests.classes.scalaJSScalalib=" + (`scala-library-sjs` / Compile / packageBin).value, "-Ddotty.tests.classes.scalaJSJavalib=" + findArtifactPath(externalJSDeps, "scalajs-javalib"), - "-Ddotty.tests.classes.scalaJSScalalib=" + findArtifactPath(externalJSDeps, "scalajs-scalalib_2.13"), "-Ddotty.tests.classes.scalaJSLibrary=" + findArtifactPath(externalJSDeps, "scalajs-library_2.13"), ) }, + // Configure to use the non-bootstrapped compiler + managedScalaInstance := false, + scalaInstance := { + val externalCompilerDeps = (`scala3-compiler-nonbootstrapped` / Compile / externalDependencyClasspath).value.map(_.data).toSet + + // IMPORTANT: We need to use actual jars to form the ScalaInstance and not + // just directories containing classfiles because sbt maintains a cache of + // compiler instances. This cache is invalidated based on timestamps + // however this is only implemented on jars, directories are never + // invalidated. + val tastyCore = (`tasty-core-nonbootstrapped` / Compile / packageBin).value + val scalaLibrary = (`scala-library-nonbootstrapped` / Compile / packageBin).value + val scala3Interfaces = (`scala3-interfaces` / Compile / packageBin).value + val scala3Compiler = (`scala3-compiler-nonbootstrapped` / Compile / packageBin).value + + Defaults.makeScalaInstance( + dottyNonBootstrappedVersion, + libraryJars = Array(scalaLibrary), + allCompilerJars = Seq(tastyCore, scala3Interfaces, scala3Compiler) ++ externalCompilerDeps, + allDocJars = Seq.empty, + state.value, + scalaInstanceTopLoader.value + ) + }, + scalaCompilerBridgeBinaryJar := { + Some((`scala3-sbt-bridge-nonbootstrapped` / Compile / packageBin).value) + }, + Test / forkOptions := (Test / forkOptions).value.withWorkingDirectory((ThisBuild / baseDirectory).value), ) lazy val `scala3-bench` = project.in(file("bench")).asDottyBench(NonBootstrapped) diff --git a/project/ScalaLibraryPlugin.scala b/project/ScalaLibraryPlugin.scala index c829935005fe..bbc5db0fa5db 100644 --- a/project/ScalaLibraryPlugin.scala +++ b/project/ScalaLibraryPlugin.scala @@ -14,76 +14,47 @@ object ScalaLibraryPlugin extends AutoPlugin { private val scala2Version = "2.13.16" - val fetchScala2ClassFiles = taskKey[(Set[File], File)]("Fetch the files to use that were compiled with Scala 2") - val fetchScala2SJSIR = taskKey[(Set[File], File)]("Fetch the .sjsir to use from Scala 2") + object autoImport { + val keepSJSIR = settingKey[Boolean]("Should we patch .sjsir too?") + } - override def projectSettings = Seq ( - fetchScala2ClassFiles := { - val stream = streams.value - val cache = stream.cacheDirectory - val target = cache / "scala-library-classes" - val report = update.value - - val scalaLibraryBinaryJar = report.select( - configuration = configurationFilter(), - module = (_: ModuleID).name == "scala-library", - artifact = artifactFilter(`type` = "jar")).headOption.getOrElse { - sys.error(s"Could not fetch scala-library binary JAR") - } + import autoImport._ - if (!target.exists()) { - IO.createDirectory(target) - } - - (FileFunction.cached(cache / "fetch-scala-library-classes", FilesInfo.lastModified, FilesInfo.exists) { _ => - stream.log.info(s"Unpacking scala-library binaries to persistent directory: ${target.getAbsolutePath}") - IO.unzip(scalaLibraryBinaryJar, target) - (target ** "*.class").get.toSet - } (Set(scalaLibraryBinaryJar)), target) - - }, - fetchScala2SJSIR := { + override def projectSettings = Seq ( + (Compile / manipulateBytecode) := { val stream = streams.value + val target = (Compile / classDirectory).value val lm = dependencyResolution.value val log = stream.log val cache = stream.cacheDirectory val retrieveDir = cache / "scalajs-scalalib" / scalaVersion.value + val comp = lm.retrieve("org.scala-js" % "scalajs-scalalib_2.13" % s"$scala2Version+$scalaJSVersion", scalaModuleInfo = None, retrieveDir, log) .fold(w => throw w.resolveException, identity) + .filterNot(_.getPath().contains("javalib")) + .filter(!_.getPath().contains("scalajs-scalalib_2.13") || keepSJSIR.value) + .distinct - println(comp(0)) - - val target = cache / "scala-library-sjsir" - - - if (!target.exists()) { - IO.createDirectory(target) - } - - (FileFunction.cached(cache / "fetch-scala-library-sjsir", FilesInfo.lastModified, FilesInfo.exists) { _ => - stream.log.info(s"Unpacking scalajs-scalalib binaries to persistent directory: ${target.getAbsolutePath}") - IO.unzip(comp(0), target) - (target ** "*.sjsir").get.toSet - } (Set(comp(0))), target) + // Fetch classfiles and sjsir files + val patches: Seq[(Set[File], File)] = comp.map(fetch(stream, _)) - }, - (Compile / manipulateBytecode) := { - val stream = streams.value - val target = (Compile / classDirectory).value - val (files, reference) = fetchScala2ClassFiles.value; val previous = (Compile / manipulateBytecode).value + val analysis = previous.analysis match { case analysis: sbt.internal.inc.Analysis => analysis case _ => sys.error("Unexpected analysis type") } - var stamps = analysis.stamps - for (file <- files; - id <- file.relativeTo(reference); - if filesToCopy(id.toString().replace("\\", "/")); // Only Override Some Very Specific Files - dest = target / (id.toString); - ref <- dest.relativeTo((LocalRootProject / baseDirectory).value) - ) { + + // Patch the files that are in the list + for { + (files, reference) <- patches + file <- files + id <- file.relativeTo(reference) + if filesToCopy(id.toString().replace("\\", "/")) // Only Override Some Very Specific Files + dest = target / (id.toString) + ref <- dest.relativeTo((LocalRootProject / baseDirectory).value) + } { // Copy the files to the classDirectory IO.copyFile(file, dest) // Update the timestamp in the analysis @@ -92,6 +63,7 @@ object ScalaLibraryPlugin extends AutoPlugin { Stamper.forFarmHashP(dest.toPath())) } + val overwrittenBinaries = Files.walk((Compile / classDirectory).value.toPath()) .iterator() .asScala @@ -99,57 +71,75 @@ object ScalaLibraryPlugin extends AutoPlugin { .map(_.relativeTo((Compile / classDirectory).value).get) .toSet - val diff = files.filterNot(_.relativeTo(reference).exists(overwrittenBinaries)) - - // Copy all the specialized classes in the stdlib - // no need to update any stamps as these classes exist nowhere in the analysis - for (orig <- diff; dest <- orig.relativeTo(reference)) { - IO.copyFile(orig, ((Compile / classDirectory).value / dest.toString())) + for ((files, reference) <- patches) { + val diff = files.filterNot(file => overwrittenBinaries.contains(file.relativeTo(reference).get)) + // Copy all the specialized classes in the stdlib + // no need to update any stamps as these classes exist nowhere in the analysis + for (orig <- diff; dest <- orig.relativeTo(reference)) { + IO.copyFile(orig, ((Compile / classDirectory).value / dest.toString())) + } } previous .withAnalysis(analysis.copy(stamps = stamps)) // update the analysis with the correct stamps .withHasModified(true) // mark it as updated for sbt to update its caches + } ) + def fetch(stream: TaskStreams, jar: File) = { + val cache = stream.cacheDirectory + val target = cache / jar.getName() + + if (!target.exists()) { + IO.createDirectory(target) + } + + (FileFunction.cached(cache / "fetch-scala-library-classes", FilesInfo.lastModified, FilesInfo.exists) { _ => + stream.log.info(s"Unpacking scala-library binaries to persistent directory: ${target.getAbsolutePath}") + IO.unzip(jar, target) + (target ** "*.class").get.toSet ++ (target ** "*.sjsir").get.toSet + } (Set(jar)), target) + } + private lazy val filesToCopy = Set( - "scala/Tuple1.class", - "scala/Tuple2.class", - "scala/collection/DoubleStepper.class", - "scala/collection/IntStepper.class", - "scala/collection/LongStepper.class", - "scala/collection/immutable/DoubleVectorStepper.class", - "scala/collection/immutable/IntVectorStepper.class", - "scala/collection/immutable/LongVectorStepper.class", - "scala/jdk/DoubleAccumulator.class", - "scala/jdk/IntAccumulator.class", - "scala/jdk/LongAccumulator.class", - "scala/jdk/FunctionWrappers$FromJavaDoubleBinaryOperator.class", - "scala/jdk/FunctionWrappers$FromJavaBooleanSupplier.class", - "scala/jdk/FunctionWrappers$FromJavaDoubleConsumer.class", - "scala/jdk/FunctionWrappers$FromJavaDoublePredicate.class", - "scala/jdk/FunctionWrappers$FromJavaDoubleSupplier.class", - "scala/jdk/FunctionWrappers$FromJavaDoubleToIntFunction.class", - "scala/jdk/FunctionWrappers$FromJavaDoubleToLongFunction.class", - "scala/jdk/FunctionWrappers$FromJavaIntBinaryOperator.class", - "scala/jdk/FunctionWrappers$FromJavaDoubleUnaryOperator.class", - "scala/jdk/FunctionWrappers$FromJavaIntPredicate.class", - "scala/jdk/FunctionWrappers$FromJavaIntConsumer.class", - "scala/jdk/FunctionWrappers$FromJavaIntSupplier.class", - "scala/jdk/FunctionWrappers$FromJavaIntToDoubleFunction.class", - "scala/jdk/FunctionWrappers$FromJavaIntToLongFunction.class", - "scala/jdk/FunctionWrappers$FromJavaIntUnaryOperator.class", - "scala/jdk/FunctionWrappers$FromJavaLongBinaryOperator.class", - "scala/jdk/FunctionWrappers$FromJavaLongConsumer.class", - "scala/jdk/FunctionWrappers$FromJavaLongPredicate.class", - "scala/jdk/FunctionWrappers$FromJavaLongSupplier.class", - "scala/jdk/FunctionWrappers$FromJavaLongToDoubleFunction.class", - "scala/jdk/FunctionWrappers$FromJavaLongToIntFunction.class", - "scala/jdk/FunctionWrappers$FromJavaLongUnaryOperator.class", - "scala/collection/ArrayOps$ReverseIterator.class", - "scala/runtime/NonLocalReturnControl.class", - "scala/util/Sorting.class", "scala/util/Sorting$.class", // Contains @specialized annotation - ) + "scala/Tuple1", + "scala/Tuple2", + "scala/collection/DoubleStepper", + "scala/collection/IntStepper", + "scala/collection/LongStepper", + "scala/collection/immutable/DoubleVectorStepper", + "scala/collection/immutable/IntVectorStepper", + "scala/collection/immutable/LongVectorStepper", + "scala/collection/immutable/Range", "scala/collection/immutable/Range$", + "scala/jdk/DoubleAccumulator", + "scala/jdk/IntAccumulator", + "scala/jdk/LongAccumulator", + "scala/jdk/FunctionWrappers$FromJavaDoubleBinaryOperator", + "scala/jdk/FunctionWrappers$FromJavaBooleanSupplier", + "scala/jdk/FunctionWrappers$FromJavaDoubleConsumer", + "scala/jdk/FunctionWrappers$FromJavaDoublePredicate", + "scala/jdk/FunctionWrappers$FromJavaDoubleSupplier", + "scala/jdk/FunctionWrappers$FromJavaDoubleToIntFunction", + "scala/jdk/FunctionWrappers$FromJavaDoubleToLongFunction", + "scala/jdk/FunctionWrappers$FromJavaIntBinaryOperator", + "scala/jdk/FunctionWrappers$FromJavaDoubleUnaryOperator", + "scala/jdk/FunctionWrappers$FromJavaIntPredicate", + "scala/jdk/FunctionWrappers$FromJavaIntConsumer", + "scala/jdk/FunctionWrappers$FromJavaIntSupplier", + "scala/jdk/FunctionWrappers$FromJavaIntToDoubleFunction", + "scala/jdk/FunctionWrappers$FromJavaIntToLongFunction", + "scala/jdk/FunctionWrappers$FromJavaIntUnaryOperator", + "scala/jdk/FunctionWrappers$FromJavaLongBinaryOperator", + "scala/jdk/FunctionWrappers$FromJavaLongConsumer", + "scala/jdk/FunctionWrappers$FromJavaLongPredicate", + "scala/jdk/FunctionWrappers$FromJavaLongSupplier", + "scala/jdk/FunctionWrappers$FromJavaLongToDoubleFunction", + "scala/jdk/FunctionWrappers$FromJavaLongToIntFunction", + "scala/jdk/FunctionWrappers$FromJavaLongUnaryOperator", + "scala/collection/ArrayOps$ReverseIterator", + "scala/runtime/NonLocalReturnControl", + "scala/util/Sorting", "scala/util/Sorting$", + ).flatMap(f => Seq(s"$f.class", s"$f.sjsir")) } diff --git a/sjs-compiler-tests/test/scala/dotty/tools/dotc/ScalaJSCompilationTests.scala b/sjs-compiler-tests/test/scala/dotty/tools/dotc/ScalaJSCompilationTests.scala index 55c8693715d8..fe9136635fd4 100644 --- a/sjs-compiler-tests/test/scala/dotty/tools/dotc/ScalaJSCompilationTests.scala +++ b/sjs-compiler-tests/test/scala/dotty/tools/dotc/ScalaJSCompilationTests.scala @@ -10,7 +10,6 @@ import reporting.TestReporter import vulpix._ import org.junit.Ignore -@Ignore @Category(Array(classOf[ScalaJSCompilationTests])) class ScalaJSCompilationTests { import ParallelTesting._ diff --git a/tests/neg-scalajs/js-native-members.check b/tests/neg-scalajs/js-native-members.check index 60990cbf3d97..1dbb9fef596e 100644 --- a/tests/neg-scalajs/js-native-members.check +++ b/tests/neg-scalajs/js-native-members.check @@ -1,38 +1,38 @@ --- Warning: tests/neg-scalajs/js-native-members.scala:24:16 ------------------------------------------------------------ +-- Warning: tests/neg-scalajs/js-native-members.scala:24:9 ------------------------------------------------------------- 24 | private[this] def this(x: Int) = this() // ok - | ^ - | Ignoring [this] qualifier. - | This syntax will be deprecated in the future; it should be dropped. - | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html - | This construct can be rewritten automatically under -rewrite -source 3.4-migration. --- Warning: tests/neg-scalajs/js-native-members.scala:28:16 ------------------------------------------------------------ + | ^^^^^^ + | Ignoring [this] qualifier. + | The syntax `private[this]` will be deprecated in the future; just write `private` instead. + | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html + | This construct can be rewritten automatically under -rewrite -source 3.4-migration. +-- Warning: tests/neg-scalajs/js-native-members.scala:28:9 ------------------------------------------------------------- 28 | private[this] val a: Int = js.native // error - | ^ - | Ignoring [this] qualifier. - | This syntax will be deprecated in the future; it should be dropped. - | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html - | This construct can be rewritten automatically under -rewrite -source 3.4-migration. --- Warning: tests/neg-scalajs/js-native-members.scala:32:16 ------------------------------------------------------------ + | ^^^^^^ + | Ignoring [this] qualifier. + | The syntax `private[this]` will be deprecated in the future; just write `private` instead. + | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html + | This construct can be rewritten automatically under -rewrite -source 3.4-migration. +-- Warning: tests/neg-scalajs/js-native-members.scala:32:9 ------------------------------------------------------------- 32 | private[this] var d: Int = js.native // error - | ^ - | Ignoring [this] qualifier. - | This syntax will be deprecated in the future; it should be dropped. - | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html - | This construct can be rewritten automatically under -rewrite -source 3.4-migration. --- Warning: tests/neg-scalajs/js-native-members.scala:36:16 ------------------------------------------------------------ + | ^^^^^^ + | Ignoring [this] qualifier. + | The syntax `private[this]` will be deprecated in the future; just write `private` instead. + | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html + | This construct can be rewritten automatically under -rewrite -source 3.4-migration. +-- Warning: tests/neg-scalajs/js-native-members.scala:36:9 ------------------------------------------------------------- 36 | private[this] def g(): Int = js.native // error - | ^ - | Ignoring [this] qualifier. - | This syntax will be deprecated in the future; it should be dropped. - | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html - | This construct can be rewritten automatically under -rewrite -source 3.4-migration. --- Warning: tests/neg-scalajs/js-native-members.scala:49:25 ------------------------------------------------------------ + | ^^^^^^ + | Ignoring [this] qualifier. + | The syntax `private[this]` will be deprecated in the future; just write `private` instead. + | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html + | This construct can be rewritten automatically under -rewrite -source 3.4-migration. +-- Warning: tests/neg-scalajs/js-native-members.scala:49:18 ------------------------------------------------------------ 49 | class X3 private[this] () extends js.Object { // ok - | ^ - | Ignoring [this] qualifier. - | This syntax will be deprecated in the future; it should be dropped. - | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html - | This construct can be rewritten automatically under -rewrite -source 3.4-migration. + | ^^^^^^ + | Ignoring [this] qualifier. + | The syntax `private[this]` will be deprecated in the future; just write `private` instead. + | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html + | This construct can be rewritten automatically under -rewrite -source 3.4-migration. -- [E003] Syntax Warning: tests/neg-scalajs/js-native-members.scala:58:44 ---------------------------------------------- 58 | def assign[T, U](target: T, source: U): T with U = js.native // ok | ^^^^ diff --git a/tests/neg-scalajs/js-non-native-members-qualified-private.check b/tests/neg-scalajs/js-non-native-members-qualified-private.check index 6befabb7a9c0..fdab95772224 100644 --- a/tests/neg-scalajs/js-non-native-members-qualified-private.check +++ b/tests/neg-scalajs/js-non-native-members-qualified-private.check @@ -1,10 +1,10 @@ --- Warning: tests/neg-scalajs/js-non-native-members-qualified-private.scala:52:28 -------------------------------------- +-- Warning: tests/neg-scalajs/js-non-native-members-qualified-private.scala:52:21 -------------------------------------- 52 | class B private[this] () extends js.Object // ok - | ^ - | Ignoring [this] qualifier. - | This syntax will be deprecated in the future; it should be dropped. - | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html - | This construct can be rewritten automatically under -rewrite -source 3.4-migration. + | ^^^^^^ + | Ignoring [this] qualifier. + | The syntax `private[this]` will be deprecated in the future; just write `private` instead. + | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html + | This construct can be rewritten automatically under -rewrite -source 3.4-migration. -- Error: tests/neg-scalajs/js-non-native-members-qualified-private.scala:6:32 ----------------------------------------- 6 | private[Enclosing1] def foo(i: Int): Int = i // error | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/run/classTags.scala b/tests/run/classTags.scala index da8d9826ada1..1d8b61ec3d8a 100644 --- a/tests/run/classTags.scala +++ b/tests/run/classTags.scala @@ -1,3 +1,4 @@ +// scalajs: --skip --pending object Test { type T = String