@@ -85,7 +85,7 @@ class PrepJSInterop extends MacroTransform with IdentityDenotTransformer { thisP
85
85
private def anyEnclosingOwner : OwnerKind = allEnclosingOwners
86
86
87
87
private def enterOwner [A ](kind : OwnerKind )(body : => A ): A = {
88
- require(kind.isBaseKind, kind)
88
+ require(kind.withoutMods. isBaseKind, kind.withoutMods )
89
89
val oldEnclosingOwner = enclosingOwner
90
90
val oldAllEnclosingOwners = allEnclosingOwners
91
91
enclosingOwner = kind
@@ -302,8 +302,10 @@ class PrepJSInterop extends MacroTransform with IdentityDenotTransformer { thisP
302
302
super .transform(tree)
303
303
304
304
case _ : Export =>
305
- if anyEnclosingOwner is OwnerKind .JSNative then
305
+ if enclosingOwner is OwnerKind .JSNative then
306
306
report.error(" Native JS traits, classes and objects cannot contain exported definitions." , tree)
307
+ else if enclosingOwner is OwnerKind .WithJSTrait then
308
+ report.error(" Non-native JS traits cannot contain exported definitions." , tree)
307
309
308
310
super .transform(tree)
309
311
@@ -465,6 +467,7 @@ class PrepJSInterop extends MacroTransform with IdentityDenotTransformer { thisP
465
467
val kind = {
466
468
if (! isJSNative) {
467
469
if (sym.is(ModuleClass )) OwnerKind .JSMod
470
+ else if (sym.is(Trait )) OwnerKind .JSClass | OwnerKind .WithJSTrait
468
471
else OwnerKind .JSClass
469
472
} else {
470
473
if (sym.is(ModuleClass )) OwnerKind .JSNativeMod
@@ -825,38 +828,38 @@ class PrepJSInterop extends MacroTransform with IdentityDenotTransformer { thisP
825
828
/** Removes annotations from exported definitions (e.g. `export foo.bar`):
826
829
* - `js.native`
827
830
* - `js.annotation.*`
828
- * - `js.annotation.internal.*`
829
831
*/
830
832
private def stripJSAnnotsOnExported (sym : Symbol )(using Context ): Unit =
831
833
if ! sym.is(Exported ) then return
832
834
833
835
val JSNativeAnnot = jsdefn.JSNativeAnnot
834
836
val JSAnnotPackage = jsdefn.JSAnnotPackage
835
- val JSAnnotInternalPackage = jsdefn.JSAnnotInternalPackage
836
837
837
838
extension (sym : Symbol ) def isJSAnnot =
838
- (sym eq JSNativeAnnot ) || (sym.owner eq JSAnnotPackage ) || (sym.owner eq JSAnnotInternalPackage )
839
+ (sym eq JSNativeAnnot ) || (sym.owner eq JSAnnotPackage )
839
840
840
841
val newAnnots = sym.annotations.filterConserve(! _.symbol.isJSAnnot)
841
842
if newAnnots ne sym.annotations then
842
843
sym.annotations = newAnnots
843
844
end stripJSAnnotsOnExported
844
845
845
846
private def checkRHSCallsJSNative (tree : ValOrDefDef , longKindStr : String )(using Context ): Unit = {
846
- if ! tree.symbol.is(Exported ) then
847
- // Check that the rhs is exactly `= js.native`
848
- tree.rhs match {
849
- case sel : Select if sel.symbol == jsdefn.JSPackage_native =>
850
- // ok
851
- case _ =>
852
- val pos = if (tree.rhs != EmptyTree ) tree.rhs.srcPos else tree.srcPos
853
- report.error(s " $longKindStr may only call js.native. " , pos)
854
- }
847
+ if tree.symbol.is(Exported ) then
848
+ return // we already report an error that exports are not allowed here, this prevents extra errors.
849
+
850
+ // Check that the rhs is exactly `= js.native`
851
+ tree.rhs match {
852
+ case sel : Select if sel.symbol == jsdefn.JSPackage_native =>
853
+ // ok
854
+ case _ =>
855
+ val pos = if (tree.rhs != EmptyTree ) tree.rhs.srcPos else tree.srcPos
856
+ report.error(s " $longKindStr may only call js.native. " , pos)
857
+ }
855
858
856
- // Check that the resul type was explicitly specified
857
- // (This is stronger than Scala 2, which only warns, and only if it was inferred as Nothing.)
858
- if (tree.tpt.span.isSynthetic)
859
- report.error(i " The type of ${tree.name} must be explicitly specified because it is JS native. " , tree)
859
+ // Check that the resul type was explicitly specified
860
+ // (This is stronger than Scala 2, which only warns, and only if it was inferred as Nothing.)
861
+ if (tree.tpt.span.isSynthetic)
862
+ report.error(i " The type of ${tree.name} must be explicitly specified because it is JS native. " , tree)
860
863
}
861
864
862
865
private def checkJSNativeSpecificAnnotsOnNonJSNative (memberDef : MemberDef )(using Context ): Unit = {
@@ -996,6 +999,9 @@ object PrepJSInterop {
996
999
inline def isBaseKind : Boolean =
997
1000
Integer .lowestOneBit(baseKinds) == baseKinds && baseKinds != 0 // exactly 1 bit on
998
1001
1002
+ @ inline def withoutMods : OwnerKind =
1003
+ new OwnerKind (this .baseKinds & ~ ModifierMask .baseKinds)
1004
+
999
1005
// cannot be `inline` because it accesses the private constructor
1000
1006
@ inline def | (that : OwnerKind ): OwnerKind =
1001
1007
new OwnerKind (this .baseKinds | that.baseKinds)
@@ -1026,6 +1032,11 @@ object PrepJSInterop {
1026
1032
/** A non-native JS object. */
1027
1033
val JSMod = new OwnerKind (0x20 )
1028
1034
1035
+ // Modifiers - these add information to a base kind
1036
+
1037
+ /** A modifer for `JSClass` to signal a non-native JS trait */
1038
+ val WithJSTrait = new OwnerKind (0x1000 )
1039
+
1029
1040
// Compound kinds
1030
1041
1031
1042
/** A Scala class, trait or object, i.e., anything not extending js.Any. */
@@ -1038,6 +1049,9 @@ object PrepJSInterop {
1038
1049
/** A JS type, i.e., something extending js.Any. */
1039
1050
val JSType = JSNative | JSNonNative
1040
1051
1052
+ /** A mask of all OwnerKind modifiers */
1053
+ private val ModifierMask = WithJSTrait
1054
+
1041
1055
/** Any kind of class/trait, i.e., a Scala or JS class/trait. */
1042
1056
val AnyClass = ScalaClass | JSNativeClass | JSClass
1043
1057
}
0 commit comments