@@ -22,13 +22,29 @@ public class ExportSwift {
2222 let moduleName : String
2323 private let exposeToGlobal : Bool
2424 private var skeleton : ExportedSkeleton
25+ private let imported : ImportedModuleSkeleton ?
2526 private var sourceFiles : [ ( sourceFile: SourceFileSyntax , inputFilePath: String ) ] = [ ]
2627
27- public init ( progress: ProgressReporting , moduleName: String , skeleton: ExportedSkeleton ) {
28+ private var hasGenerics : Bool {
29+ let hasGenericExports = skeleton. functions. contains { !( $0. genericParameterNames. isEmpty) }
30+ let hasGenericImports =
31+ imported? . children. contains { file in
32+ file. functions. contains { !( $0. genericParameterNames. isEmpty) }
33+ } ?? false
34+ return hasGenericExports || hasGenericImports
35+ }
36+
37+ public init (
38+ progress: ProgressReporting ,
39+ moduleName: String ,
40+ skeleton: ExportedSkeleton ,
41+ imported: ImportedModuleSkeleton ? = nil
42+ ) {
2843 self . progress = progress
2944 self . moduleName = moduleName
3045 self . exposeToGlobal = skeleton. exposeToGlobal
3146 self . skeleton = skeleton
47+ self . imported = imported
3248 }
3349
3450 /// Finalizes the export process and generates the bridge code
@@ -80,6 +96,9 @@ public class ExportSwift {
8096 let structCodegen = StructCodegen ( )
8197 for structDef in skeleton. structs {
8298 decls. append ( contentsOf: structCodegen. renderStructHelpers ( structDef) )
99+ if hasGenerics {
100+ decls. append ( contentsOf: renderStructGenericConformance ( structDef: structDef) )
101+ }
83102 decls. append ( contentsOf: try renderSingleExportedStruct ( struct: structDef) )
84103 }
85104
@@ -817,9 +836,45 @@ public class ExportSwift {
817836 // Generate ConvertibleToJSValue extension
818837 decls. append ( contentsOf: renderConvertibleToJSValueExtension ( klass: klass) )
819838
839+ if hasGenerics, klass. isFinal == true {
840+ decls. append ( contentsOf: renderClassGenericConformance ( klass: klass) )
841+ }
842+
820843 return decls
821844 }
822845
846+ private func renderClassGenericConformance( klass: ExportedClass ) -> [ DeclSyntax ] {
847+ let typeName = klass. swiftCallName
848+ let printer = CodeFragmentPrinter ( )
849+ printer. write ( " extension \( typeName) : _BridgedSwiftGenericBridgeable { " )
850+ printer. indent {
851+ printer. write (
852+ " @_spi(BridgeJS) public static var bridgeJSTypeName: StaticString { \" \( klass. abiName) \" } "
853+ )
854+ printer. write (
855+ " @_spi(BridgeJS) public static let bridgeJSTypeID: Int32 = _swift_js_resolve_type_id( \( typeName) .bridgeJSTypeName) "
856+ )
857+ }
858+ printer. write ( " } " )
859+ return [ " \( raw: printer. lines. joined ( separator: " \n " ) ) " ]
860+ }
861+
862+ private func renderStructGenericConformance( structDef: ExportedStruct ) -> [ DeclSyntax ] {
863+ let typeName = structDef. swiftCallName
864+ let printer = CodeFragmentPrinter ( )
865+ printer. write ( " extension \( typeName) : _BridgedSwiftGenericBridgeable { " )
866+ printer. indent {
867+ printer. write (
868+ " @_spi(BridgeJS) public static var bridgeJSTypeName: StaticString { \" \( structDef. abiName) \" } "
869+ )
870+ printer. write (
871+ " @_spi(BridgeJS) public static let bridgeJSTypeID: Int32 = _swift_js_resolve_type_id( \( typeName) .bridgeJSTypeName) "
872+ )
873+ }
874+ printer. write ( " } " )
875+ return [ " \( raw: printer. lines. joined ( separator: " \n " ) ) " ]
876+ }
877+
823878 /// Generates a ConvertibleToJSValue extension for the exported class
824879 ///
825880 /// # Example
@@ -887,6 +942,8 @@ struct StackCodegen {
887942 return " JSObject.bridgeJSStackPop() "
888943 case . void, . namespaceEnum:
889944 return " () "
945+ case . generic:
946+ fatalError ( " Generic type parameters are not supported in exported declarations " )
890947 }
891948 }
892949
@@ -899,7 +956,7 @@ struct StackCodegen {
899956 return " \( raw: typeName) < \( raw: wrappedType. swiftType) >.bridgeJSStackPop() "
900957 case . jsObject( let className? ) :
901958 return " \( raw: typeName) <JSObject>.bridgeJSStackPop().map { \( raw: className) (unsafelyWrapping: $0) } "
902- case . nullable, . void, . namespaceEnum, . closure, . unsafePointer, . swiftProtocol:
959+ case . nullable, . void, . namespaceEnum, . closure, . unsafePointer, . swiftProtocol, . generic :
903960 fatalError ( " Invalid nullable wrapped type: \( wrappedType) " )
904961 }
905962 }
@@ -932,6 +989,8 @@ struct StackCodegen {
932989 return lowerArrayStatements ( elementType: elementType, accessor: accessor, varPrefix: varPrefix)
933990 case . dictionary( let valueType) :
934991 return lowerDictionaryStatements ( valueType: valueType, accessor: accessor, varPrefix: varPrefix)
992+ case . generic:
993+ fatalError ( " Generic type parameters are not supported in exported declarations " )
935994 }
936995 }
937996
@@ -1312,10 +1371,12 @@ struct StructCodegen {
13121371 returnType: . i32
13131372 )
13141373
1315- return [
1374+ var decls : [ DeclSyntax ] = [
13161375 bridgedStructExtension, " \( raw: lowerExternDeclPrinter. lines. joined ( separator: " \n " ) ) " ,
13171376 " \( raw: liftExternDeclPrinter. lines. joined ( separator: " \n " ) ) " ,
13181377 ]
1378+
1379+ return decls
13191380 }
13201381
13211382 private func generateStructLiftCode( structDef: ExportedStruct ) -> [ String ] {
@@ -1593,6 +1654,7 @@ extension BridgeType {
15931654 let effectsStr = ( signature. isAsync ? " async " : " " ) + ( signature. isThrows ? " throws " : " " )
15941655 let closureType = " ( \( paramTypes) ) \( effectsStr) -> \( signature. returnType. swiftType) "
15951656 return useJSTypedClosure ? " JSTypedClosure< \( closureType) > " : closureType
1657+ case . generic( let name) : return name
15961658 }
15971659 }
15981660
@@ -1675,6 +1737,8 @@ extension BridgeType {
16751737 return LiftingIntrinsicInfo ( parameters: [ ( " callbackId " , . i32) ] )
16761738 case . array, . dictionary:
16771739 return LiftingIntrinsicInfo ( parameters: [ ] )
1740+ case . generic:
1741+ throw BridgeJSCoreError ( " Generic type parameters are not supported in exported declarations " )
16781742 }
16791743 }
16801744
@@ -1726,6 +1790,8 @@ extension BridgeType {
17261790 return . jsObject
17271791 case . array, . dictionary:
17281792 return . array
1793+ case . generic:
1794+ throw BridgeJSCoreError ( " Generic type parameters are not supported in exported declarations " )
17291795 }
17301796 }
17311797}
0 commit comments