diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index f5643cc44ddd..38641cea93e4 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -290,12 +290,12 @@ class JSCodeGen()(using genCtx: Context) { "genScalaClass() must be called only for normal classes: "+sym) assert(sym.superClass != NoSymbol, sym) - /*if (hasDefaultCtorArgsAndRawJSModule(sym)) { - reporter.error(pos, - "Implementation restriction: constructors of " + - "Scala classes cannot have default parameters " + - "if their companion module is JS native.") - }*/ + if (hasDefaultCtorArgsAndJSModule(sym)) { + report.error( + "Implementation restriction: " + + "constructors of Scala classes cannot have default parameters if their companion module is JS native.", + td) + } val classIdent = encodeClassNameIdent(sym) val originalName = originalNameOfClass(sym) @@ -965,9 +965,8 @@ class JSCodeGen()(using genCtx: Context) { if (hasDefaultCtorArgsAndJSModule(classSym)) { report.error( - "Implementation restriction: constructors of " + - "non-native JS classes cannot have default parameters " + - "if their companion module is JS native.", + "Implementation restriction: " + + "constructors of non-native JS classes cannot have default parameters if their companion module is JS native.", classSym.srcPos) val ctorDef = js.JSMethodDef(js.MemberFlags.empty, js.StringLiteral("constructor"), Nil, None, js.Skip())( @@ -1067,9 +1066,10 @@ class JSCodeGen()(using genCtx: Context) { Some(js.MethodDef(js.MemberFlags.empty, methodName, originalName, jsParams, toIRType(patchedResultType(sym)), None)( OptimizerHints.empty, None)) - } else /*if (isJSNativeCtorDefaultParam(sym)) { + } else if (sym.isJSNativeCtorDefaultParam) { + // #11592 None - } else if (sym.isClassConstructor && isHijackedBoxedClass(sym.owner)) { + } else /*if (sym.isClassConstructor && isHijackedBoxedClass(sym.owner)) { None } else*/ { /*def isTraitImplForwarder = dd.rhs match { diff --git a/compiler/src/dotty/tools/dotc/transform/sjs/JSSymUtils.scala b/compiler/src/dotty/tools/dotc/transform/sjs/JSSymUtils.scala index c11bc16d85cf..0651e33c4d7d 100644 --- a/compiler/src/dotty/tools/dotc/transform/sjs/JSSymUtils.scala +++ b/compiler/src/dotty/tools/dotc/transform/sjs/JSSymUtils.scala @@ -158,6 +158,13 @@ object JSSymUtils { } } + /** Is this symbol a default param accessor for the constructor of a native JS class? */ + def isJSNativeCtorDefaultParam(using Context): Boolean = { + sym.name.is(DefaultGetterName) + && sym.name.exclude(DefaultGetterName) == nme.CONSTRUCTOR + && sym.owner.linkedClass.hasAnnotation(jsdefn.JSNativeAnnot) + } + def jsCallingConvention(using Context): JSCallingConvention = JSCallingConvention.of(sym) diff --git a/tests/sjs-junit/test/org/scalajs/testsuite/compiler/RegressionTestScala3.scala b/tests/sjs-junit/test/org/scalajs/testsuite/compiler/RegressionTestScala3.scala index 24c80e18bddb..4a7ccad3cc5a 100644 --- a/tests/sjs-junit/test/org/scalajs/testsuite/compiler/RegressionTestScala3.scala +++ b/tests/sjs-junit/test/org/scalajs/testsuite/compiler/RegressionTestScala3.scala @@ -4,6 +4,7 @@ import org.junit.Assert.* import org.junit.Test import scala.scalajs.js +import scala.scalajs.js.annotation._ class RegressionTestScala3 { import RegressionTestScala3.* @@ -21,6 +22,11 @@ class RegressionTestScala3 { assertEquals(-1, obj2.y) assertEquals(4, obj2.foo(5)) } + + @Test def testJSNativeDefaultCtorParamIssue11592(): Unit = { + assertEquals("foo", new RangeErrorIssue11592("foo").message) + assertEquals("", new RangeErrorIssue11592().message) + } } object RegressionTestScala3 { @@ -33,6 +39,12 @@ object RegressionTestScala3 { def foo(x: Int): Int = new ChildClass().concreteMethod(x) } + + @js.native + @JSGlobal("RangeError") + class RangeErrorIssue11592(msg: String = js.native) extends js.Object { + val message: String = js.native + } } // This class needs to be at the top-level, not in an object, to reproduce the issue