Skip to content

Commit a3c1a70

Browse files
committed
Scala.js: Handle @js.native private vals.
In dotc, `private val`s do not generate a getter method, so always relying on the getter to generate the `JSNativeMemberDef` and reading it is not correct. We now generate `JSNativeMemberDef`s both for `ValDef`s and for `DefDef`s that are not Accessors. For reading, we support both `Select`s of fields and `Apply`s of methods.
1 parent 3c9c5ba commit a3c1a70

File tree

2 files changed

+38
-13
lines changed

2 files changed

+38
-13
lines changed

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

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -353,14 +353,17 @@ class JSCodeGen()(using genCtx: Context) {
353353
tree match {
354354
case EmptyTree => ()
355355

356-
case _: ValDef =>
357-
() // fields are added via genClassFields()
356+
case vd: ValDef =>
357+
// fields are added via genClassFields(), but we need to generate the JS native members
358+
val sym = vd.symbol
359+
if (!sym.is(Module) && sym.hasAnnotation(jsdefn.JSNativeAnnot))
360+
generatedNonFieldMembers += genJSNativeMemberDef(vd)
358361

359362
case dd: DefDef =>
360363
val sym = dd.symbol
361-
362-
if (sym.hasAnnotation(jsdefn.JSNativeAnnot))
363-
generatedNonFieldMembers += genJSNativeMemberDef(dd)
364+
if sym.hasAnnotation(jsdefn.JSNativeAnnot) then
365+
if !sym.is(Accessor) then
366+
generatedNonFieldMembers += genJSNativeMemberDef(dd)
364367
else
365368
generatedNonFieldMembers ++= genMethod(dd)
366369

@@ -1379,12 +1382,12 @@ class JSCodeGen()(using genCtx: Context) {
13791382
// Generate a method -------------------------------------------------------
13801383

13811384
/** Generates the JSNativeMemberDef. */
1382-
def genJSNativeMemberDef(tree: DefDef): js.JSNativeMemberDef = {
1385+
def genJSNativeMemberDef(tree: ValOrDefDef): js.JSNativeMemberDef = {
13831386
implicit val pos = tree.span
13841387

13851388
val sym = tree.symbol
13861389
val flags = js.MemberFlags.empty.withNamespace(js.MemberNamespace.PublicStatic)
1387-
val methodName = encodeMethodSym(sym)
1390+
val methodName = encodeJSNativeMemberSym(sym)
13881391
val jsNativeLoadSpec = computeJSNativeLoadSpecOfValDef(sym)
13891392
js.JSNativeMemberDef(flags, methodName, jsNativeLoadSpec)
13901393
}
@@ -1782,6 +1785,8 @@ class JSCodeGen()(using genCtx: Context) {
17821785
genLoadModule(sym)
17831786
} else if (sym.is(JavaStatic)) {
17841787
genLoadStaticField(sym)
1788+
} else if (sym.hasAnnotation(jsdefn.JSNativeAnnot)) {
1789+
genJSNativeMemberSelect(tree)
17851790
} else {
17861791
val (field, boxed) = genAssignableField(sym, qualifier)
17871792
if (boxed) unbox(field, atPhase(elimErasedValueTypePhase)(sym.info))
@@ -3030,7 +3035,7 @@ class JSCodeGen()(using genCtx: Context) {
30303035
else
30313036
genApplyJSClassMethod(genExpr(receiver), sym, genActualArgs(sym, args))
30323037
} else if (sym.hasAnnotation(jsdefn.JSNativeAnnot)) {
3033-
genJSNativeMemberCall(tree, isStat)
3038+
genJSNativeMemberCall(tree)
30343039
} else {
30353040
genApplyMethodMaybeStatically(genExpr(receiver), sym, genActualArgs(sym, args))
30363041
}
@@ -3161,14 +3166,21 @@ class JSCodeGen()(using genCtx: Context) {
31613166
}
31623167

31633168
/** Gen JS code for a call to a native JS def or val. */
3164-
private def genJSNativeMemberCall(tree: Apply, isStat: Boolean): js.Tree = {
3169+
private def genJSNativeMemberSelect(tree: Tree): js.Tree =
3170+
genJSNativeMemberSelectOrCall(tree, Nil)
3171+
3172+
/** Gen JS code for a call to a native JS def or val. */
3173+
private def genJSNativeMemberCall(tree: Apply): js.Tree =
3174+
genJSNativeMemberSelectOrCall(tree, tree.args)
3175+
3176+
/** Gen JS code for a call to a native JS def or val. */
3177+
private def genJSNativeMemberSelectOrCall(tree: Tree, args: List[Tree]): js.Tree = {
31653178
val sym = tree.symbol
3166-
val Apply(_, args) = tree
31673179

31683180
implicit val pos = tree.span
31693181

31703182
val jsNativeMemberValue =
3171-
js.SelectJSNativeMember(encodeClassName(sym.owner), encodeMethodSym(sym))
3183+
js.SelectJSNativeMember(encodeClassName(sym.owner), encodeJSNativeMemberSym(sym))
31723184

31733185
val boxedResult =
31743186
if (sym.isJSGetter) jsNativeMemberValue

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import org.scalajs.ir.UTF8String
2424

2525
import dotty.tools.backend.jvm.DottyBackendInterface.symExtensions
2626

27+
import JSDefinitions.jsdefn
28+
2729
/** Encoding of symbol names for JavaScript
2830
*
2931
* Some issues that this encoding solves:
@@ -213,11 +215,22 @@ object JSEncoding {
213215
js.MethodIdent(methodName)
214216
}
215217

216-
def encodeStaticMemberSym(sym: Symbol)(
217-
implicit ctx: Context, pos: ir.Position): js.MethodIdent = {
218+
def encodeJSNativeMemberSym(sym: Symbol)(using Context, ir.Position): js.MethodIdent = {
219+
require(sym.hasAnnotation(jsdefn.JSNativeAnnot),
220+
"encodeJSNativeMemberSym called with non-native symbol: " + sym)
221+
if (sym.is(Method))
222+
encodeMethodSym(sym)
223+
else
224+
encodeFieldSymAsMethod(sym)
225+
}
226+
227+
def encodeStaticMemberSym(sym: Symbol)(using Context, ir.Position): js.MethodIdent = {
218228
require(sym.is(Flags.JavaStaticTerm),
219229
"encodeStaticMemberSym called with non-static symbol: " + sym)
230+
encodeFieldSymAsMethod(sym)
231+
}
220232

233+
private def encodeFieldSymAsMethod(sym: Symbol)(using Context, ir.Position): js.MethodIdent = {
221234
val name = sym.name
222235
val resultTypeRef = paramOrResultTypeRef(sym.info)
223236
val methodName = MethodName(name.mangledString, Nil, resultTypeRef)

0 commit comments

Comments
 (0)