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