Skip to content

Commit 9d6dfff

Browse files
committed
Make Reusability macro output deterministic
1 parent 51ea8c7 commit 9d6dfff

File tree

3 files changed

+22
-12
lines changed

3 files changed

+22
-12
lines changed

core/src/main/scala/japgolly/scalajs/react/internal/MacroUtils.scala

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,13 @@ abstract class MacroUtils {
129129

130130
def go(t: Type): Unit = {
131131
val tb = ensureValidAdtBase(t)
132-
val subclasses = tb.knownDirectSubclasses
132+
val subclasses = tb.knownDirectSubclasses.toArray
133+
134+
// Sort for output determinism
135+
java.util.Arrays.sort(subclasses, new java.util.Comparator[Symbol] {
136+
override def compare(a: Symbol, b: Symbol) =
137+
a.fullName.compareTo(b.fullName)
138+
})
133139

134140
// abstract first because their children may also be considered knownDirectSubclasses
135141
for (sub <- subclasses) {
@@ -406,10 +412,17 @@ abstract class MacroUtils {
406412
tryInferImplicit(t) getOrElse fail(s"Implicit not found: $t")
407413

408414
implicit val liftInit = Liftable[Init](i => q"..${i.stmts}")
409-
class Init {
415+
416+
class Init(freshNameFn: Int => String) {
410417
var seen = Map.empty[String, TermName]
411418
var stmts: Vector[Tree] = Vector.empty
412419

420+
private var vars = 0
421+
def newName(): String = {
422+
vars += 1
423+
freshNameFn(vars)
424+
}
425+
413426
def +=(t: Tree): Unit =
414427
stmts :+= t
415428

@@ -422,7 +435,7 @@ abstract class MacroUtils {
422435
val k = value.toString()
423436
seen.get(k) match {
424437
case None =>
425-
val v = TermName(c.freshName())
438+
val v = TermName(newName())
426439
this += q"val $v = $value"
427440
seen = seen.updated(k, v)
428441
v
@@ -434,12 +447,6 @@ abstract class MacroUtils {
434447
q"..$this; $body"
435448
}
436449

437-
def Init(stmts: Tree*): Init = {
438-
val i = new Init
439-
stmts foreach (i += _)
440-
i
441-
}
442-
443450
def LitNil = Ident(c.mirror staticModule "scala.collection.immutable.Nil")
444451

445452
def identityExpr[T: c.WeakTypeTag]: c.Expr[T => T] = {

doc/changelog/1.2.3.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
## 1.2.3
2+
3+
* Make Reusability macro generated code deterministic.
4+
scalajs-react build should be 'reproducable', i.e. generate identical JS if the source is the same.

extra/src/main/scala/japgolly/scalajs/react/extra/internal/ReusabilityMacros.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ class ReusabilityMacros(val c: Context) extends MacroUtils {
3434

3535
private def implSumType[T: c.WeakTypeTag](debug: Boolean, derive: Boolean): c.Expr[Reusability[T]] = {
3636
val T = weakTypeOf[T]
37-
38-
val init = new Init
37+
val init = new Init("i$" + _)
3938
val bind1 = TermName("bound1")
4039
val bind2 = TermName("bound2")
4140

@@ -86,7 +85,7 @@ class ReusabilityMacros(val c: Context) extends MacroUtils {
8685
q"$Reusability.by[$T,$t](_.$n)"
8786

8887
case _ =>
89-
val init = new Init
88+
val init = new Init("i$" + _)
9089
var tests = Vector.empty[Tree]
9190

9291
val memo = collection.mutable.HashMap.empty[Type, TermName]

0 commit comments

Comments
 (0)