@@ -22,13 +22,20 @@ public class ExportSwift {
2222 let moduleName : String
2323 private let exposeToGlobal : Bool
2424 private var skeleton : ExportedSkeleton
25+ private let hasGenerics : Bool
2526 private var sourceFiles : [ ( sourceFile: SourceFileSyntax , inputFilePath: String ) ] = [ ]
2627
27- public init ( progress: ProgressReporting , moduleName: String , skeleton: ExportedSkeleton ) {
28+ public init (
29+ progress: ProgressReporting ,
30+ moduleName: String ,
31+ skeleton: ExportedSkeleton ,
32+ hasGenerics: Bool = false
33+ ) {
2834 self . progress = progress
2935 self . moduleName = moduleName
3036 self . exposeToGlobal = skeleton. exposeToGlobal
3137 self . skeleton = skeleton
38+ self . hasGenerics = hasGenerics
3239 }
3340
3441 /// Finalizes the export process and generates the bridge code
@@ -77,7 +84,7 @@ public class ExportSwift {
7784 }
7885
7986 try withSpan ( " Render Structs " ) { [ self ] in
80- let structCodegen = StructCodegen ( )
87+ let structCodegen = StructCodegen ( hasGenerics : hasGenerics )
8188 for structDef in skeleton. structs {
8289 decls. append ( contentsOf: structCodegen. renderStructHelpers ( structDef) )
8390 decls. append ( contentsOf: try renderSingleExportedStruct ( struct: structDef) )
@@ -817,9 +824,29 @@ public class ExportSwift {
817824 // Generate ConvertibleToJSValue extension
818825 decls. append ( contentsOf: renderConvertibleToJSValueExtension ( klass: klass) )
819826
827+ if hasGenerics, klass. isFinal == true {
828+ decls. append ( contentsOf: renderClassGenericConformance ( klass: klass) )
829+ }
830+
820831 return decls
821832 }
822833
834+ private func renderClassGenericConformance( klass: ExportedClass ) -> [ DeclSyntax ] {
835+ let typeName = klass. swiftCallName
836+ let printer = CodeFragmentPrinter ( )
837+ printer. write ( " extension \( typeName) : _BridgedSwiftGenericBridgeable { " )
838+ printer. indent {
839+ printer. write (
840+ " @_spi(BridgeJS) public static var bridgeJSTypeName: StaticString { \" \( klass. abiName) \" } "
841+ )
842+ printer. write (
843+ " @_spi(BridgeJS) public static let bridgeJSTypeID: Int32 = _swift_js_resolve_type_id( \( typeName) .bridgeJSTypeName) "
844+ )
845+ }
846+ printer. write ( " } " )
847+ return [ " \( raw: printer. lines. joined ( separator: " \n " ) ) " ]
848+ }
849+
823850 /// Generates a ConvertibleToJSValue extension for the exported class
824851 ///
825852 /// # Example
@@ -887,6 +914,8 @@ struct StackCodegen {
887914 return " JSObject.bridgeJSStackPop() "
888915 case . void, . namespaceEnum:
889916 return " () "
917+ case . generic:
918+ fatalError ( " Generic type parameters are not supported in exported declarations " )
890919 }
891920 }
892921
@@ -899,7 +928,7 @@ struct StackCodegen {
899928 return " \( raw: typeName) < \( raw: wrappedType. swiftType) >.bridgeJSStackPop() "
900929 case . jsObject( let className? ) :
901930 return " \( raw: typeName) <JSObject>.bridgeJSStackPop().map { \( raw: className) (unsafelyWrapping: $0) } "
902- case . nullable, . void, . namespaceEnum, . closure, . unsafePointer, . swiftProtocol:
931+ case . nullable, . void, . namespaceEnum, . closure, . unsafePointer, . swiftProtocol, . generic :
903932 fatalError ( " Invalid nullable wrapped type: \( wrappedType) " )
904933 }
905934 }
@@ -932,6 +961,8 @@ struct StackCodegen {
932961 return lowerArrayStatements ( elementType: elementType, accessor: accessor, varPrefix: varPrefix)
933962 case . dictionary( let valueType) :
934963 return lowerDictionaryStatements ( valueType: valueType, accessor: accessor, varPrefix: varPrefix)
964+ case . generic:
965+ fatalError ( " Generic type parameters are not supported in exported declarations " )
935966 }
936967 }
937968
@@ -1242,6 +1273,11 @@ struct EnumCodegen {
12421273
12431274struct StructCodegen {
12441275 private let stackCodegen = StackCodegen ( )
1276+ private let hasGenerics : Bool
1277+
1278+ init ( hasGenerics: Bool = false ) {
1279+ self . hasGenerics = hasGenerics
1280+ }
12451281
12461282 func renderStructHelpers( _ structDef: ExportedStruct ) -> [ DeclSyntax ] {
12471283 let typeName = structDef. swiftCallName
@@ -1312,10 +1348,27 @@ struct StructCodegen {
13121348 returnType: . i32
13131349 )
13141350
1315- return [
1351+ var decls : [ DeclSyntax ] = [
13161352 bridgedStructExtension, " \( raw: lowerExternDeclPrinter. lines. joined ( separator: " \n " ) ) " ,
13171353 " \( raw: liftExternDeclPrinter. lines. joined ( separator: " \n " ) ) " ,
13181354 ]
1355+
1356+ if hasGenerics {
1357+ let genericConformancePrinter = CodeFragmentPrinter ( )
1358+ genericConformancePrinter. write ( " extension \( typeName) : _BridgedSwiftGenericBridgeable { " )
1359+ genericConformancePrinter. indent {
1360+ genericConformancePrinter. write (
1361+ " @_spi(BridgeJS) public static var bridgeJSTypeName: StaticString { \" \( structDef. abiName) \" } "
1362+ )
1363+ genericConformancePrinter. write (
1364+ " @_spi(BridgeJS) public static let bridgeJSTypeID: Int32 = _swift_js_resolve_type_id( \( typeName) .bridgeJSTypeName) "
1365+ )
1366+ }
1367+ genericConformancePrinter. write ( " } " )
1368+ decls. append ( " \( raw: genericConformancePrinter. lines. joined ( separator: " \n " ) ) " )
1369+ }
1370+
1371+ return decls
13191372 }
13201373
13211374 private func generateStructLiftCode( structDef: ExportedStruct ) -> [ String ] {
@@ -1593,6 +1646,7 @@ extension BridgeType {
15931646 let effectsStr = ( signature. isAsync ? " async " : " " ) + ( signature. isThrows ? " throws " : " " )
15941647 let closureType = " ( \( paramTypes) ) \( effectsStr) -> \( signature. returnType. swiftType) "
15951648 return useJSTypedClosure ? " JSTypedClosure< \( closureType) > " : closureType
1649+ case . generic( let name) : return name
15961650 }
15971651 }
15981652
@@ -1675,6 +1729,8 @@ extension BridgeType {
16751729 return LiftingIntrinsicInfo ( parameters: [ ( " callbackId " , . i32) ] )
16761730 case . array, . dictionary:
16771731 return LiftingIntrinsicInfo ( parameters: [ ] )
1732+ case . generic:
1733+ throw BridgeJSCoreError ( " Generic type parameters are not supported in exported declarations " )
16781734 }
16791735 }
16801736
@@ -1726,6 +1782,8 @@ extension BridgeType {
17261782 return . jsObject
17271783 case . array, . dictionary:
17281784 return . array
1785+ case . generic:
1786+ throw BridgeJSCoreError ( " Generic type parameters are not supported in exported declarations " )
17291787 }
17301788 }
17311789}
0 commit comments