@@ -16,7 +16,7 @@ public struct ClosureCodegen {
1616
1717 func collectClosureSignatures ( from type : BridgeType , into signatures : inout Set < ClosureSignature > ) {
1818 switch type {
19- case . closure ( let signature ) :
19+ case . closure ( let signature , _ ) :
2020 signatures . insert ( signature )
2121 for paramType in signature . parameters {
2222 collectClosureSignatures ( from : paramType , into : & signatures )
@@ -32,15 +32,14 @@ public struct ClosureCodegen {
3232 func renderClosureHelpers ( _ signature : ClosureSignature ) throws -> [ DeclSyntax ] {
3333 let mangledName = signature . mangleName
3434 let helperName = " _BJS_Closure_ \( mangledName ) "
35- let boxClassName = " _BJS_ClosureBox_ \( mangledName ) "
3635
3736 let closureParams = signature . parameters . enumerated ( ) . map { _ , type in
3837 " \( type . swiftType ) "
3938 } . joined ( separator : " , " )
4039
4140 let swiftEffects = ( signature . isAsync ? " async " : " " ) + ( signature . isThrows ? " throws " : " " )
4241 let swiftReturnType = signature . returnType . swiftType
43- let closureType = " ( \( closureParams ) ) \( swiftEffects ) -> \( swiftReturnType ) "
42+ let swiftClosureType = " ( \( closureParams ) ) \( swiftEffects ) -> \( swiftReturnType ) "
4443
4544 let externName = " invoke_js_callback_ \( signature . moduleName ) _ \( mangledName ) "
4645
@@ -69,13 +68,15 @@ public struct ClosureCodegen {
6968 // Generate extern declaration using CallJSEmission
7069 let externDecl = builder . renderImportDecl ( )
7170
72- let boxClassDecl : DeclSyntax = """
73- private final class \( raw : boxClassName ) : _BridgedSwiftClosureBox {
74- let closure: \( raw : closureType )
75- init(_ closure: @escaping \( raw : closureType ) ) {
76- self.closure = closure
77- }
71+ let makeClosureExternDecl : DeclSyntax = """
72+ #if arch(wasm32)
73+ @_extern(wasm, module: " bjs " , name: " make_swift_closure_ \( raw : signature . moduleName ) _ \( raw : signature . mangleName ) " )
74+ fileprivate func make_swift_closure_ \( raw : signature . moduleName ) _ \( raw : signature . mangleName ) (_ boxPtr: UnsafeMutableRawPointer) -> Int32
75+ #else
76+ fileprivate func make_swift_closure_ \( raw : signature . moduleName ) _ \( raw : signature . mangleName ) (_ boxPtr: UnsafeMutableRawPointer) -> Int32 {
77+ fatalError( " Only available on WebAssembly " )
7878 }
79+ #endif
7980 """
8081
8182 let helperEnumDecl = EnumDeclSyntax (
@@ -84,33 +85,6 @@ public struct ClosureCodegen {
8485 } ,
8586 name : . identifier ( helperName ) ,
8687 memberBlockBuilder : {
87- DeclSyntax (
88- FunctionDeclSyntax (
89- modifiers : DeclModifierListSyntax {
90- DeclModifierSyntax ( name : . keyword ( . static ) )
91- } ,
92- name : . identifier ( " bridgeJSLower " ) ,
93- signature : FunctionSignatureSyntax (
94- parameterClause : FunctionParameterClauseSyntax {
95- FunctionParameterSyntax (
96- firstName : . wildcardToken ( ) ,
97- secondName : . identifier ( " closure " ) ,
98- colon : . colonToken ( ) ,
99- type : TypeSyntax ( " @escaping \( raw : closureType ) " )
100- )
101- } ,
102- returnClause : ReturnClauseSyntax (
103- arrow : . arrowToken ( ) ,
104- type : IdentifierTypeSyntax ( name : . identifier ( " UnsafeMutableRawPointer " ) )
105- )
106- ) ,
107- body : CodeBlockSyntax {
108- " let box = \( raw : boxClassName ) (closure) "
109- " return Unmanaged.passRetained(box).toOpaque() "
110- }
111- )
112- )
113-
11488 DeclSyntax (
11589 FunctionDeclSyntax (
11690 modifiers : DeclModifierListSyntax {
@@ -128,7 +102,7 @@ public struct ClosureCodegen {
128102 } ,
129103 returnClause : ReturnClauseSyntax (
130104 arrow : . arrowToken ( ) ,
131- type : IdentifierTypeSyntax ( name : . identifier ( closureType ) )
105+ type : IdentifierTypeSyntax ( name : . identifier ( swiftClosureType ) )
132106 )
133107 ) ,
134108 body : CodeBlockSyntax {
@@ -178,11 +152,32 @@ public struct ClosureCodegen {
178152 )
179153 }
180154 )
181- return [ externDecl , boxClassDecl , DeclSyntax ( helperEnumDecl ) ]
155+ let typedClosureExtension : DeclSyntax = """
156+ extension JSTypedClosure where Signature == \( raw : swiftClosureType ) {
157+ init(fileID: StaticString = #fileID, line: UInt32 = #line, _ body: @escaping \( raw : swiftClosureType ) ) {
158+ self.init(
159+ makeClosure: make_swift_closure_ \( raw : signature . moduleName ) _ \( raw : signature . mangleName ) ,
160+ body: body,
161+ fileID: fileID,
162+ line: line
163+ )
164+ }
165+ }
166+ """
167+
168+ return [
169+ externDecl , makeClosureExternDecl , DeclSyntax ( helperEnumDecl ) , typedClosureExtension ,
170+ ]
182171 }
183172
184173 func renderClosureInvokeHandler ( _ signature : ClosureSignature ) throws -> DeclSyntax {
185- let boxClassName = " _BJS_ClosureBox_ \( signature . mangleName ) "
174+ let closureParams = signature . parameters . enumerated ( ) . map { _ , type in
175+ " \( type . swiftType ) "
176+ } . joined ( separator : " , " )
177+ let swiftEffects = ( signature . isAsync ? " async " : " " ) + ( signature . isThrows ? " throws " : " " )
178+ let swiftReturnType = signature . returnType . swiftType
179+ let swiftClosureType = " ( \( closureParams ) ) \( swiftEffects ) -> \( swiftReturnType ) "
180+ let boxType = " _BridgeJSTypedClosureBox< \( swiftClosureType ) > "
186181 let abiName = " invoke_swift_closure_ \( signature . moduleName ) _ \( signature . mangleName ) "
187182
188183 // Build ABI parameters directly with WasmCoreType (no string conversion needed)
@@ -205,7 +200,7 @@ public struct ClosureCodegen {
205200 liftedParams . append ( " \( paramType . swiftType ) .bridgeJSLiftParameter( \( argNames . joined ( separator : " , " ) ) ) " )
206201 }
207202
208- let closureCallExpr = ExprSyntax ( " box. closure(\( raw : liftedParams . joined ( separator : " , " ) ) ) " )
203+ let closureCallExpr = ExprSyntax ( " closure( \( raw : liftedParams . joined ( separator : " , " ) ) ) " )
209204
210205 // Determine return type
211206 let abiReturnWasmType : WasmCoreType ?
@@ -217,6 +212,8 @@ public struct ClosureCodegen {
217212 abiReturnWasmType = nil
218213 }
219214
215+ let throwReturn = abiReturnWasmType ? . swiftReturnPlaceholderStmt ?? " return "
216+
220217 // Build signature using SwiftSignatureBuilder
221218 let funcSignature = SwiftSignatureBuilder . buildABIFunctionSignature (
222219 abiParameters : abiParams ,
@@ -225,7 +222,13 @@ public struct ClosureCodegen {
225222
226223 // Build body
227224 let body = CodeBlockItemListSyntax {
228- " let box = Unmanaged< \( raw : boxClassName ) >.fromOpaque(boxPtr).takeUnretainedValue() "
225+ " let box = Unmanaged< \( raw : boxType ) >.fromOpaque(boxPtr).takeUnretainedValue() "
226+ """
227+ guard let closure = box.closure else {
228+ box._bridgeJSThrowReleasedClosure()
229+ \( raw : throwReturn )
230+ }
231+ """
229232 if signature . returnType == . void {
230233 closureCallExpr
231234 } else {
@@ -315,7 +318,7 @@ public struct ClosureCodegen {
315318 for setter in type . setters {
316319 collectClosureSignatures ( from : setter . type , into : & closureSignatures )
317320 }
318- for method in type . methods {
321+ for method in type . methods + type . staticMethods {
319322 collectClosureSignatures ( from : method . parameters , into : & closureSignatures )
320323 collectClosureSignatures ( from : method . returnType , into : & closureSignatures )
321324 }
0 commit comments