@@ -758,7 +758,7 @@ class JSCodeGen()(using genCtx: Context) {
758
758
(paramName, paramInfo) <- m.info.paramNamess.flatten.zip(m.info.paramInfoss.flatten)
759
759
} yield {
760
760
js.ParamDef (freshLocalIdent(paramName), NoOriginalName ,
761
- toIRType(paramInfo), mutable = false , rest = false )
761
+ toIRType(paramInfo), mutable = false )
762
762
}
763
763
val resultType = toIRType(m.info.resultType)
764
764
@@ -811,11 +811,16 @@ class JSCodeGen()(using genCtx: Context) {
811
811
812
812
val flags = js.MemberFlags .empty.withMutable(mutable).withNamespace(namespace)
813
813
814
- val irTpe =
814
+ val irTpe0 =
815
815
if (isJSClass) genExposedFieldIRType(f)
816
816
else if (isTopLevelExport) jstpe.AnyType
817
817
else toIRType(f.info)
818
818
819
+ // scala-js/#4370 Fields cannot have type NothingType
820
+ val irTpe =
821
+ if (irTpe0 == jstpe.NothingType ) encodeClassType(defn.NothingClass )
822
+ else irTpe0
823
+
819
824
if (isJSClass && f.isJSExposed)
820
825
js.JSFieldDef (flags, genExpr(f.jsName)(f.sourcePos), irTpe) :: Nil
821
826
else
@@ -896,7 +901,7 @@ class JSCodeGen()(using genCtx: Context) {
896
901
val fqcnArg = js.StringLiteral (sym.fullName.toString)
897
902
val runtimeClassArg = js.ClassOf (toTypeRef(sym.info))
898
903
val loadModuleFunArg =
899
- js.Closure (arrow = true , Nil , Nil , genLoadModule(sym), Nil )
904
+ js.Closure (arrow = true , Nil , Nil , None , genLoadModule(sym), Nil )
900
905
901
906
val stat = genApplyMethod(
902
907
genLoadModule(jsdefn.ReflectModule ),
@@ -924,14 +929,14 @@ class JSCodeGen()(using genCtx: Context) {
924
929
} yield {
925
930
val paramType = js.ClassOf (toTypeRef(paramInfo))
926
931
val paramDef = js.ParamDef (freshLocalIdent(paramName),
927
- NoOriginalName , jstpe.AnyType , mutable = false , rest = false )
932
+ NoOriginalName , jstpe.AnyType , mutable = false )
928
933
val actualParam = unbox(paramDef.ref, paramInfo)
929
934
(paramType, paramDef, actualParam)
930
935
}).unzip3
931
936
932
937
val paramTypesArray = js.JSArrayConstr (parameterTypes)
933
938
934
- val newInstanceFun = js.Closure (arrow = true , Nil , formalParams, {
939
+ val newInstanceFun = js.Closure (arrow = true , Nil , formalParams, None , {
935
940
js.New (encodeClassName(sym), encodeMethodSym(ctor), actualParams)
936
941
}, Nil )
937
942
@@ -965,7 +970,7 @@ class JSCodeGen()(using genCtx: Context) {
965
970
" if their companion module is JS native." ,
966
971
classSym.srcPos)
967
972
val ctorDef = js.JSMethodDef (js.MemberFlags .empty,
968
- js.StringLiteral (" constructor" ), Nil , js.Skip ())(
973
+ js.StringLiteral (" constructor" ), Nil , None , js.Skip ())(
969
974
OptimizerHints .empty, None )
970
975
(None , ctorDef)
971
976
} else {
@@ -985,7 +990,7 @@ class JSCodeGen()(using genCtx: Context) {
985
990
val captureParamsWithJSSuperClass = captureParams.map { params =>
986
991
val jsSuperClassParam = js.ParamDef (
987
992
js.LocalIdent (JSSuperClassParamName ), NoOriginalName ,
988
- jstpe.AnyType , mutable = false , rest = false )
993
+ jstpe.AnyType , mutable = false )
989
994
jsSuperClassParam :: params
990
995
}
991
996
@@ -1055,6 +1060,9 @@ class JSCodeGen()(using genCtx: Context) {
1055
1060
1056
1061
if (primitives.isPrimitive(sym)) {
1057
1062
None
1063
+ } else if (sym.is(Deferred ) && currentClassSym.isNonNativeJSClass) {
1064
+ // scala-js/#4409: Do not emit abstract methods in non-native JS classes
1065
+ None
1058
1066
} else if (sym.is(Deferred )) {
1059
1067
Some (js.MethodDef (js.MemberFlags .empty, methodName, originalName,
1060
1068
jsParams, toIRType(patchedResultType(sym)), None )(
@@ -1153,7 +1161,7 @@ class JSCodeGen()(using genCtx: Context) {
1153
1161
val flags =
1154
1162
js.MemberFlags .empty.withNamespace(staticNamespace)
1155
1163
val thisParamDef = js.ParamDef (thisLocalIdent, thisOriginalName,
1156
- jstpe.AnyType , mutable = false , rest = false )
1164
+ jstpe.AnyType , mutable = false )
1157
1165
1158
1166
js.MethodDef (flags, methodName, originalName,
1159
1167
thisParamDef :: jsParams, resultIRType, Some (genBody()))(
@@ -1222,7 +1230,7 @@ class JSCodeGen()(using genCtx: Context) {
1222
1230
1223
1231
private def genParamDef (sym : Symbol , ptpe : jstpe.Type , pos : Position ): js.ParamDef = {
1224
1232
js.ParamDef (encodeLocalSym(sym)(implicitly, pos, implicitly),
1225
- originalNameOfLocal(sym), ptpe, mutable = false , rest = false )(pos)
1233
+ originalNameOfLocal(sym), ptpe, mutable = false )(pos)
1226
1234
}
1227
1235
1228
1236
// Generate statements and expressions -------------------------------------
@@ -1930,10 +1938,11 @@ class JSCodeGen()(using genCtx: Context) {
1930
1938
val jsClassCaptures = originalClassDef.jsClassCaptures.getOrElse {
1931
1939
throw new AssertionError (s " no class captures for anonymous JS class at $pos" )
1932
1940
}
1933
- val js .JSMethodDef (_, _, ctorParams, ctorBody) = constructor.getOrElse {
1941
+ val js .JSMethodDef (_, _, ctorParams, ctorRestParam, ctorBody) = constructor.getOrElse {
1934
1942
throw new AssertionError (" No ctor found" )
1935
1943
}
1936
- assert(ctorParams.isEmpty, s " non-empty constructor params for anonymous JS class at $pos" )
1944
+ assert(ctorParams.isEmpty && ctorRestParam.isEmpty,
1945
+ s " non-empty constructor params for anonymous JS class at $pos" )
1937
1946
1938
1947
/* The first class capture is always a reference to the super class.
1939
1948
* This is enforced by genJSClassCapturesAndConstructor.
@@ -1950,8 +1959,8 @@ class JSCodeGen()(using genCtx: Context) {
1950
1959
def selfRef (implicit pos : ir.Position ) =
1951
1960
js.VarRef (selfName)(jstpe.AnyType )
1952
1961
1953
- def memberLambda (params : List [js.ParamDef ], body : js.Tree )(implicit pos : ir.Position ): js.Closure =
1954
- js.Closure (arrow = false , captureParams = Nil , params, body, captureValues = Nil )
1962
+ def memberLambda (params : List [js.ParamDef ], restParam : Option [js. ParamDef ], body : js.Tree )(implicit pos : ir.Position ): js.Closure =
1963
+ js.Closure (arrow = false , captureParams = Nil , params, restParam, body, captureValues = Nil )
1955
1964
1956
1965
val memberDefinitions0 = instanceMembers.toList.map {
1957
1966
case fdef : js.FieldDef =>
@@ -1966,16 +1975,16 @@ class JSCodeGen()(using genCtx: Context) {
1966
1975
1967
1976
case mdef : js.JSMethodDef =>
1968
1977
implicit val pos = mdef.pos
1969
- val impl = memberLambda(mdef.args, mdef.body)
1978
+ val impl = memberLambda(mdef.args, mdef.restParam, mdef. body)
1970
1979
js.Assign (js.JSSelect (selfRef, mdef.name), impl)
1971
1980
1972
1981
case pdef : js.JSPropertyDef =>
1973
1982
implicit val pos = pdef.pos
1974
1983
val optGetter = pdef.getterBody.map { body =>
1975
- js.StringLiteral (" get" ) -> memberLambda(params = Nil , body)
1984
+ js.StringLiteral (" get" ) -> memberLambda(params = Nil , restParam = None , body)
1976
1985
}
1977
1986
val optSetter = pdef.setterArgAndBody.map { case (arg, body) =>
1978
- js.StringLiteral (" set" ) -> memberLambda(params = arg :: Nil , body)
1987
+ js.StringLiteral (" set" ) -> memberLambda(params = arg :: Nil , restParam = None , body)
1979
1988
}
1980
1989
val descriptor = js.JSObjectConstr (
1981
1990
optGetter.toList :::
@@ -2067,7 +2076,7 @@ class JSCodeGen()(using genCtx: Context) {
2067
2076
}
2068
2077
}.transform(ctorBody, isStat = true )
2069
2078
2070
- val closure = js.Closure (arrow = true , jsClassCaptures, Nil ,
2079
+ val closure = js.Closure (arrow = true , jsClassCaptures, Nil , None ,
2071
2080
js.Block (inlinedCtorStats, selfRef), jsSuperClassValue :: args)
2072
2081
js.JSFunctionApply (closure, Nil )
2073
2082
}
@@ -2519,7 +2528,7 @@ class JSCodeGen()(using genCtx: Context) {
2519
2528
ErrorType (msg)
2520
2529
}
2521
2530
2522
- def genSelect (): js.Tree =
2531
+ def genSelect (): js.AssignLhs =
2523
2532
js.ArraySelect (genArray, genArgs(0 ))(toIRType(elementType))
2524
2533
2525
2534
if (isArrayGet(code)) {
@@ -2679,8 +2688,8 @@ class JSCodeGen()(using genCtx: Context) {
2679
2688
case _ =>
2680
2689
def jsFunName = genExpr(jsNameOf(sym))
2681
2690
2682
- def genSuperReference (propName : js.Tree ): js.Tree = {
2683
- jsSuperClassValue.fold[js.Tree ] {
2691
+ def genSuperReference (propName : js.Tree ): js.AssignLhs = {
2692
+ jsSuperClassValue.fold[js.AssignLhs ] {
2684
2693
genJSSelectOrGlobalRef(receiver, propName)
2685
2694
} { superClassValue =>
2686
2695
js.JSSuperSelect (superClassValue, ruleOutGlobalScope(receiver), propName)
@@ -3075,7 +3084,7 @@ class JSCodeGen()(using genCtx: Context) {
3075
3084
case _ => (freshLocalIdent(), NoOriginalName )
3076
3085
}
3077
3086
val formalCapture = js.ParamDef (formalIdent, originalName,
3078
- toIRType(value.tpe), mutable = false , rest = false )
3087
+ toIRType(value.tpe), mutable = false )
3079
3088
val actualCapture = genExpr(value)
3080
3089
(formalCapture, actualCapture)
3081
3090
}
@@ -3087,8 +3096,7 @@ class JSCodeGen()(using genCtx: Context) {
3087
3096
val formalAndActualParams = formalParamNamesAndTypes.map {
3088
3097
case (name, tpe) =>
3089
3098
val formalParam = js.ParamDef (freshLocalIdent(name.toString),
3090
- OriginalName (name.toString), jstpe.AnyType , mutable = false ,
3091
- rest = false )
3099
+ OriginalName (name.toString), jstpe.AnyType , mutable = false )
3092
3100
val actualParam = unbox(formalParam.ref, tpe)
3093
3101
(formalParam, actualParam)
3094
3102
}
@@ -3115,14 +3123,15 @@ class JSCodeGen()(using genCtx: Context) {
3115
3123
arrow = false ,
3116
3124
formalCaptures,
3117
3125
otherParams,
3126
+ None ,
3118
3127
js.Block (
3119
3128
js.VarDef (thisParam.name, thisParam.originalName,
3120
3129
thisParam.ptpe, mutable = false ,
3121
3130
js.This ()(thisParam.ptpe)(thisParam.pos))(thisParam.pos),
3122
3131
genBody),
3123
3132
actualCaptures)
3124
3133
} else {
3125
- val closure = js.Closure (arrow = true , formalCaptures, formalParams, genBody, actualCaptures)
3134
+ val closure = js.Closure (arrow = true , formalCaptures, formalParams, None , genBody, actualCaptures)
3126
3135
3127
3136
if (jsdefn.isJSFunctionClass(funInterfaceSym)) {
3128
3137
closure
@@ -3894,7 +3903,7 @@ class JSCodeGen()(using genCtx: Context) {
3894
3903
}
3895
3904
}
3896
3905
3897
- private def genAssignableField (sym : Symbol , qualifier : Tree )(implicit pos : SourcePosition ): (js.Tree , Boolean ) = {
3906
+ private def genAssignableField (sym : Symbol , qualifier : Tree )(implicit pos : SourcePosition ): (js.AssignLhs , Boolean ) = {
3898
3907
def qual = genExpr(qualifier)
3899
3908
3900
3909
if (sym.owner.isNonNativeJSClass) {
@@ -3921,17 +3930,27 @@ class JSCodeGen()(using genCtx: Context) {
3921
3930
val f = js.JSSelect (genLoadJSConstructor(companionClass), js.StringLiteral (jsName))
3922
3931
(f, true )
3923
3932
} else {
3924
- val f =
3925
- val className = encodeClassName(sym.owner)
3926
- val fieldIdent = encodeFieldSym(sym)
3927
- val irType = toIRType(sym.info)
3933
+ val className = encodeClassName(sym.owner)
3934
+ val fieldIdent = encodeFieldSym(sym)
3935
+
3936
+ /* #4370 Fields cannot have type NothingType, so we box them as
3937
+ * scala.runtime.Nothing$ instead. They will be initialized with
3938
+ * `null`, and any attempt to access them will throw a
3939
+ * `ClassCastException` (generated in the unboxing code).
3940
+ */
3941
+ val (irType, boxed) = toIRType(sym.info) match
3942
+ case jstpe.NothingType =>
3943
+ (encodeClassType(defn.NothingClass ), true )
3944
+ case ftpe =>
3945
+ (ftpe, false )
3928
3946
3947
+ val f =
3929
3948
if sym.is(JavaStatic ) then
3930
3949
js.SelectStatic (className, fieldIdent)(irType)
3931
3950
else
3932
3951
js.Select (qual, className, fieldIdent)(irType)
3933
3952
3934
- (f, false )
3953
+ (f, boxed )
3935
3954
}
3936
3955
}
3937
3956
@@ -4048,7 +4067,7 @@ class JSCodeGen()(using genCtx: Context) {
4048
4067
* Otherwise, report a compile error.
4049
4068
*/
4050
4069
private def genJSSelectOrGlobalRef (qual : MaybeGlobalScope , item : js.Tree )(
4051
- implicit pos : SourcePosition ): js.Tree = {
4070
+ implicit pos : SourcePosition ): js.AssignLhs = {
4052
4071
qual match {
4053
4072
case MaybeGlobalScope .NotGlobalScope (qualTree) =>
4054
4073
js.JSSelect (qualTree, item)
0 commit comments