@@ -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