@@ -302,8 +302,10 @@ class PrepJSInterop extends MacroTransform with IdentityDenotTransformer { thisP
302302 super .transform(tree)
303303
304304 case _ : Export =>
305- if anyEnclosingOwner is OwnerKind .JSNative then
305+ if enclosingOwner is OwnerKind .JSNative then
306306 report.error(" Native JS traits, classes and objects cannot contain exported definitions." , tree)
307+ else if enclosingOwner is OwnerKind .JSTrait then
308+ report.error(" Non-native JS traits cannot contain exported definitions." , tree)
307309
308310 super .transform(tree)
309311
@@ -465,7 +467,8 @@ class PrepJSInterop extends MacroTransform with IdentityDenotTransformer { thisP
465467 val kind = {
466468 if (! isJSNative) {
467469 if (sym.is(ModuleClass )) OwnerKind .JSMod
468- else OwnerKind .JSClass
470+ else if (sym.is(Trait )) OwnerKind .JSTrait
471+ else OwnerKind .JSNonTraitClass
469472 } else {
470473 if (sym.is(ModuleClass )) OwnerKind .JSNativeMod
471474 else OwnerKind .JSNativeClass
@@ -825,38 +828,39 @@ class PrepJSInterop extends MacroTransform with IdentityDenotTransformer { thisP
825828 /** Removes annotations from exported definitions (e.g. `export foo.bar`):
826829 * - `js.native`
827830 * - `js.annotation.*`
828- * - `js.annotation.internal.*`
829831 */
830832 private def stripJSAnnotsOnExported (sym : Symbol )(using Context ): Unit =
831- if ! sym.is(Exported ) then return
833+ if ! sym.is(Exported ) then
834+ return // only remove annotations from exported definitions
832835
833836 val JSNativeAnnot = jsdefn.JSNativeAnnot
834837 val JSAnnotPackage = jsdefn.JSAnnotPackage
835- val JSAnnotInternalPackage = jsdefn.JSAnnotInternalPackage
836838
837839 extension (sym : Symbol ) def isJSAnnot =
838- (sym eq JSNativeAnnot ) || (sym.owner eq JSAnnotPackage ) || (sym.owner eq JSAnnotInternalPackage )
840+ (sym eq JSNativeAnnot ) || (sym.owner eq JSAnnotPackage )
839841
840842 val newAnnots = sym.annotations.filterConserve(! _.symbol.isJSAnnot)
841843 if newAnnots ne sym.annotations then
842844 sym.annotations = newAnnots
843845 end stripJSAnnotsOnExported
844846
845847 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- }
848+ if tree.symbol.is(Exported ) then
849+ return // we already report an error that exports are not allowed here, this prevents extra errors.
850+
851+ // Check that the rhs is exactly `= js.native`
852+ tree.rhs match {
853+ case sel : Select if sel.symbol == jsdefn.JSPackage_native =>
854+ // ok
855+ case _ =>
856+ val pos = if (tree.rhs != EmptyTree ) tree.rhs.srcPos else tree.srcPos
857+ report.error(s " $longKindStr may only call js.native. " , pos)
858+ }
855859
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)
860+ // Check that the resul type was explicitly specified
861+ // (This is stronger than Scala 2, which only warns, and only if it was inferred as Nothing.)
862+ if (tree.tpt.span.isSynthetic)
863+ report.error(i " The type of ${tree.name} must be explicitly specified because it is JS native. " , tree)
860864 }
861865
862866 private def checkJSNativeSpecificAnnotsOnNonJSNative (memberDef : MemberDef )(using Context ): Unit = {
@@ -1021,10 +1025,12 @@ object PrepJSInterop {
10211025 val JSNativeClass = new OwnerKind (0x04 )
10221026 /** A native JS object, which extends js.Any. */
10231027 val JSNativeMod = new OwnerKind (0x08 )
1024- /** A non-native JS class/trait. */
1025- val JSClass = new OwnerKind (0x10 )
1028+ /** A non-native JS class (not a trait). */
1029+ val JSNonTraitClass = new OwnerKind (0x10 )
1030+ /** A non-native JS trait. */
1031+ val JSTrait = new OwnerKind (0x20 )
10261032 /** A non-native JS object. */
1027- val JSMod = new OwnerKind (0x20 )
1033+ val JSMod = new OwnerKind (0x40 )
10281034
10291035 // Compound kinds
10301036
@@ -1034,12 +1040,12 @@ object PrepJSInterop {
10341040 /** A native JS class/trait/object. */
10351041 val JSNative = JSNativeClass | JSNativeMod
10361042 /** A non-native JS class/trait/object. */
1037- val JSNonNative = JSClass | JSMod
1043+ val JSNonNative = JSNonTraitClass | JSTrait | JSMod
10381044 /** A JS type, i.e., something extending js.Any. */
10391045 val JSType = JSNative | JSNonNative
10401046
10411047 /** Any kind of class/trait, i.e., a Scala or JS class/trait. */
1042- val AnyClass = ScalaClass | JSNativeClass | JSClass
1048+ val AnyClass = ScalaClass | JSNativeClass | JSNonTraitClass | JSTrait
10431049 }
10441050
10451051 /** Tests if the symbol extend `js.Any`.
0 commit comments