Skip to content

Commit 71e8fc2

Browse files
committed
Fix scala-js#4769: Give JSPropertyDef a hash
1 parent 8458ffe commit 71e8fc2

File tree

6 files changed

+67
-8
lines changed

6 files changed

+67
-8
lines changed

compiler/src/main/scala/org/scalajs/nscplugin/GenJSExports.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ trait GenJSExports[G <: Global with Singleton] extends SubComponent {
264264
reporter.error(alts.head.pos,
265265
s"Conflicting properties and methods for ${classSym.fullName}::$name.")
266266
implicit val pos = alts.head.pos
267-
js.JSPropertyDef(js.MemberFlags.empty, genExpr(name), None, None)
267+
js.JSPropertyDef(js.MemberFlags.empty, genExpr(name), None, None)(None)
268268
} else {
269269
genMemberExportOrDispatcher(name, isProp, alts, static = false)
270270
}
@@ -317,7 +317,7 @@ trait GenJSExports[G <: Global with Singleton] extends SubComponent {
317317
}
318318
}
319319

320-
js.JSPropertyDef(flags, genExpr(jsName), getterBody, setterArgAndBody)
320+
js.JSPropertyDef(flags, genExpr(jsName), getterBody, setterArgAndBody)(None)
321321
}
322322

323323
/** generates the exporter function (i.e. exporter for non-properties) for

ir/shared/src/main/scala/org/scalajs/ir/Hashers.scala

+24-1
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,35 @@ object Hashers {
8787
}
8888
}
8989

90+
def hashJSPropertyDef(propDef: JSPropertyDef): JSPropertyDef = {
91+
if (propDef.hash.isDefined) propDef
92+
else {
93+
val hasher = new TreeHasher()
94+
val JSPropertyDef(flags, name, getterBody, setterArgAndBody) = propDef
95+
96+
hasher.mixPos(propDef.pos)
97+
hasher.mixInt(MemberFlags.toBits(flags))
98+
hasher.mixTree(name)
99+
getterBody.foreach(hasher.mixTree(_))
100+
setterArgAndBody.foreach { case (param, body) =>
101+
hasher.mixParamDef(param)
102+
hasher.mixTree(body)
103+
}
104+
105+
val hash = hasher.finalizeHash()
106+
107+
JSPropertyDef(flags, name, getterBody, setterArgAndBody)(Some(hash))(propDef.pos)
108+
}
109+
}
110+
90111
/** Hash definitions from a ClassDef where applicable */
91112
def hashMemberDefs(memberDefs: List[MemberDef]): List[MemberDef] = memberDefs.map {
92113
case methodDef: MethodDef => hashMethodDef(methodDef)
93114
case ctorDef: JSConstructorDef => hashJSConstructorDef(ctorDef)
94115
case methodDef: JSMethodDef => hashJSMethodDef(methodDef)
95-
case otherDef => otherDef
116+
case propDef: JSPropertyDef => hashJSPropertyDef(propDef)
117+
case fieldDef: AnyFieldDef => fieldDef
118+
case native: JSNativeMemberDef => native
96119
}
97120

98121
/** Hash the definitions in a ClassDef (where applicable) */

ir/shared/src/main/scala/org/scalajs/ir/Serializers.scala

