@@ -758,7 +758,7 @@ class JSCodeGen()(using genCtx: Context) {
758758 (paramName, paramInfo) <- m.info.paramNamess.flatten.zip(m.info.paramInfoss.flatten)
759759 } yield {
760760 js.ParamDef (freshLocalIdent(paramName), NoOriginalName ,
761- toIRType(paramInfo), mutable = false , rest = false )
761+ toIRType(paramInfo), mutable = false )
762762 }
763763 val resultType = toIRType(m.info.resultType)
764764
@@ -811,11 +811,16 @@ class JSCodeGen()(using genCtx: Context) {
811811
812812 val flags = js.MemberFlags .empty.withMutable(mutable).withNamespace(namespace)
813813
814- val irTpe =
814+ val irTpe0 =
815815 if (isJSClass) genExposedFieldIRType(f)
816816 else if (isTopLevelExport) jstpe.AnyType
817817 else toIRType(f.info)
818818
819+ // scala-js/#4370 Fields cannot have type NothingType
820+ val irTpe =
821+ if (irTpe0 == jstpe.NothingType ) encodeClassType(defn.NothingClass )
822+ else irTpe0
823+
819824 if (isJSClass && f.isJSExposed)
820825 js.JSFieldDef (flags, genExpr(f.jsName)(f.sourcePos), irTpe) :: Nil
821826 else
@@ -896,7 +901,7 @@ class JSCodeGen()(using genCtx: Context) {
896901 val fqcnArg = js.StringLiteral (sym.fullName.toString)
897902 val runtimeClassArg = js.ClassOf (toTypeRef(sym.info))
898903 val loadModuleFunArg =
899- js.Closure (arrow = true , Nil , Nil , genLoadModule(sym), Nil )
904+ js.Closure (arrow = true , Nil , Nil , None , genLoadModule(sym), Nil )
900905
901906 val stat = genApplyMethod(
902907 genLoadModule(jsdefn.ReflectModule ),
@@ -924,14 +929,14 @@ class JSCodeGen()(using genCtx: Context) {
924929 } yield {
925930 val paramType = js.ClassOf (toTypeRef(paramInfo))
926931 val paramDef = js.ParamDef (freshLocalIdent(paramName),
927- NoOriginalName , jstpe.AnyType , mutable = false , rest = false )
932+ NoOriginalName , jstpe.AnyType , mutable = false )
928933 val actualParam = unbox(paramDef.ref, paramInfo)
929934 (paramType, paramDef, actualParam)
930935 }).unzip3
931936
932937 val paramTypesArray = js.JSArrayConstr (parameterTypes)
933938
934- val newInstanceFun = js.Closure (arrow = true , Nil , formalParams, {
939+ val newInstanceFun = js.Closure (arrow = true , Nil , formalParams, None , {
935940 js.New (encodeClassName(sym), encodeMethodSym(ctor), actualParams)
936941 }, Nil )
937942
@@ -965,7 +970,7 @@ class JSCodeGen()(using genCtx: Context) {
965970 " if their companion module is JS native." ,
966971 classSym.srcPos)
967972 val ctorDef = js.JSMethodDef (js.MemberFlags .empty,
968- js.StringLiteral (" constructor" ), Nil , js.Skip ())(
973+ js.StringLiteral (" constructor" ), Nil , None , js.Skip ())(
969974 OptimizerHints .empty, None )
970975 (None , ctorDef)
971976 } else {
@@ -985,7 +990,7 @@ class JSCodeGen()(using genCtx: Context) {
985990 val captureParamsWithJSSuperClass = captureParams.map { params =>
986991 val jsSuperClassParam = js.ParamDef (
987992 js.LocalIdent (JSSuperClassParamName ), NoOriginalName ,
988- jstpe.AnyType , mutable = false , rest = false )
993+ jstpe.AnyType , mutable = false )
989994 jsSuperClassParam :: params
990995 }
991996
@@ -1055,6 +1060,9 @@ class JSCodeGen()(using genCtx: Context) {
10551060
10561061 if (primitives.isPrimitive(sym)) {
10571062 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
10581066 } else if (sym.is(Deferred )) {
10591067 Some (js.MethodDef (js.MemberFlags .empty, methodName, originalName,
10601068 jsParams, toIRType(patchedResultType(sym)), None )(
@@ -1153,7 +1161,7 @@ class JSCodeGen()(using genCtx: Context) {
11531161 val flags =
11541162 js.MemberFlags .empty.withNamespace(staticNamespace)
11551163 val thisParamDef = js.ParamDef (thisLocalIdent, thisOriginalName,
1156- jstpe.AnyType , mutable = false , rest = false )
1164+ jstpe.AnyType , mutable = false )
11571165
11581166 js.MethodDef (flags, methodName, originalName,
11591167 thisParamDef :: jsParams, resultIRType, Some (genBody()))(
@@ -1222,7 +1230,7 @@ class JSCodeGen()(using genCtx: Context) {
12221230
12231231 private def genParamDef (sym : Symbol , ptpe : jstpe.Type , pos : Position ): js.ParamDef = {
12241232 js.ParamDef (encodeLocalSym(sym)(implicitly, pos, implicitly),
1225- originalNameOfLocal(sym), ptpe, mutable = false , rest = false )(pos)
1233+ originalNameOfLocal(sym), ptpe, mutable = false )(pos)
12261234 }
12271235
12281236 // Generate statements and expressions -------------------------------------
@@ -1930,10 +1938,11 @@ class JSCodeGen()(using genCtx: Context) {
19301938 val jsClassCaptures = originalClassDef.jsClassCaptures.getOrElse {
19311939 throw new AssertionError (s " no class captures for anonymous JS class at $pos" )
19321940 }
1933- val js .JSMethodDef (_, _, ctorParams, ctorBody) = constructor.getOrElse {
1941+ val js .JSMethodDef (_, _, ctorParams, ctorRestParam, ctorBody) = constructor.getOrElse {
19341942 throw new AssertionError (" No ctor found" )
19351943 }
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" )
19371946
19381947 /* The first class capture is always a reference to the super class.
19391948 * This is enforced by genJSClassCapturesAndConstructor.
@@ -1950,8 +1959,8 @@ class JSCodeGen()(using genCtx: Context) {
19501959 def selfRef (implicit pos : ir.Position ) =
19511960 js.VarRef (selfName)(jstpe.AnyType )
19521961
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 )
19551964
19561965 val memberDefinitions0 = instanceMembers.toList.map {
19571966 case fdef : js.FieldDef =>
@@ -1966,16 +1975,16 @@ class JSCodeGen()(using genCtx: Context) {
19661975
19671976 case mdef : js.JSMethodDef =>
19681977 implicit val pos = mdef.pos
1969- val impl = memberLambda(mdef.args, mdef.body)
1978+ val impl = memberLambda(mdef.args, mdef.restParam, mdef. body)
19701979 js.Assign (js.JSSelect (selfRef, mdef.name), impl)
19711980
19721981 case pdef : js.JSPropertyDef =>
19731982 implicit val pos = pdef.pos
19741983 val optGetter = pdef.getterBody.map { body =>
1975- js.StringLiteral (" get" ) -> memberLambda(params = Nil , body)
1984+ js.StringLiteral (" get" ) -> memberLambda(params = Nil , restParam = None , body)
19761985 }
19771986 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)
19791988 }
19801989 val descriptor = js.JSObjectConstr (
19811990 optGetter.toList :::
@@ -2067,7 +2076,7 @@ class JSCodeGen()(using genCtx: Context) {
20672076 }
20682077 }.transform(ctorBody, isStat = true )
20692078
2070- val closure = js.Closure (arrow = true , jsClassCaptures, Nil ,
2079+ val closure = js.Closure (arrow = true , jsClassCaptures, Nil , None ,
20712080 js.Block (inlinedCtorStats, selfRef), jsSuperClassValue :: args)
20722081 js.JSFunctionApply (closure, Nil )
20732082 }
@@ -2519,7 +2528,7 @@ class JSCodeGen()(using genCtx: Context) {
25192528 ErrorType (msg)
25202529 }
25212530
2522- def genSelect (): js.Tree =
2531+ def genSelect (): js.AssignLhs =
25232532 js.ArraySelect (genArray, genArgs(0 ))(toIRType(elementType))
25242533
25252534 if (isArrayGet(code)) {
@@ -2679,8 +2688,8 @@ class JSCodeGen()(using genCtx: Context) {
26792688 case _ =>
26802689 def jsFunName = genExpr(jsNameOf(sym))
26812690
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 ] {
26842693 genJSSelectOrGlobalRef(receiver, propName)
26852694 } { superClassValue =>
26862695 js.JSSuperSelect (superClassValue, ruleOutGlobalScope(receiver), propName)
@@ -3075,7 +3084,7 @@ class JSCodeGen()(using genCtx: Context) {
30753084 case _ => (freshLocalIdent(), NoOriginalName )
30763085 }
30773086 val formalCapture = js.ParamDef (formalIdent, originalName,
3078- toIRType(value.tpe), mutable = false , rest = false )
3087+ toIRType(value.tpe), mutable = false )
30793088 val actualCapture = genExpr(value)
30803089 (formalCapture, actualCapture)
30813090 }
@@ -3087,8 +3096,7 @@ class JSCodeGen()(using genCtx: Context) {
30873096 val formalAndActualParams = formalParamNamesAndTypes.map {
30883097 case (name, tpe) =>
30893098 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 )
30923100 val actualParam = unbox(formalParam.ref, tpe)
30933101 (formalParam, actualParam)
30943102 }
@@ -3115,14 +3123,15 @@ class JSCodeGen()(using genCtx: Context) {
31153123 arrow = false ,
31163124 formalCaptures,
31173125 otherParams,
3126+ None ,
31183127 js.Block (
31193128 js.VarDef (thisParam.name, thisParam.originalName,
31203129 thisParam.ptpe, mutable = false ,
31213130 js.This ()(thisParam.ptpe)(thisParam.pos))(thisParam.pos),
31223131 genBody),
31233132 actualCaptures)
31243133 } else {
3125- val closure = js.Closure (arrow = true , formalCaptures, formalParams, genBody, actualCaptures)
3134+ val closure = js.Closure (arrow = true , formalCaptures, formalParams, None , genBody, actualCaptures)
31263135
31273136 if (jsdefn.isJSFunctionClass(funInterfaceSym)) {
31283137 closure
@@ -3894,7 +3903,7 @@ class JSCodeGen()(using genCtx: Context) {
38943903 }
38953904 }
38963905
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 ) = {
38983907 def qual = genExpr(qualifier)
38993908
39003909 if (sym.owner.isNonNativeJSClass) {
@@ -3921,17 +3930,27 @@ class JSCodeGen()(using genCtx: Context) {
39213930 val f = js.JSSelect (genLoadJSConstructor(companionClass), js.StringLiteral (jsName))
39223931 (f, true )
39233932 } 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 )
39283946
3947+ val f =
39293948 if sym.is(JavaStatic ) then
39303949 js.SelectStatic (className, fieldIdent)(irType)
39313950 else
39323951 js.Select (qual, className, fieldIdent)(irType)
39333952
3934- (f, false )
3953+ (f, boxed )
39353954 }
39363955 }
39373956
@@ -4048,7 +4067,7 @@ class JSCodeGen()(using genCtx: Context) {
40484067 * Otherwise, report a compile error.
40494068 */
40504069 private def genJSSelectOrGlobalRef (qual : MaybeGlobalScope , item : js.Tree )(
4051- implicit pos : SourcePosition ): js.Tree = {
4070+ implicit pos : SourcePosition ): js.AssignLhs = {
40524071 qual match {
40534072 case MaybeGlobalScope .NotGlobalScope (qualTree) =>
40544073 js.JSSelect (qualTree, item)
0 commit comments