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
Fix #2681: Module Splitting Support #4198
Conversation
At the moment, the overall diff is identical to #4111 |
68ec932
to
7846888
Compare
7846888
to
b743483
Compare
I'll probably have to go over this bits by bits ^^ By any chance, would you have some advice on in which order to read things in the big commit (Add Module Splitting support in the linker)? |
|
Thank you! That will be very helpful. :) |
I forgot about the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reviewed the steps 1 to 9 so far (including 6b for the Analyzer
). Overall this looks really excellent! I have very minor comments here and there, but nothing major.
linker/shared/src/main/scala/org/scalajs/linker/standard/ModuleSet.scala
Outdated
Show resolved
Hide resolved
linker/shared/src/main/scala/org/scalajs/linker/standard/ModuleSet.scala
Show resolved
Hide resolved
linker/shared/src/main/scala/org/scalajs/linker/frontend/modulesplitter/ModuleSplitter.scala
Outdated
Show resolved
Hide resolved
linker/shared/src/main/scala/org/scalajs/linker/frontend/modulesplitter/ModuleSplitter.scala
Outdated
Show resolved
Hide resolved
linker/shared/src/main/scala/org/scalajs/linker/frontend/modulesplitter/ModuleSplitter.scala
Outdated
Show resolved
Hide resolved
linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/VarGen.scala
Outdated
Show resolved
Hide resolved
linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/KnowledgeGuardian.scala
Show resolved
Hide resolved
linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/KnowledgeGuardian.scala
Outdated
Show resolved
Hide resolved
linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/FunctionEmitter.scala
Outdated
Show resolved
Hide resolved
linker/shared/src/main/scala/org/scalajs/linker/backend/OutputWriter.scala
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some more review until linker/jvm/src/test/scala/org/scalajs/linker/PathOutputDirectoryTest.scala
, excluded.
linker-interface/shared/src/main/scala/org/scalajs/linker/interface/Linker.scala
Outdated
Show resolved
Hide resolved
linker-interface/shared/src/main/scala/org/scalajs/linker/interface/Report.scala
Outdated
Show resolved
Hide resolved
linker-interface/shared/src/main/scala/org/scalajs/linker/interface/Report.scala
Outdated
Show resolved
Hide resolved
linker-interface/shared/src/main/scala/org/scalajs/linker/interface/Report.scala
Outdated
Show resolved
Hide resolved
linker-interface/shared/src/main/scala/org/scalajs/linker/interface/Report.scala
Outdated
Show resolved
Hide resolved
...erface/shared/src/main/scala/org/scalajs/linker/interface/unstable/OutputDirectoryImpl.scala
Outdated
Show resolved
Hide resolved
...erface/shared/src/main/scala/org/scalajs/linker/interface/unstable/OutputDirectoryImpl.scala
Outdated
Show resolved
Hide resolved
linker/js/src/main/scala/org/scalajs/linker/NodeOutputDirectory.scala
Outdated
Show resolved
Hide resolved
linker/jvm/src/main/scala/org/scalajs/linker/PathOutputDirectory.scala
Outdated
Show resolved
Hide resolved
linker/jvm/src/main/scala/org/scalajs/linker/PathOutputDirectory.scala
Outdated
Show resolved
Hide resolved
b743483
to
826b82e
Compare
I have addressed the first round of comments. All questions I have not answered in the review thread should be answered in code comments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And that's the end of the review for the big Linker commit.
linker/shared/src/main/scala/org/scalajs/linker/MemOutputDirectory.scala
Show resolved
Hide resolved
linker/shared/src/test/scala/org/scalajs/linker/LinkerTest.scala
Outdated
Show resolved
Hide resolved
826b82e
to
c8688c4
Compare
I forgot to mention: I also rebased on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed until ScalaJSPluginInternal.scala
(excluded) in the sbt plugin commit.
linker/shared/src/main/scala/org/scalajs/linker/standard/ModuleSet.scala
Outdated
Show resolved
Hide resolved
c8688c4
to
cf66437
Compare
@sjrd There is a subtle bug I have introduced when I moved I will attempt to fix the problem by making module initializers first class citizens in the Analyzer. This is unfortunate, but I'm not sure I see another option. |
I have added a commit fixing the bug and adding a regression test. |
36acddb
to
90a5f77
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All right, here is the end of the review, including the latest commit that fixes the module initializer issue.
There is one serious issue in ScalaJSPluginInternal
(there are a few comments that relate to the same thing), but otherwise it looks very good.
class MinModuleSplittingTest { | ||
import scala.concurrent.ExecutionContext.Implicits.global | ||
|
||
/** Smoke test to ensure modules do note get merged too much. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/** Smoke test to ensure modules do note get merged too much. */ | |
/** Smoke test to ensure modules do not get merged too much. */ |
@js.native | ||
private def basename(str: String): String = js.native | ||
object PromisesFS extends js.Object { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
object PromisesFS extends js.Object { | |
private object PromisesFS extends js.Object { |
@@ -1478,6 +1472,19 @@ class ExportsTest { | |||
} | |||
} | |||
|
|||
@Test def top_level_export_field_is_writiable_accross_modules(): Unit = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Test def top_level_export_field_is_writiable_accross_modules(): Unit = { | |
@Test def top_level_export_field_is_writable_accross_modules(): Unit = { |
@@ -122,6 +131,8 @@ private[sbtplugin] object ScalaJSPluginInternal { | |||
box.ensure(linkerImpl.clearableLinker(config)) | |||
}, | |||
|
|||
scalaJSLinker in legacyKey := (scalaJSLinker in key).value, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not right. It will silently break compatibility in ways that are hard to debug. Although it's a bit of a specialized use case, if a user had specified
scalaJSLinker in (Compile, fastOptJS) := something
that setting will now be ignored. IMO we should do the reverse. Set scalaJSLinker in legacyKey
first, then derive scalaJSLinker in key := (scalaJSLinker in legacyKey).value
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Writing to scalaJSLinker
is specified to be an unstable API, but fair enough, for consistency with everything else, we might as well do it.
@@ -141,6 +152,8 @@ private[sbtplugin] object ScalaJSPluginInternal { | |||
Tags.Tag(s"uses-scalajs-linker-$projectPart-$configPart-$stagePart") | |||
}, | |||
|
|||
usesScalaJSLinkerTag in legacyKey := (usesScalaJSLinkerTag in key).value, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is fine because it is essentially a read-only key from the users' point of view.
@@ -151,6 +164,8 @@ private[sbtplugin] object ScalaJSPluginInternal { | |||
scalaJSLinkerConfigFingerprint in key := | |||
StandardConfig.fingerprint((scalaJSLinkerConfig in key).value), | |||
|
|||
moduleName in legacyKey := (moduleName in key).value, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is arguably OK because it will still affect the artifactPath in legacyKey
. Nevertheless, I think we should also derive the new one from the old one, for consistency.
@@ -335,14 +410,21 @@ private[sbtplugin] object ScalaJSPluginInternal { | |||
((crossTarget in fullOptJS).value / | |||
((moduleName in fullOptJS).value + "-opt.js")), | |||
|
|||
scalaJSLinkerConfig in fullOptJS ~= { prevConfig => | |||
scalaJSLinkerConfig in linkJSProd ~= { prevConfig => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the most annoying one, as it is a very real use case for people to tweak scalaJSLinkerConfig in (Compile, fullOptJS)
. We absolutely must not throw away their configuration, especially since it also affects the result of the legacy keys themselves.
So we should still have here in fullOptJS
, and after that add
scalaJSLinkerConfig in linkJSDev := (scalaJSLinkerConfig in fastOptJS).value,
scalaJSLinkerConfig in linkJSProd := (scalaJSLinkerConfig in fullOptJS).value,
90a5f77
to
d291eab
Compare
I have added a commit addressing the comments. (I have changed everything to be in terms of the Regarding the names of the new tasks. I like your suggestion from #4111:
It keeps For me, there are two open questions on this PR:
|
I would say that I prefer both
For the programmatic API of the |
I'd tend to agree in fact. It speaks easier. OTOH, From the 6 possible permutations of
Personally, I think I prefer |
On the other hand, Ah, naming in computer science! |
Let's settle on |
Sounds good. :) |
Without the leading slash, the resulting Path ends up not having a parent Path / directory. This in turn makes the (upcoming) backwards compatibility adapter for the Linker fail. While `Path`s without parents are techincally allowed, its hardly a case we should care about for the backwards compatibility adapter.
Rebased. Testing marathon is starting. |
Adding -Xexperimental makes compilation fail if the unapply is not marked final: "could not optimize @tailrec annotated method unapply: it is neither private nor final so can be overridden"
This commit does not add support to the compiler nor the sbt-plugin to test backwards compatibility. Further, we do not deprecate the old API yet to avoid build failures.
We cannot test this fully yet, since we need support in the sbt-plugin for that.
At this point, we can fully test exports end-to-end. We do not migrate all sbt-plugin tests to test backwards compatibility. However, we can now deprecate the old APIs without build failures. The custom-linker sbt test is migrated in this commit because it relies on the internal scalaJSLinkerBox key.
@sjrd testing is reaching completion. Do you have further comments on this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's ship it! 🚀 ✨
No description provided.