Skip to content

Commit 8947f38

Browse files
Merge pull request #13734 from dotty-staging/scalajs-1.7.1
Upgrade to Scala.js 1.7.1.
2 parents 8da40a4 + 3ad19ce commit 8947f38

File tree

4 files changed

+137
-107
lines changed

4 files changed

+137
-107
lines changed

compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

Lines changed: 136 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ import org.scalajs.ir.Trees.OptimizerHints
4242
import dotty.tools.dotc.transform.sjs.JSSymUtils._
4343

4444
import JSEncoding._
45-
import JSInterop._
4645
import ScopedVar.withScopedVars
4746

4847
/** Main codegen for Scala.js IR.
@@ -526,7 +525,7 @@ class JSCodeGen()(using genCtx: Context) {
526525
/* We add symbols that we have to expose here. This way we also
527526
* get inherited stuff that is implemented in this class.
528527
*/
529-
dispatchMethodNames += jsNameOf(sym)
528+
dispatchMethodNames += sym.jsName
530529
}
531530
}
532531

@@ -790,7 +789,21 @@ class JSCodeGen()(using genCtx: Context) {
790789

791790
def isExcluded(m: Symbol): Boolean = {
792791
def hasAccessBoundary = m.accessBoundary(defn.RootClass) ne defn.RootClass
793-
m.is(Deferred) || m.isConstructor || hasAccessBoundary || (m.owner eq defn.ObjectClass)
792+
793+
def isOfJLObject: Boolean = m.owner eq defn.ObjectClass
794+
795+
def isDefaultParamOfJSNativeDef: Boolean = {
796+
m.name.is(DefaultGetterName) && {
797+
val info = new DefaultParamInfo(m)
798+
!info.isForConstructor && info.attachedMethod.hasAnnotation(jsdefn.JSNativeAnnot)
799+
}
800+
}
801+
802+
m.is(Deferred)
803+
|| m.isConstructor
804+
|| hasAccessBoundary
805+
|| isOfJLObject
806+
|| m.hasAnnotation(jsdefn.JSNativeAnnot) || isDefaultParamOfJSNativeDef // #4557
794807
}
795808

796809
val forwarders = for {
@@ -1403,6 +1416,53 @@ class JSCodeGen()(using genCtx: Context) {
14031416
val vparamss = dd.termParamss
14041417
val rhs = dd.rhs
14051418

1419+
/* Is this method a default accessor that should be ignored?
1420+
*
1421+
* This is the case iff one of the following applies:
1422+
* - It is a constructor default accessor and the linked class is a
1423+
* native JS class.
1424+
* - It is a default accessor for a native JS def, but with the caveat
1425+
* that its rhs must be `js.native` because of #4553.
1426+
*
1427+
* Both of those conditions can only happen if the default accessor is in
1428+
* a module class, so we use that as a fast way out. (But omitting that
1429+
* condition would not change the result.)
1430+
*
1431+
* This is different than `isJSDefaultParam` in `genApply`: we do not
1432+
* ignore default accessors of *non-native* JS types. Neither for
1433+
* constructor default accessor nor regular default accessors. We also
1434+
* do not need to worry about non-constructor members of native JS types,
1435+
* since for those, the entire member list is ignored in `genJSClassData`.
1436+
*/
1437+
def isIgnorableDefaultParam: Boolean = {
1438+
sym.name.is(DefaultGetterName) && sym.owner.is(ModuleClass) && {
1439+
val info = new DefaultParamInfo(sym)
1440+
if (info.isForConstructor) {
1441+
/* This is a default accessor for a constructor parameter. Check
1442+
* whether the attached constructor is a native JS constructor,
1443+
* which is the case iff the linked class is a native JS type.
1444+
*/
1445+
info.constructorOwner.hasAnnotation(jsdefn.JSNativeAnnot)
1446+
} else {
1447+
/* #4553 We need to ignore default accessors for JS native defs.
1448+
* However, because Scala.js <= 1.7.0 actually emitted code calling
1449+
* those accessors, we must keep default accessors that would
1450+
* compile. The only accessors we can actually get rid of are those
1451+
* that are `= js.native`.
1452+
*/
1453+
!sym.owner.isJSType &&
1454+
info.attachedMethod.hasAnnotation(jsdefn.JSNativeAnnot) && {
1455+
dd.rhs match {
1456+
case MaybeAsInstanceOf(Apply(fun, _)) =>
1457+
fun.symbol == jsdefn.JSPackage_native
1458+
case _ =>
1459+
false
1460+
}
1461+
}
1462+
}
1463+
}
1464+
}
1465+
14061466
withPerMethodBodyState(sym) {
14071467
assert(vparamss.isEmpty || vparamss.tail.isEmpty,
14081468
"Malformed parameter list: " + vparamss)
@@ -1422,7 +1482,7 @@ class JSCodeGen()(using genCtx: Context) {
14221482
Some(js.MethodDef(js.MemberFlags.empty, methodName, originalName,
14231483
jsParams, toIRType(patchedResultType(sym)), None)(
14241484
OptimizerHints.empty, None))
1425-
} else if (sym.isJSNativeCtorDefaultParam) {
1485+
} else if (isIgnorableDefaultParam) {
14261486
// #11592
14271487
None
14281488
} else if (sym.is(Bridge) && sym.name.is(DefaultGetterName) && currentClassSym.isNonNativeJSClass) {
@@ -2008,8 +2068,52 @@ class JSCodeGen()(using genCtx: Context) {
20082068
val args = tree.args
20092069
val sym = tree.fun.symbol
20102070

2071+
/* Is the method a JS default accessor, which should become an
2072+
* `UndefinedParam` rather than being compiled normally.
2073+
*
2074+
* This is true iff one of the following conditions apply:
2075+
* - It is a constructor default param for the constructor of a JS class.
2076+
* - It is a default param of an instance method of a native JS type.
2077+
* - It is a default param of an instance method of a non-native JS type
2078+
* and the attached method is exposed.
2079+
* - It is a default param for a native JS def.
2080+
*
2081+
* This is different than `isIgnorableDefaultParam` in
2082+
* `genMethodWithCurrentLocalNameScope`: we include here the default
2083+
* accessors of *non-native* JS types (unless the corresponding methods are
2084+
* not exposed). We also need to handle non-constructor members of native
2085+
* JS types.
2086+
*/
2087+
def isJSDefaultParam: Boolean = {
2088+
sym.name.is(DefaultGetterName) && {
2089+
val info = new DefaultParamInfo(sym)
2090+
if (info.isForConstructor) {
2091+
/* This is a default accessor for a constructor parameter. Check
2092+
* whether the attached constructor is a JS constructor, which is
2093+
* the case iff the linked class is a JS type.
2094+
*/
2095+
info.constructorOwner.isJSType
2096+
} else {
2097+
if (sym.owner.isJSType) {
2098+
/* The default accessor is in a JS type. It is a JS default
2099+
* param iff the enclosing class is native or the attached method
2100+
* is exposed.
2101+
*/
2102+
!sym.owner.isNonNativeJSClass || info.attachedMethod.isJSExposed
2103+
} else {
2104+
/* The default accessor is in a Scala type. It is a JS default
2105+
* param iff the attached method is a native JS def. This can
2106+
* only happen if the owner is a module class, which we test
2107+
* first as a fast way out.
2108+
*/
2109+
sym.owner.is(ModuleClass) && info.attachedMethod.hasAnnotation(jsdefn.JSNativeAnnot)
2110+
}
2111+
}
2112+
}
2113+
}
2114+
20112115
tree.fun match {
2012-
case _ if sym.isJSDefaultParam =>
2116+
case _ if isJSDefaultParam =>
20132117
js.Transient(UndefinedParam)
20142118

20152119
case Select(Super(_, _), _) =>
@@ -4579,4 +4683,31 @@ object JSCodeGen {
45794683
out.print("<undefined-param>")
45804684
}
45814685

4686+
/** Info about a default param accessor.
4687+
*
4688+
* The method must have a default getter name for this class to make sense.
4689+
*/
4690+
private class DefaultParamInfo(sym: Symbol)(using Context) {
4691+
private val methodName = sym.name.exclude(DefaultGetterName)
4692+
4693+
def isForConstructor: Boolean = methodName == nme.CONSTRUCTOR
4694+
4695+
/** When `isForConstructor` is true, returns the owner of the attached
4696+
* constructor.
4697+
*/
4698+
def constructorOwner: Symbol = sym.owner.linkedClass
4699+
4700+
/** When `isForConstructor` is false, returns the method attached to the
4701+
* specified default accessor.
4702+
*/
4703+
def attachedMethod: Symbol = {
4704+
// If there are overloads, we need to find the one that has default params.
4705+
val overloads = sym.owner.info.decl(methodName)
4706+
if (!overloads.isOverloaded)
4707+
overloads.symbol
4708+
else
4709+
overloads.suchThat(_.is(HasDefaultParams)).symbol
4710+
}
4711+
}
4712+
45824713
}

compiler/src/dotty/tools/backend/sjs/JSInterop.scala

Lines changed: 0 additions & 74 deletions
This file was deleted.

compiler/src/dotty/tools/dotc/transform/sjs/JSSymUtils.scala

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -156,33 +156,6 @@ object JSSymUtils {
156156
def isJSBracketCall(using Context): Boolean =
157157
sym.hasAnnotation(jsdefn.JSBracketCallAnnot)
158158

159-
/** Is this symbol a default param accessor for a JS method?
160-
*
161-
* For default param accessors of *constructors*, we need to test whether
162-
* the companion *class* of the owner is a JS type; not whether the owner
163-
* is a JS type.
164-
*/
165-
def isJSDefaultParam(using Context): Boolean = {
166-
sym.name.is(DefaultGetterName) && {
167-
val owner = sym.owner
168-
val methName = sym.name.exclude(DefaultGetterName)
169-
if (methName == nme.CONSTRUCTOR) {
170-
owner.linkedClass.isJSType
171-
} else {
172-
def isAttachedMethodExposed: Boolean =
173-
owner.info.decl(methName).hasAltWith(_.symbol.isJSExposed)
174-
owner.isJSType && (!owner.isNonNativeJSClass || isAttachedMethodExposed)
175-
}
176-
}
177-
}
178-
179-
/** Is this symbol a default param accessor for the constructor of a native JS class? */
180-
def isJSNativeCtorDefaultParam(using Context): Boolean = {
181-
sym.name.is(DefaultGetterName)
182-
&& sym.name.exclude(DefaultGetterName) == nme.CONSTRUCTOR
183-
&& sym.owner.linkedClass.hasAnnotation(jsdefn.JSNativeAnnot)
184-
}
185-
186159
def jsCallingConvention(using Context): JSCallingConvention =
187160
JSCallingConvention.of(sym)
188161

project/plugins.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// e.g. addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.1.0")
44

5-
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.7.0")
5+
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.7.1")
66

77
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.6")
88

0 commit comments

Comments
 (0)