@@ -16,7 +16,7 @@ public struct ClosureCodegen {
1616 let closureParams = signature . parameters . map { " \( sendingPrefix ) \( $0 . closureSwiftType ) " } . joined (
1717 separator : " , "
1818 )
19- let swiftEffects = ( signature . isAsync ? " async " : " " ) + ( signature . isThrows ? " throws " : " " )
19+ let swiftEffects = ( signature . isAsync ? " async " : " " ) + ( signature . isThrows ? " throws(JSException) " : " " )
2020 let swiftReturnType = signature . returnType . closureSwiftType
2121 return " ( \( closureParams ) ) \( swiftEffects ) -> \( swiftReturnType ) "
2222 }
@@ -73,7 +73,17 @@ public struct ClosureCodegen {
7373 helperEnumDeclPrinter . indent {
7474 helperEnumDeclPrinter . write ( " let callback = JSObject.bridgeJSLiftParameter(callbackId) " )
7575 let parameters : String
76- if signature . parameters . isEmpty {
76+ if signature . isThrows || signature . isAsync {
77+ let sendingPrefix = signature . sendingParameters ? " sending " : " "
78+ let typedParams =
79+ signature . parameters . enumerated ( ) . map { index , paramType in
80+ " param \( index ) : \( sendingPrefix ) \( paramType . closureSwiftType ) "
81+ } . joined ( separator : " , " )
82+ let returnType = signature . returnType . closureSwiftType
83+ let effects =
84+ ( signature . isAsync ? " async " : " " ) + ( signature . isThrows ? " throws(JSException) " : " " )
85+ parameters = " ( \( typedParams ) ) \( effects ) -> \( returnType ) "
86+ } else if signature . parameters . isEmpty {
7787 parameters = " "
7888 } else if signature . parameters . count == 1 {
7989 parameters = " param0 "
@@ -146,22 +156,25 @@ public struct ClosureCodegen {
146156 liftedParams . append ( " \( paramType . swiftType ) .bridgeJSLiftParameter( \( argNames . joined ( separator : " , " ) ) ) " )
147157 }
148158
149- let closureCallExpr = ExprSyntax ( " closure( \( raw : liftedParams . joined ( separator : " , " ) ) ) " )
159+ let tryPrefix = signature . isThrows ? " try " : " "
160+ let closureCallExpr = ExprSyntax ( " \( raw : tryPrefix ) closure( \( raw : liftedParams . joined ( separator : " , " ) ) ) " )
161+ let asyncTryPrefix = ( signature . isThrows ? " try " : " " ) + " await "
162+ let asyncClosureCallExpr = ExprSyntax (
163+ " \( raw : asyncTryPrefix ) closure( \( raw : liftedParams . joined ( separator : " , " ) ) ) "
164+ )
150165
151- let abiReturnWasmType = try signature . returnType . loweringReturnInfo ( ) . returnType
166+ let abiReturnWasmType =
167+ signature . isAsync
168+ ? try BridgeType . jsObject ( nil ) . loweringReturnInfo ( ) . returnType
169+ : try signature . returnType . loweringReturnInfo ( ) . returnType
152170
153171 // Build signature using SwiftSignatureBuilder
154172 let funcSignature = SwiftSignatureBuilder . buildABIFunctionSignature (
155173 abiParameters : abiParams ,
156174 returnType : abiReturnWasmType
157175 )
158176
159- // Build function declaration using helper
160- let funcDecl = SwiftCodePattern . buildExposedFunctionDecl (
161- abiName : abiName ,
162- signature : funcSignature
163- ) { printer in
164- printer . write ( " let closure = Unmanaged< \( boxType ) >.fromOpaque(boxPtr).takeUnretainedValue().closure " )
177+ let emitCallAndLower : ( CodeFragmentPrinter ) -> Void = { printer in
165178 if signature . returnType == . void {
166179 printer . write ( closureCallExpr . description )
167180 } else {
@@ -189,6 +202,79 @@ public struct ClosureCodegen {
189202 }
190203 }
191204
205+ let emitAsyncCallAndLower : ( CodeFragmentPrinter ) -> Void = { printer in
206+ printer . write ( " let closure = Unmanaged< \( boxType ) >.fromOpaque(boxPtr).takeUnretainedValue().closure " )
207+ let resolveType = signature . returnType
208+ let resolveName = " Promise_resolve_ \( resolveType . mangleTypeName ) "
209+ let rejectName = " Promise_reject "
210+ let closureHead : String
211+ if signature . isThrows {
212+ let returnSpelling = resolveType == . void ? " " : " -> \( resolveType . closureSwiftType ) "
213+ closureHead = " () async throws(JSException) \( returnSpelling ) in "
214+ } else {
215+ closureHead = " "
216+ }
217+ printer . write ( " return _bjs_makePromise(resolve: \( resolveName ) , reject: \( rejectName ) ) { \( closureHead ) " )
218+ printer . indent {
219+ if resolveType == . void {
220+ printer . write ( asyncClosureCallExpr . description )
221+ } else {
222+ printer . write ( " return \( asyncClosureCallExpr ) " )
223+ }
224+ }
225+ printer . write ( " } " )
226+ }
227+
228+ let catchPlaceholderStmt = abiReturnWasmType ? . swiftReturnPlaceholderStmt
229+
230+ // Build function declaration using helper
231+ let funcDecl = SwiftCodePattern . buildExposedFunctionDecl (
232+ abiName : abiName ,
233+ signature : funcSignature
234+ ) { printer in
235+ if signature . isAsync {
236+ emitAsyncCallAndLower ( printer )
237+ } else if signature . isThrows {
238+ printer . write (
239+ " let closure = Unmanaged< \( boxType ) >.fromOpaque(boxPtr).takeUnretainedValue().closure "
240+ )
241+ printer . write ( " do { " )
242+ printer . indent {
243+ emitCallAndLower ( printer )
244+ }
245+ printer . write ( " } catch let error { " )
246+ printer . indent {
247+ printer . write ( " if let error = error.thrownValue.object { " )
248+ printer . indent {
249+ printer . write ( " withExtendedLifetime(error) { " )
250+ printer . indent {
251+ printer . write ( " _swift_js_throw(Int32(bitPattern: $0.id)) " )
252+ }
253+ printer . write ( " } " )
254+ }
255+ printer . write ( " } else { " )
256+ printer . indent {
257+ printer . write ( " let jsError = JSError(message: error.description) " )
258+ printer . write ( " withExtendedLifetime(jsError.jsObject) { " )
259+ printer . indent {
260+ printer . write ( " _swift_js_throw(Int32(bitPattern: $0.id)) " )
261+ }
262+ printer . write ( " } " )
263+ }
264+ printer . write ( " } " )
265+ if let catchPlaceholderStmt {
266+ printer . write ( catchPlaceholderStmt )
267+ }
268+ }
269+ printer . write ( " } " )
270+ } else {
271+ printer . write (
272+ " let closure = Unmanaged< \( boxType ) >.fromOpaque(boxPtr).takeUnretainedValue().closure "
273+ )
274+ emitCallAndLower ( printer )
275+ }
276+ }
277+
192278 return DeclSyntax ( funcDecl )
193279 }
194280
0 commit comments