@@ -91,6 +91,13 @@ public class ExportSwift {
9191 }
9292 }
9393
94+ withSpan ( " Render Generic Bridgeable Conformances " ) { [ self ] in
95+ let genericConformanceCodegen = GenericConformanceCodegen ( )
96+ for entry in skeleton . genericBridgeableTypeEntries {
97+ decls . append ( contentsOf : genericConformanceCodegen . renderConformance ( typeName : entry . swiftName ) )
98+ }
99+ }
100+
94101 try withSpan ( " Render Async Promise Helpers " ) { [ self ] in
95102 let asyncResolveTypes = skeleton . asyncPromiseResolveReturnTypes
96103 if ! asyncResolveTypes . isEmpty {
@@ -875,6 +882,57 @@ public class ExportSwift {
875882 }
876883}
877884
885+ // MARK: - GenericConformanceCodegen
886+
887+ struct GenericConformanceCodegen {
888+ func renderConformance ( typeName : String ) -> [ DeclSyntax ] {
889+ let printer = CodeFragmentPrinter ( )
890+ printer . write ( " extension \( typeName ) : BridgedSwiftGenericBridgeable { " )
891+ printer . indent {
892+ printer . write (
893+ " @_spi(BridgeJS) public static let bridgeJSTypeHandle = \( typeName ) .bridgeJSMakeTypeHandle() "
894+ )
895+ }
896+ printer . write ( " } " )
897+ return [ " \( raw : printer . lines . joined ( separator : " \n " ) ) " ]
898+ }
899+ }
900+
901+ // MARK: - GenericTypeRegistrationCodegen
902+
903+ public struct GenericTypeRegistrationCodegen {
904+ public init ( ) { }
905+
906+ public func render ( for skeleton : BridgeJSSkeleton ) -> String ? {
907+ guard let entries = skeleton . typeRegistrationEntries else { return nil }
908+ let abiName = ABINameGenerator . typeRegistrationFunctionName ( moduleName : skeleton . moduleName )
909+ let printer = CodeFragmentPrinter ( )
910+ printer . write ( " #if arch(wasm32) " )
911+ printer . write ( " @_extern(wasm, module: \" bjs \" , name: \" \( abiName ) \" ) " )
912+ printer . write ( " fileprivate func _ \( abiName ) _extern(_ base: UnsafePointer<Int32>?, _ count: Int32) " )
913+ printer . nextLine ( )
914+ printer . write ( " @_expose(wasm, \" \( abiName ) \" ) " )
915+ printer . write ( " public func _ \( abiName ) () { " )
916+ printer . indent {
917+ printer . write ( " let typeIds: [Int32] = [ " )
918+ printer . indent {
919+ for entry in entries {
920+ printer . write ( " \( entry . swiftName ) .bridgeJSTypeID, " )
921+ }
922+ }
923+ printer . write ( " ] " )
924+ printer . write ( " typeIds.withUnsafeBufferPointer { buffer in " )
925+ printer . indent {
926+ printer . write ( " _ \( abiName ) _extern(buffer.baseAddress, Int32(buffer.count)) " )
927+ }
928+ printer . write ( " } " )
929+ }
930+ printer . write ( " } " )
931+ printer . write ( " #endif " )
932+ return printer . lines . joined ( separator : " \n " )
933+ }
934+ }
935+
878936// MARK: - StackCodegen
879937
880938/// Helper for stack-based lifting and lowering operations.
@@ -896,6 +954,10 @@ struct StackCodegen {
896954 return " JSObject.bridgeJSStackPop() "
897955 case . void , . namespaceEnum :
898956 return " () "
957+ case . generic :
958+ fatalError (
959+ " Generic parameters are only supported on imported declarations, not exported concrete-type codegen "
960+ )
899961 }
900962 }
901963
@@ -908,7 +970,7 @@ struct StackCodegen {
908970 return " \( raw : typeName ) < \( raw : wrappedType . swiftType ) >.bridgeJSStackPop() "
909971 case . jsObject ( let className ? ) :
910972 return " \( raw : typeName ) <JSObject>.bridgeJSStackPop().map { \( raw : className ) (unsafelyWrapping: $0) } "
911- case . nullable , . void , . namespaceEnum , . closure , . unsafePointer , . swiftProtocol :
973+ case . nullable , . void , . namespaceEnum , . closure , . unsafePointer , . swiftProtocol , . generic :
912974 fatalError ( " Invalid nullable wrapped type: \( wrappedType ) " )
913975 }
914976 }
@@ -941,6 +1003,10 @@ struct StackCodegen {
9411003 return lowerArrayStatements ( elementType : elementType , accessor : accessor , varPrefix : varPrefix )
9421004 case . dictionary ( let valueType ) :
9431005 return lowerDictionaryStatements ( valueType : valueType , accessor : accessor , varPrefix : varPrefix )
1006+ case . generic :
1007+ fatalError (
1008+ " Generic parameters are only supported on imported declarations, not exported concrete-type codegen "
1009+ )
9441010 }
9451011 }
9461012
@@ -1596,12 +1662,34 @@ extension BridgeType {
15961662 case . associatedValueEnum :
15971663 return [ " _BridgedSwiftAssociatedValueEnum " ]
15981664 case . rawValueEnum , . void , . unsafePointer , . namespaceEnum ,
1599- . swiftProtocol , . closure , . nullable , . array , . dictionary , . alias :
1665+ . swiftProtocol , . closure , . nullable , . array , . dictionary , . alias , . generic :
16001666 // Not supported yet.
16011667 return nil
16021668 }
16031669 }
16041670
1671+ /// Stack expressions for bare `T` and `T?`, the only generic shapes that
1672+ /// cannot reuse the concrete emission: `bridgeJSLowerParameter()` names
1673+ /// per-type members that the generic constraint erases to the stack, so
1674+ /// `bridgeJSStackPush()`/`bridgeJSStackPop()` is the shared spelling.
1675+ /// `[T]` and `[String: T]` go through the ordinary paths via the `Array`
1676+ /// and `Dictionary` stack conformances.
1677+ var genericStackPopExpression : String ? {
1678+ switch self {
1679+ case . generic ( let name ) : return " \( name ) .bridgeJSStackPop() "
1680+ case . nullable ( . generic ( let name ) , _) : return " Optional< \( name ) >.bridgeJSStackPop() "
1681+ default : return nil
1682+ }
1683+ }
1684+
1685+ func genericStackPushStatement ( value : String ) -> String ? {
1686+ switch self {
1687+ case . generic , . nullable ( . generic , _) :
1688+ return " \( value ) .bridgeJSStackPush() "
1689+ default : return nil
1690+ }
1691+ }
1692+
16051693 var swiftType : String {
16061694 switch self {
16071695 case . bool : return " Bool "
@@ -1631,6 +1719,7 @@ extension BridgeType {
16311719 let closureType = " ( \( paramTypes ) ) \( effectsStr ) -> \( signature . returnType . swiftType ) "
16321720 return useJSTypedClosure ? " JSTypedClosure< \( closureType ) > " : closureType
16331721 case . alias ( let name , _) : return name
1722+ case . generic ( let name ) : return name
16341723 }
16351724 }
16361725
@@ -1717,6 +1806,10 @@ extension BridgeType {
17171806 return LiftingIntrinsicInfo ( parameters : [ ] )
17181807 case . alias ( _, let underlying ) :
17191808 return try underlying . liftParameterInfo ( )
1809+ case . generic :
1810+ throw BridgeJSCoreError (
1811+ " Generic parameters are only supported on imported declarations, not exported concrete-type codegen "
1812+ )
17201813 }
17211814 }
17221815
@@ -1770,6 +1863,10 @@ extension BridgeType {
17701863 return . array
17711864 case . alias ( _, let underlying ) :
17721865 return try underlying . loweringReturnInfo ( )
1866+ case . generic :
1867+ throw BridgeJSCoreError (
1868+ " Generic parameters are only supported on imported declarations, not exported concrete-type codegen "
1869+ )
17731870 }
17741871 }
17751872}
0 commit comments