@@ -72,6 +72,8 @@ struct BridgeJSLink {
7272 var namespacedEnums : [ ExportedEnum ] = [ ]
7373 var enumConstantLines : [ String ] = [ ]
7474 var dtsEnumLines : [ String ] = [ ]
75+ var topLevelEnumLines : [ String ] = [ ]
76+ var topLevelDtsEnumLines : [ String ] = [ ]
7577
7678 if exportedSkeletons. contains ( where: { $0. classes. count > 0 } ) {
7779 classLines. append (
@@ -102,14 +104,31 @@ struct BridgeJSLink {
102104 if !skeleton. enums. isEmpty {
103105 for enumDefinition in skeleton. enums {
104106 let ( jsEnum, dtsEnum) = try renderExportedEnum ( enumDefinition)
105- enumConstantLines. append ( contentsOf: jsEnum)
106- if enumDefinition. enumType != . namespace {
107+
108+ switch enumDefinition. enumType {
109+ case . namespace:
110+ break
111+ case . simple, . rawValue:
112+ // ALL case and raw value enums become top-level exports
113+ var exportedJsEnum = jsEnum
114+ if !exportedJsEnum. isEmpty && exportedJsEnum [ 0 ] . hasPrefix ( " const " ) {
115+ exportedJsEnum [ 0 ] = " export " + exportedJsEnum[ 0 ]
116+ }
117+ topLevelEnumLines. append ( contentsOf: exportedJsEnum)
118+ topLevelDtsEnumLines. append ( contentsOf: dtsEnum)
119+
120+ // Track namespaced enums for globalThis assignments
121+ if enumDefinition. namespace != nil {
122+ namespacedEnums. append ( enumDefinition)
123+ }
124+ case . associatedValue:
125+ enumConstantLines. append ( contentsOf: jsEnum)
107126 exportsLines. append ( " \( enumDefinition. name) , " )
108127 if enumDefinition. namespace != nil {
109128 namespacedEnums. append ( enumDefinition)
110129 }
130+ dtsEnumLines. append ( contentsOf: dtsEnum)
111131 }
112- dtsEnumLines. append ( contentsOf: dtsEnum)
113132 }
114133 }
115134
@@ -153,10 +172,13 @@ struct BridgeJSLink {
153172
154173 let exportsSection : String
155174 if hasNamespacedItems {
175+ // Only pass associated value enums to renderGlobalNamespace
176+ // (case and raw value enums are handled at top-level)
177+ let namespacedEnumsForExports = namespacedEnums. filter { $0. enumType == . associatedValue }
156178 let namespaceSetupCode = namespaceBuilder. renderGlobalNamespace (
157179 namespacedFunctions: namespacedFunctions,
158180 namespacedClasses: namespacedClasses,
159- namespacedEnums: namespacedEnums
181+ namespacedEnums: namespacedEnumsForExports
160182 )
161183 . map { $0. indent ( count: 12 ) } . joined ( separator: " \n " )
162184
@@ -189,14 +211,22 @@ struct BridgeJSLink {
189211 """
190212 }
191213
214+ let topLevelEnumsSection = topLevelEnumLines. isEmpty ? " " : topLevelEnumLines. joined ( separator: " \n " ) + " \n \n "
215+
216+ let topLevelNamespaceCode = namespaceBuilder. renderTopLevelEnumNamespaceAssignments (
217+ namespacedEnums: namespacedEnums
218+ )
219+ let namespaceAssignmentsSection =
220+ topLevelNamespaceCode. isEmpty ? " " : topLevelNamespaceCode. joined ( separator: " \n " ) + " \n \n "
221+
192222 let outputJs = """
193223 // NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit,
194224 // DO NOT EDIT.
195225 //
196226 // To update this file, just rebuild your project or run
197227 // `swift package bridge-js`.
198228
199- export async function createInstantiator(options, swift) {
229+ \( topLevelEnumsSection ) \( namespaceAssignmentsSection ) export async function createInstantiator(options, swift) {
200230 let instance;
201231 let memory;
202232 let setException;
@@ -270,14 +300,17 @@ struct BridgeJSLink {
270300 dtsLines. append ( " export type Imports = { " )
271301 dtsLines. append ( contentsOf: importObjectBuilders. flatMap { $0. dtsImportLines } . map { $0. indent ( count: 4 ) } )
272302 dtsLines. append ( " } " )
303+ let topLevelDtsEnumsSection =
304+ topLevelDtsEnumLines. isEmpty ? " " : topLevelDtsEnumLines. joined ( separator: " \n " ) + " \n "
305+
273306 let outputDts = """
274307 // NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit,
275308 // DO NOT EDIT.
276309 //
277310 // To update this file, just rebuild your project or run
278311 // `swift package bridge-js`.
279312
280- \( dtsLines. joined ( separator: " \n " ) )
313+ \( topLevelDtsEnumsSection ) \( dtsLines. joined ( separator: " \n " ) )
281314 export function createInstantiator(options: {
282315 imports: Imports;
283316 }, swift: any): Promise<{
@@ -535,7 +568,7 @@ struct BridgeJSLink {
535568 jsLines. append ( " const \( enumDefinition. name) = { " )
536569 for (index, enumCase) in enumDefinition. cases. enumerated ( ) {
537570 let caseName = enumCase. name. capitalizedFirstLetter
538- jsLines. append ( " \( caseName) : \( index) , " . indent ( count: 0 ) )
571+ jsLines. append ( " \( caseName) : \( index) , " . indent ( count: 4 ) )
539572 }
540573 jsLines. append ( " }; " )
541574 jsLines. append ( " " )
@@ -546,15 +579,15 @@ struct BridgeJSLink {
546579 dtsLines. append ( " export enum \( enumDefinition. name) { " )
547580 for (index, enumCase) in enumDefinition. cases. enumerated ( ) {
548581 let caseName = enumCase. name. capitalizedFirstLetter
549- dtsLines. append ( " \( caseName) = \( index) , " )
582+ dtsLines. append ( " \( caseName) = \( index) , " . indent ( count : 4 ) )
550583 }
551584 dtsLines. append ( " } " )
552585 dtsLines. append ( " " )
553586 case . const:
554587 dtsLines. append ( " export const \( enumDefinition. name) : { " )
555588 for (index, enumCase) in enumDefinition. cases. enumerated ( ) {
556589 let caseName = enumCase. name. capitalizedFirstLetter
557- dtsLines. append ( " readonly \( caseName) : \( index) ; " )
590+ dtsLines. append ( " readonly \( caseName) : \( index) ; " . indent ( count : 4 ) )
558591 }
559592 dtsLines. append ( " }; " )
560593 dtsLines. append (
@@ -608,7 +641,7 @@ struct BridgeJSLink {
608641 case " Float " , " Double " : formattedValue = rawValue
609642 default : formattedValue = rawValue
610643 }
611- dtsLines. append ( " \( caseName) = \( formattedValue) , " )
644+ dtsLines. append ( " \( caseName) = \( formattedValue) , " . indent ( count : 4 ) )
612645 }
613646 dtsLines. append ( " } " )
614647 dtsLines. append ( " " )
@@ -630,7 +663,7 @@ struct BridgeJSLink {
630663 formattedValue = rawValue
631664 }
632665
633- dtsLines. append ( " readonly \( caseName) : \( formattedValue) ; " )
666+ dtsLines. append ( " readonly \( caseName) : \( formattedValue) ; " . indent ( count : 4 ) )
634667 }
635668 dtsLines. append ( " }; " )
636669 dtsLines. append (
@@ -780,7 +813,7 @@ struct BridgeJSLink {
780813
781814 uniqueNamespaces. sorted ( ) . forEach { namespace in
782815 lines. append ( " if (typeof globalThis. \( namespace) === 'undefined') { " )
783- lines. append ( " globalThis.\( namespace) = {}; " )
816+ lines. append ( " globalThis. \( namespace) = {}; " . indent ( count : 4 ) )
784817 lines. append ( " } " )
785818 }
786819
@@ -790,8 +823,11 @@ struct BridgeJSLink {
790823 }
791824
792825 namespacedEnums. forEach { enumDefinition in
793- let namespacePath : String = enumDefinition. namespace? . joined ( separator: " . " ) ?? " "
794- lines. append ( " globalThis. \( namespacePath) . \( enumDefinition. name) = exports. \( enumDefinition. name) ; " )
826+ // Only handle associated value enums here (case and raw value enums are handled at top-level)
827+ if enumDefinition. enumType == . associatedValue {
828+ let namespacePath : String = enumDefinition. namespace? . joined ( separator: " . " ) ?? " "
829+ lines. append ( " globalThis. \( namespacePath) . \( enumDefinition. name) = exports. \( enumDefinition. name) ; " )
830+ }
795831 }
796832
797833 namespacedFunctions. forEach { function in
@@ -1015,7 +1051,7 @@ struct BridgeJSLink {
10151051
10161052 uniqueNamespaces. sorted ( ) . forEach { namespace in
10171053 lines. append ( " if (typeof globalThis. \( namespace) === 'undefined') { " )
1018- lines. append ( " globalThis.\( namespace) = {}; " )
1054+ lines. append ( " globalThis. \( namespace) = {}; " . indent ( count : 4 ) )
10191055 lines. append ( " } " )
10201056 }
10211057
@@ -1037,6 +1073,44 @@ struct BridgeJSLink {
10371073 return lines
10381074 }
10391075
1076+ func renderTopLevelEnumNamespaceAssignments( namespacedEnums: [ ExportedEnum ] ) -> [ String ] {
1077+ let topLevelNamespacedEnums = namespacedEnums. filter { $0. enumType == . simple || $0. enumType == . rawValue }
1078+
1079+ guard !topLevelNamespacedEnums. isEmpty else { return [ ] }
1080+
1081+ var lines : [ String ] = [ ]
1082+ var uniqueNamespaces : [ String ] = [ ]
1083+ var seen = Set < String > ( )
1084+
1085+ for enumDef in topLevelNamespacedEnums {
1086+ guard let namespacePath = enumDef. namespace else { continue }
1087+ namespacePath. enumerated ( ) . forEach { ( index, _) in
1088+ let path = namespacePath [ 0 ... index] . joined ( separator: " . " )
1089+ if !seen. contains ( path) {
1090+ seen. insert ( path)
1091+ uniqueNamespaces. append ( path)
1092+ }
1093+ }
1094+ }
1095+
1096+ for namespace in uniqueNamespaces {
1097+ lines. append ( " if (typeof globalThis. \( namespace) === 'undefined') { " )
1098+ lines. append ( " globalThis. \( namespace) = {}; " . indent ( count: 4 ) )
1099+ lines. append ( " } " )
1100+ }
1101+
1102+ if !lines. isEmpty {
1103+ lines. append ( " " )
1104+ }
1105+
1106+ for enumDef in topLevelNamespacedEnums {
1107+ let namespacePath = enumDef. namespace? . joined ( separator: " . " ) ?? " "
1108+ lines. append ( " globalThis. \( namespacePath) . \( enumDef. name) = \( enumDef. name) ; " )
1109+ }
1110+
1111+ return lines
1112+ }
1113+
10401114 private struct NamespaceContent {
10411115 var functions : [ ExportedFunction ] = [ ]
10421116 var classes : [ ExportedClass ] = [ ]
0 commit comments