@@ -79,6 +79,7 @@ import Testing
7979 }
8080
8181 @Test ( arguments: [
82+ " GenericInitializers.swift " ,
8283 " Namespaces.swift " ,
8384 " StaticFunctions.swift " ,
8485 " StaticProperties.swift " ,
@@ -157,6 +158,105 @@ import Testing
157158 return try bridgeJSLink. link ( ) . 0
158159 }
159160
161+ @Test
162+ func genericRuntimeIsGatedToGenericBuilds( ) throws {
163+ let genericJS = try linkedJS ( forFixture: " GenericImports.swift " )
164+ #expect( genericJS. contains ( " __bjs_codecByTypeId " ) )
165+ #expect( genericJS. contains ( " function __bjs_codecForTypeId(typeId) { " ) )
166+ #expect( genericJS. contains ( " bjs[ \" bjs_TestModule_register_type_handles \" ] = function(base, count) { " ) )
167+ #expect( genericJS. contains ( " instance.exports[ \" bjs_TestModule_register_type_handles \" ](); " ) )
168+
169+ let nonGenericJS = try linkedJS ( forFixture: " SwiftStructImports.swift " )
170+ #expect( !nonGenericJS. contains ( " __bjs_codecByTypeId " ) )
171+ #expect( !nonGenericJS. contains ( " __bjs_codecForTypeId " ) )
172+ #expect( nonGenericJS. contains ( " bjs[ \" bjs_core_register_type_handles \" ] = function() {}; " ) )
173+ #expect( nonGenericJS. contains ( " bjs[ \" bjs_TestModule_register_type_handles \" ] = function() {}; " ) )
174+ #expect( !nonGenericJS. contains ( " instance.exports[ \" bjs_TestModule_register_type_handles \" ](); " ) )
175+ }
176+
177+ @Test ( arguments: [
178+ " @JS func identity<T: BridgedSwiftGenericBridgeable>(_ value: T) -> T { value } " ,
179+ " @JS class Box { @JS func identity<T: BridgedSwiftGenericBridgeable>(_ value: T) -> T { value } } " ,
180+ " @JS class Box { @JS init<T: BridgedSwiftGenericBridgeable>(_ value: T) {} } " ,
181+ ] )
182+ func genericExportsEnableCoreTypeRegistration( source: String ) throws {
183+ let js = try linkSource ( source) . js
184+ #expect( js. contains ( " __bjs_typeIdByToken.set(tokens[i], typeIds[i]); " ) )
185+ #expect( js. contains ( " instance.exports[ \" bjs_core_register_type_handles \" ](); " ) )
186+ }
187+
188+ @Test
189+ func sameTypeNameAcrossModulesLinksWithHandleIdentity( ) throws {
190+ func makeSkeleton( moduleName: String , source: String ) throws -> BridgeJSSkeleton {
191+ let swiftAPI = SwiftToSkeleton (
192+ progress: . silent,
193+ moduleName: moduleName,
194+ exposeToGlobal: false ,
195+ externalModuleIndex: . empty
196+ )
197+ swiftAPI. addSourceFile ( Parser . parse ( source: source) , inputFilePath: " \( moduleName) .swift " )
198+ return try swiftAPI. finalize ( )
199+ }
200+ let structSource = """
201+ @JS public struct Point {
202+ public var x: Int
203+ @JS public init(x: Int) { self.x = x }
204+ }
205+ """
206+ let first = try makeSkeleton (
207+ moduleName: " FirstModule " ,
208+ source: structSource + """
209+
210+ @JSFunction func identity<T: BridgedSwiftGenericBridgeable>(_ value: T) throws(JSException) -> T
211+ """
212+ )
213+ let second = try makeSkeleton ( moduleName: " SecondModule " , source: structSource)
214+ let bridgeJSLink = BridgeJSLink ( skeletons: [ first, second] )
215+ let js = try bridgeJSLink. link ( ) . outputJs
216+ #expect( js. contains ( " bjs[ \" bjs_FirstModule_register_type_handles \" ] = function(base, count) { " ) )
217+ #expect( js. contains ( " bjs[ \" bjs_SecondModule_register_type_handles \" ] = function(base, count) { " ) )
218+ }
219+
220+ @Test ( arguments: [ false , true ] )
221+ func sameTypeNameAcrossModulesFailsWithGenericExports( distinctNamespaces: Bool ) throws {
222+ func makeSkeleton( moduleName: String , source: String ) throws -> BridgeJSSkeleton {
223+ let swiftAPI = SwiftToSkeleton (
224+ progress: . silent,
225+ moduleName: moduleName,
226+ exposeToGlobal: false ,
227+ externalModuleIndex: . empty
228+ )
229+ swiftAPI. addSourceFile ( Parser . parse ( source: source) , inputFilePath: " \( moduleName) .swift " )
230+ return try swiftAPI. finalize ( )
231+ }
232+ let structSource = """
233+ @JS public struct Point {
234+ public var x: Int
235+ @JS public init(x: Int) { self.x = x }
236+ }
237+ """
238+ let first = try makeSkeleton (
239+ moduleName: " FirstModule " ,
240+ source: structSource + """
241+
242+ @JS public func identity<T: BridgedSwiftGenericBridgeable>(_ value: T) -> T { value }
243+ """
244+ )
245+ let second = try makeSkeleton (
246+ moduleName: " SecondModule " ,
247+ source: distinctNamespaces
248+ ? structSource. replacingOccurrences (
249+ of: " @JS public struct " ,
250+ with: " @JS(namespace: \" Other \" ) public struct "
251+ )
252+ : structSource
253+ )
254+ let bridgeJSLink = BridgeJSLink ( skeletons: [ first, second] )
255+ #expect( throws: BridgeJSLinkError . self) {
256+ _ = try bridgeJSLink. link ( )
257+ }
258+ }
259+
160260 @Test
161261 func perClassIdentityModeFromAnnotation( ) throws {
162262 let url = Self . inputsDirectory. appendingPathComponent ( " IdentityModeClass.swift " )
0 commit comments