@@ -69,6 +69,8 @@ struct BridgeJSLink {
69
69
var dtsClassLines : [ String ] = [ ]
70
70
var namespacedFunctions : [ ExportedFunction ] = [ ]
71
71
var namespacedClasses : [ ExportedClass ] = [ ]
72
+ var enumConstantLines : [ String ] = [ ]
73
+ var dtsEnumLines : [ String ] = [ ]
72
74
73
75
if exportedSkeletons. contains ( where: { $0. classes. count > 0 } ) {
74
76
classLines. append (
@@ -96,6 +98,15 @@ struct BridgeJSLink {
96
98
}
97
99
}
98
100
101
+ if !skeleton. enums. isEmpty {
102
+ for enumDef in skeleton. enums {
103
+ let ( jsEnum, dtsEnum) = try renderExportedEnum ( enumDef)
104
+ enumConstantLines. append ( contentsOf: jsEnum)
105
+ exportsLines. append ( " \( enumDef. name) , " )
106
+ dtsEnumLines. append ( contentsOf: dtsEnum)
107
+ }
108
+ }
109
+
99
110
for function in skeleton. functions {
100
111
var ( js, dts) = renderExportedFunction ( function: function)
101
112
@@ -135,6 +146,7 @@ struct BridgeJSLink {
135
146
. map { $0. indent ( count: 12 ) } . joined ( separator: " \n " )
136
147
exportsSection = """
137
148
\( classLines. map { $0. indent ( count: 12 ) } . joined ( separator: " \n " ) )
149
+ \( enumConstantLines. map { $0. indent ( count: 12 ) } . joined ( separator: " \n " ) )
138
150
const exports = {
139
151
\( exportsLines. map { $0. indent ( count: 16 ) } . joined ( separator: " \n " ) )
140
152
};
@@ -147,6 +159,7 @@ struct BridgeJSLink {
147
159
} else {
148
160
exportsSection = """
149
161
\( classLines. map { $0. indent ( count: 12 ) } . joined ( separator: " \n " ) )
162
+ \( enumConstantLines. map { $0. indent ( count: 12 ) } . joined ( separator: " \n " ) )
150
163
return {
151
164
\( exportsLines. map { $0. indent ( count: 16 ) } . joined ( separator: " \n " ) )
152
165
};
@@ -227,6 +240,7 @@ struct BridgeJSLink {
227
240
var dtsLines : [ String ] = [ ]
228
241
dtsLines. append ( contentsOf: namespaceDeclarations ( ) )
229
242
dtsLines. append ( contentsOf: dtsClassLines)
243
+ dtsLines. append ( contentsOf: dtsEnumLines)
230
244
dtsLines. append ( contentsOf: generateImportedTypeDefinitions ( ) )
231
245
dtsLines. append ( " export type Exports = { " )
232
246
dtsLines. append ( contentsOf: dtsExportLines. map { $0. indent ( count: 4 ) } )
@@ -437,6 +451,29 @@ struct BridgeJSLink {
437
451
cleanupLines. append ( " swift.memory.release( \( bytesIdLabel) ); " )
438
452
parameterForwardings. append ( bytesIdLabel)
439
453
parameterForwardings. append ( " \( bytesLabel) .length " )
454
+ case . caseEnum( _) :
455
+ // Case enum: JavaScript receives a number (0,1,2...), pass directly to WASM
456
+ parameterForwardings. append ( " \( param. name) | 0 " )
457
+ case . rawValueEnum( _, let rawType) :
458
+ switch rawType {
459
+ case " String " :
460
+ let bytesLabel = " \( param. name) Bytes "
461
+ let bytesIdLabel = " \( param. name) Id "
462
+ bodyLines. append ( " const \( bytesLabel) = textEncoder.encode( \( param. name) ); " )
463
+ bodyLines. append ( " const \( bytesIdLabel) = swift.memory.retain( \( bytesLabel) ); " )
464
+ cleanupLines. append ( " swift.memory.release( \( bytesIdLabel) ); " )
465
+ parameterForwardings. append ( bytesIdLabel)
466
+ parameterForwardings. append ( " \( bytesLabel) .length " )
467
+ case " Bool " :
468
+ parameterForwardings. append ( " \( param. name) ? 1 : 0 " )
469
+ default :
470
+ parameterForwardings. append ( " \( param. name) " )
471
+ }
472
+ case . associatedValueEnum:
473
+ parameterForwardings. append ( " 0 " )
474
+ parameterForwardings. append ( " 0 " )
475
+ case . namespaceEnum:
476
+ break
440
477
case . jsObject:
441
478
parameterForwardings. append ( " swift.memory.retain( \( param. name) ) " )
442
479
case . swiftHeapObject:
@@ -468,6 +505,30 @@ struct BridgeJSLink {
468
505
bodyLines. append ( " const ret = tmpRetString; " )
469
506
bodyLines. append ( " tmpRetString = undefined; " )
470
507
returnExpr = " ret "
508
+ case . caseEnum( _) :
509
+ // Case enum: WASM returns Int32, use directly as JavaScript number
510
+ bodyLines. append ( " const ret = \( call) ; " )
511
+ returnExpr = " ret "
512
+ case . rawValueEnum( _, let rawType) :
513
+ switch rawType {
514
+ case " String " :
515
+ bodyLines. append ( " \( call) ; " )
516
+ bodyLines. append ( " const ret = tmpRetString; " )
517
+ bodyLines. append ( " tmpRetString = undefined; " )
518
+ returnExpr = " ret "
519
+ case " Bool " :
520
+ bodyLines. append ( " const ret = \( call) ; " )
521
+ returnExpr = " ret !== 0 "
522
+ default :
523
+ bodyLines. append ( " const ret = \( call) ; " )
524
+ returnExpr = " ret "
525
+ }
526
+ case . associatedValueEnum:
527
+ bodyLines. append ( " \( call) ; " )
528
+ returnExpr = " \" \" "
529
+ case . namespaceEnum:
530
+ bodyLines. append ( " \( call) ; " )
531
+ returnExpr = " undefined "
471
532
case . int, . float, . double:
472
533
bodyLines. append ( " const ret = \( call) ; " )
473
534
returnExpr = " ret "
@@ -541,6 +602,86 @@ struct BridgeJSLink {
541
602
" ( \( parameters. map { " \( $0. name) : \( $0. type. tsType) " } . joined ( separator: " , " ) ) ): \( returnTypeWithEffect) "
542
603
}
543
604
605
+ func renderExportedEnum( _ enumDef: ExportedEnum ) throws -> ( js: [ String ] , dts: [ String ] ) {
606
+ var jsLines : [ String ] = [ ]
607
+ var dtsLines : [ String ] = [ ]
608
+
609
+ switch enumDef. enumType {
610
+ case . simple:
611
+ jsLines. append ( " const \( enumDef. name) = { " )
612
+ for (index, enumCase) in enumDef. cases. enumerated ( ) {
613
+ let caseName = enumCase. name. capitalizedFirstLetter
614
+ jsLines. append ( " \( caseName) : \( index) , " . indent ( count: 0 ) )
615
+ }
616
+ jsLines. append ( " }; " )
617
+ jsLines. append ( " " )
618
+
619
+ dtsLines. append ( " export const \( enumDef. name) : { " )
620
+ for (index, enumCase) in enumDef. cases. enumerated ( ) {
621
+ let caseName = enumCase. name. capitalizedFirstLetter
622
+ dtsLines. append ( " readonly \( caseName) : \( index) ; " )
623
+ }
624
+ dtsLines. append ( " }; " )
625
+ dtsLines. append ( " export type \( enumDef. name) = typeof \( enumDef. name) [keyof typeof \( enumDef. name) ]; " )
626
+ dtsLines. append ( " " )
627
+ case . rawValue:
628
+ guard let rawType = enumDef. rawType else {
629
+ throw BridgeJSLinkError ( message: " Raw value enum \( enumDef. name) is missing rawType " )
630
+ }
631
+
632
+ jsLines. append ( " const \( enumDef. name) = { " )
633
+ for enumCase in enumDef. cases {
634
+ let caseName = enumCase. name. capitalizedFirstLetter
635
+ let rawValue = enumCase. rawValue ?? enumCase. name
636
+ let formattedValue : String
637
+
638
+ switch rawType {
639
+ case " String " :
640
+ formattedValue = " \" \( rawValue) \" "
641
+ case " Bool " :
642
+ formattedValue = rawValue. lowercased ( ) == " true " ? " true " : " false "
643
+ case " Float " , " Double " :
644
+ formattedValue = rawValue
645
+ default :
646
+ formattedValue = rawValue
647
+ }
648
+
649
+ jsLines. append ( " \( caseName) : \( formattedValue) , " . indent ( count: 4 ) )
650
+ }
651
+ jsLines. append ( " }; " )
652
+ jsLines. append ( " " )
653
+
654
+ dtsLines. append ( " export const \( enumDef. name) : { " )
655
+ for enumCase in enumDef. cases {
656
+ let caseName = enumCase. name. capitalizedFirstLetter
657
+ let rawValue = enumCase. rawValue ?? enumCase. name
658
+ let formattedValue : String
659
+
660
+ switch rawType {
661
+ case " String " :
662
+ formattedValue = " \" \( rawValue) \" "
663
+ case " Bool " :
664
+ formattedValue = rawValue. lowercased ( ) == " true " ? " true " : " false "
665
+ case " Float " , " Double " :
666
+ formattedValue = rawValue
667
+ default :
668
+ formattedValue = rawValue
669
+ }
670
+
671
+ dtsLines. append ( " readonly \( caseName) : \( formattedValue) ; " )
672
+ }
673
+ dtsLines. append ( " }; " )
674
+ dtsLines. append ( " export type \( enumDef. name) = typeof \( enumDef. name) [keyof typeof \( enumDef. name) ]; " )
675
+ dtsLines. append ( " " )
676
+
677
+ case . associatedValue, . namespace:
678
+ jsLines. append ( " // TODO: Implement \( enumDef. enumType) enum: \( enumDef. name) " )
679
+ dtsLines. append ( " // TODO: Implement \( enumDef. enumType) enum: \( enumDef. name) " )
680
+ }
681
+
682
+ return ( jsLines, dtsLines)
683
+ }
684
+
544
685
func renderExportedFunction( function: ExportedFunction ) -> ( js: [ String ] , dts: [ String ] ) {
545
686
let thunkBuilder = ExportedThunkBuilder ( effects: function. effects)
546
687
for param in function. parameters {
@@ -698,6 +839,24 @@ struct BridgeJSLink {
698
839
bodyLines. append ( " const \( stringObjectName) = swift.memory.getObject( \( param. name) ); " )
699
840
bodyLines. append ( " swift.memory.release( \( param. name) ); " )
700
841
parameterForwardings. append ( stringObjectName)
842
+ case . caseEnum( _) :
843
+ parameterForwardings. append ( param. name)
844
+ case . rawValueEnum( _, let rawType) :
845
+ switch rawType {
846
+ case " String " :
847
+ let stringObjectName = " \( param. name) Object "
848
+ bodyLines. append ( " const \( stringObjectName) = swift.memory.getObject( \( param. name) ); " )
849
+ bodyLines. append ( " swift.memory.release( \( param. name) ); " )
850
+ parameterForwardings. append ( stringObjectName)
851
+ case " Bool " :
852
+ parameterForwardings. append ( " \( param. name) !== 0 " )
853
+ default :
854
+ parameterForwardings. append ( param. name)
855
+ }
856
+ case . associatedValueEnum:
857
+ parameterForwardings. append ( " \" \" " )
858
+ case . namespaceEnum:
859
+ break
701
860
case . jsObject:
702
861
parameterForwardings. append ( " swift.memory.getObject( \( param. name) ) " )
703
862
default :
@@ -769,6 +928,22 @@ struct BridgeJSLink {
769
928
case . string:
770
929
bodyLines. append ( " tmpRetBytes = textEncoder.encode(ret); " )
771
930
return " tmpRetBytes.length "
931
+ case . caseEnum( _) :
932
+ return " ret "
933
+ case . rawValueEnum( _, let rawType) :
934
+ switch rawType {
935
+ case " String " :
936
+ bodyLines. append ( " tmpRetBytes = textEncoder.encode(ret); " )
937
+ return " tmpRetBytes.length "
938
+ case " Bool " :
939
+ return " ret ? 1 : 0 "
940
+ default :
941
+ return " ret "
942
+ }
943
+ case . associatedValueEnum:
944
+ return " 0 "
945
+ case . namespaceEnum:
946
+ return " 0 "
772
947
case . int, . float, . double:
773
948
return " ret "
774
949
case . bool:
@@ -947,6 +1122,11 @@ extension String {
947
1122
func indent( count: Int ) -> String {
948
1123
return String ( repeating: " " , count: count) + self
949
1124
}
1125
+
1126
+ var capitalizedFirstLetter : String {
1127
+ guard !isEmpty else { return self }
1128
+ return prefix ( 1 ) . uppercased ( ) + dropFirst( )
1129
+ }
950
1130
}
951
1131
952
1132
extension BridgeType {
@@ -968,6 +1148,14 @@ extension BridgeType {
968
1148
return name ?? " any "
969
1149
case . swiftHeapObject( let name) :
970
1150
return name
1151
+ case . caseEnum( let name) :
1152
+ return name
1153
+ case . rawValueEnum( let name, _) :
1154
+ return name
1155
+ case . associatedValueEnum( let name) :
1156
+ return name
1157
+ case . namespaceEnum( let name) :
1158
+ return name
971
1159
}
972
1160
}
973
1161
}
0 commit comments