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