@@ -292,6 +292,13 @@ abstract class GenJSCode extends plugins.PluginComponent
292
292
" genClass() must be called only for normal classes: " + sym)
293
293
assert(sym.superClass != NoSymbol , sym)
294
294
295
+ if (hasDefaultCtorArgsAndRawJSModule(sym)) {
296
+ reporter.error(pos,
297
+ " Implementation restriction: constructors of " +
298
+ " Scala classes cannot have default parameters " +
299
+ " if their companion module is JS native." )
300
+ }
301
+
295
302
val classIdent = encodeClassFullNameIdent(sym)
296
303
val isHijacked = isHijackedBoxedClass(sym)
297
304
@@ -650,54 +657,51 @@ abstract class GenJSCode extends plugins.PluginComponent
650
657
constructorTrees : List [DefDef ]): js.Tree = {
651
658
implicit val pos = classSym.pos
652
659
653
- // Implementation restriction
654
- val syms = constructorTrees.map(_.symbol)
655
- val hasBadParam = enteringPhase(currentRun.uncurryPhase) {
656
- syms.exists(_.paramss.flatten.exists(p => p.hasDefault))
657
- }
658
- if (hasBadParam) {
660
+ if (hasDefaultCtorArgsAndRawJSModule(classSym)) {
659
661
reporter.error(pos,
660
- " Implementation restriction: the constructor of a " +
661
- " Scala.js-defined JS classes cannot have default parameters." )
662
- }
663
-
664
- withNewLocalNameScope {
665
- val ctors : List [js.MethodDef ] = constructorTrees.flatMap { tree =>
666
- genMethodWithCurrentLocalNameScope(tree)
667
- }
662
+ " Implementation restriction: constructors of " +
663
+ " Scala.js-defined JS classes cannot have default parameters " +
664
+ " if their companion module is JS native." )
665
+ js.EmptyTree
666
+ } else {
667
+ withNewLocalNameScope {
668
+ val ctors : List [js.MethodDef ] = constructorTrees.flatMap { tree =>
669
+ genMethodWithCurrentLocalNameScope(tree)
670
+ }
668
671
669
- val dispatch =
670
- genJSConstructorExport(constructorTrees.map(_.symbol))
671
- val js .MethodDef (_, dispatchName, dispatchArgs, dispatchResultType,
672
- dispatchResolution) = dispatch
672
+ val dispatch =
673
+ genJSConstructorExport(constructorTrees.map(_.symbol))
674
+ val js .MethodDef (_, dispatchName, dispatchArgs, dispatchResultType,
675
+ dispatchResolution) = dispatch
673
676
674
- val jsConstructorBuilder = mkJSConstructorBuilder(ctors)
677
+ val jsConstructorBuilder = mkJSConstructorBuilder(ctors)
675
678
676
- val overloadIdent = freshLocalIdent(" overload" )
679
+ val overloadIdent = freshLocalIdent(" overload" )
677
680
678
- // Section containing the overload resolution and casts of parameters
679
- val overloadSelection = mkOverloadSelection(jsConstructorBuilder,
681
+ // Section containing the overload resolution and casts of parameters
682
+ val overloadSelection = mkOverloadSelection(jsConstructorBuilder,
680
683
overloadIdent, dispatchResolution)
681
684
682
- /* Section containing all the code executed before the call to `this`
683
- * for every secondary constructor.
684
- */
685
- val prePrimaryCtorBody =
686
- jsConstructorBuilder.mkPrePrimaryCtorBody(overloadIdent)
685
+ /* Section containing all the code executed before the call to `this`
686
+ * for every secondary constructor.
687
+ */
688
+ val prePrimaryCtorBody =
689
+ jsConstructorBuilder.mkPrePrimaryCtorBody(overloadIdent)
687
690
688
- val primaryCtorBody = jsConstructorBuilder.primaryCtorBody
691
+ val primaryCtorBody = jsConstructorBuilder.primaryCtorBody
689
692
690
- /* Section containing all the code executed after the call to this for
691
- * every secondary constructor.
692
- */
693
- val postPrimaryCtorBody =
694
- jsConstructorBuilder.mkPostPrimaryCtorBody(overloadIdent)
693
+ /* Section containing all the code executed after the call to this for
694
+ * every secondary constructor.
695
+ */
696
+ val postPrimaryCtorBody =
697
+ jsConstructorBuilder.mkPostPrimaryCtorBody(overloadIdent)
695
698
696
- val newBody = js.Block (overloadSelection ::: prePrimaryCtorBody ::
697
- primaryCtorBody :: postPrimaryCtorBody :: Nil )
699
+ val newBody = js.Block (overloadSelection ::: prePrimaryCtorBody ::
700
+ primaryCtorBody :: postPrimaryCtorBody :: Nil )
698
701
699
- js.MethodDef (static = false , dispatchName, dispatchArgs, jstpe.NoType ,
700
- newBody)(dispatch.optimizerHints, None )
702
+ js.MethodDef (static = false , dispatchName, dispatchArgs, jstpe.NoType ,
703
+ newBody)(dispatch.optimizerHints, None )
704
+ }
701
705
}
702
706
}
703
707
@@ -1066,7 +1070,7 @@ abstract class GenJSCode extends plugins.PluginComponent
1066
1070
Some (js.MethodDef (static = false , methodName,
1067
1071
jsParams, toIRType(sym.tpe.resultType), body)(
1068
1072
OptimizerHints .empty, None ))
1069
- } else if (isRawJSCtorDefaultParam (sym)) {
1073
+ } else if (isJSNativeCtorDefaultParam (sym)) {
1070
1074
None
1071
1075
} else if (sym.isClassConstructor && isHijackedBoxedClass(sym.owner)) {
1072
1076
None
@@ -1776,8 +1780,12 @@ abstract class GenJSCode extends plugins.PluginComponent
1776
1780
val sym = fun.symbol
1777
1781
1778
1782
def isRawJSDefaultParam : Boolean = {
1779
- sym.hasFlag(reflect.internal.Flags .DEFAULTPARAM ) &&
1780
- (isRawJSType(sym.owner.tpe) || isRawJSCtorDefaultParam(sym))
1783
+ if (isCtorDefaultParam(sym)) {
1784
+ isRawJSCtorDefaultParam(sym)
1785
+ } else {
1786
+ sym.hasFlag(reflect.internal.Flags .DEFAULTPARAM ) &&
1787
+ isRawJSType(sym.owner.tpe)
1788
+ }
1781
1789
}
1782
1790
1783
1791
fun match {
@@ -4465,7 +4473,7 @@ abstract class GenJSCode extends plugins.PluginComponent
4465
4473
4466
4474
if (isGlobalScope) {
4467
4475
genLoadGlobal()
4468
- } else if (isRawJSType(sym.tpe) && ! isScalaJSDefinedJSClass (sym)) {
4476
+ } else if (isJSNativeClass (sym)) {
4469
4477
genPrimitiveJSModule(sym)
4470
4478
} else {
4471
4479
val moduleClassName = encodeClassFullName(sym)
@@ -4520,6 +4528,10 @@ abstract class GenJSCode extends plugins.PluginComponent
4520
4528
def isScalaJSDefinedJSClass (sym : Symbol ): Boolean =
4521
4529
! sym.isTrait && sym.hasAnnotation(ScalaJSDefinedAnnotation )
4522
4530
4531
+ /** Tests whether the given class is a JS native class. */
4532
+ private def isJSNativeClass (sym : Symbol ): Boolean =
4533
+ isRawJSType(sym.tpe) && ! isScalaJSDefinedJSClass(sym)
4534
+
4523
4535
/** Tests whether the given member is exposed, i.e., whether it was
4524
4536
* originally a public or protected member of a Scala.js-defined JS class.
4525
4537
*/
@@ -4531,12 +4543,40 @@ abstract class GenJSCode extends plugins.PluginComponent
4531
4543
sym.isAnonymousClass && AllJSFunctionClasses .exists(sym isSubClass _)
4532
4544
4533
4545
private def isRawJSCtorDefaultParam (sym : Symbol ) = {
4546
+ isCtorDefaultParam(sym) &&
4547
+ isRawJSType(patchedLinkedClassOfClass(sym.owner).tpe)
4548
+ }
4549
+
4550
+ private def isJSNativeCtorDefaultParam (sym : Symbol ) = {
4551
+ isCtorDefaultParam(sym) &&
4552
+ isJSNativeClass(patchedLinkedClassOfClass(sym.owner))
4553
+ }
4554
+
4555
+ private def isCtorDefaultParam (sym : Symbol ) = {
4534
4556
sym.hasFlag(reflect.internal.Flags .DEFAULTPARAM ) &&
4535
4557
sym.owner.isModuleClass &&
4536
- isRawJSType(patchedLinkedClassOfClass(sym.owner).tpe) &&
4537
4558
nme.defaultGetterToMethod(sym.name) == nme.CONSTRUCTOR
4538
4559
}
4539
4560
4561
+ private def hasDefaultCtorArgsAndRawJSModule (classSym : Symbol ): Boolean = {
4562
+ /* Get the companion module class.
4563
+ * For inner classes the sym.owner.companionModule can be broken,
4564
+ * therefore companionModule is fetched at uncurryPhase.
4565
+ */
4566
+ val companionClass = enteringPhase(currentRun.uncurryPhase) {
4567
+ classSym.companionModule
4568
+ }.moduleClass
4569
+
4570
+ def hasDefaultParameters = {
4571
+ val syms = classSym.info.members.filter(_.isClassConstructor)
4572
+ enteringPhase(currentRun.uncurryPhase) {
4573
+ syms.exists(_.paramss.iterator.flatten.exists(_.hasDefault))
4574
+ }
4575
+ }
4576
+
4577
+ isJSNativeClass(companionClass) && hasDefaultParameters
4578
+ }
4579
+
4540
4580
private def patchedLinkedClassOfClass (sym : Symbol ): Symbol = {
4541
4581
/* Work around a bug of scalac with linkedClassOfClass where package
4542
4582
* objects are involved (the companion class would somehow exist twice
0 commit comments