+35-2
Original file line numberDiff line numberDiff line change
@@ -711,8 +711,17 @@ object Serializers {
711711
writeInt(length)
712712
bufferUnderlying.continue()
713713

714-
case JSPropertyDef(flags, name, getter, setterArgAndBody) =>
714+
case propDef: JSPropertyDef =>
715+
val JSPropertyDef(flags, name, getter, setterArgAndBody) = propDef
716+
715717
writeByte(TagJSPropertyDef)
718+
writeOptHash(propDef.hash)
719+
720+
// Prepare for back-jump and write dummy length
721+
bufferUnderlying.markJump()
722+
writeInt(-1)
723+
724+
// Write out prop def
716725
writeInt(MemberFlags.toBits(flags))
717726
writeTree(name)
718727
writeOptTree(getter)
@@ -721,6 +730,11 @@ object Serializers {
721730
writeParamDef(arg); writeTree(body)
722731
}
723732

733+
// Jump back and write true length
734+
val length = bufferUnderlying.jumpBack()
735+
writeInt(length)
736+
bufferUnderlying.continue()
737+
724738
case JSNativeMemberDef(flags, name, jsNativeLoadSpec) =>
725739
writeByte(TagJSNativeMemberDef)
726740
writeInt(MemberFlags.toBits(flags))
@@ -1591,6 +1605,18 @@ object Serializers {
15911605
OptimizerHints.fromBits(readInt()), optHash)
15921606

15931607
case TagJSPropertyDef =>
1608+
val optHash = {
1609+
if (hacks.use12) {
1610+
None
1611+
} else {
1612+
val optHash = readOptHash()
1613+
// read and discard the length
1614+
val len = readInt()
1615+
assert(len >= 0)
1616+
optHash
1617+
}
1618+
}
1619+
15941620
val flags = MemberFlags.fromBits(readInt())
15951621
val name = bodyHack5Expr(readTree())
15961622
val getterBody = readOptTree().map(bodyHack5Expr(_))
@@ -1600,7 +1626,7 @@ object Serializers {
16001626
else
16011627
None
16021628
}
1603-
JSPropertyDef(flags, name, getterBody, setterArgAndBody)
1629+
JSPropertyDef(flags, name, getterBody, setterArgAndBody)(optHash)
16041630

16051631
case TagJSNativeMemberDef =>
16061632
val flags = MemberFlags.fromBits(readInt())
@@ -2021,6 +2047,13 @@ object Serializers {
20212047
private val use7: Boolean = use6 || sourceVersion == "1.7"
20222048

20232049
val use8: Boolean = use7 || sourceVersion == "1.8"
2050+
2051+
assert(sourceVersion != "1.9", "source version 1.9 does not exist")
2052+
assert(sourceVersion != "1.10", "source version 1.10 does not exist")
2053+
2054+
private val use11: Boolean = use8 || sourceVersion == "1.11"
2055+
2056+
val use12: Boolean = use11 || sourceVersion == "1.12"
20242057
}
20252058

20262059
/** Names needed for hacks. */

ir/shared/src/main/scala/org/scalajs/ir/Transformers.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ object Transformers {
273273
getterBody.map(transformStat),
274274
setterArgAndBody map { case (arg, body) =>
275275
(arg, transformStat(body))
276-
})
276+
})(None)
277277
}
278278
}
279279

ir/shared/src/main/scala/org/scalajs/ir/Trees.scala

+1
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,7 @@ object Trees {
11931193

11941194
sealed case class JSPropertyDef(flags: MemberFlags, name: Tree,
11951195
getterBody: Option[Tree], setterArgAndBody: Option[(ParamDef, Tree)])(
1196+
val hash: Option[TreeHash])(
11961197
implicit val pos: Position)
11971198
extends JSMethodPropDef
11981199

linker/shared/src/main/scala/org/scalajs/linker/frontend/BaseLinker.scala

+4-2
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,10 @@ final class BaseLinker(config: CommonPhaseConfig, checkIR: Boolean) {
189189
}
190190

191191
case m: JSPropertyDef =>
192-
if (analyzerInfo.isAnySubclassInstantiated)
193-
exportedMembers += new Versioned(m, None)
192+
if (analyzerInfo.isAnySubclassInstantiated) {
193+
val version = m.hash.map(Hashers.hashAsVersion(_))
194+
exportedMembers += new Versioned(m, version)
195+
}
194196

195197
case m: JSNativeMemberDef =>
196198
if (analyzerInfo.jsNativeMembersUsed.contains(m.name.name))

0 commit comments

Comments
 (0)