@@ -1497,12 +1497,12 @@ public class ExportSwift {
14971497 }
14981498
14991499 for signature in closureSignatures. sorted ( by: { $0. mangleName < $1. mangleName } ) {
1500- decls. append ( try closureCodegen. renderClosureHelper ( signature: signature) )
1500+ decls. append ( contentsOf : try closureCodegen. renderClosureHelper ( signature: signature) )
15011501 decls. append ( try closureCodegen. renderClosureInvokeHandler ( signature: signature) )
15021502 }
15031503
15041504 for proto in exportedProtocols {
1505- decls. append ( try renderProtocolWrapper ( protocol: proto) )
1505+ decls. append ( contentsOf : try renderProtocolWrapper ( protocol: proto) )
15061506 }
15071507
15081508 for enumDef in exportedEnums {
@@ -1547,6 +1547,7 @@ public class ExportSwift {
15471547 var parameters : [ Parameter ] = [ ]
15481548 var abiParameterSignatures : [ ( name: String , type: WasmCoreType ) ] = [ ]
15491549 var abiReturnType : WasmCoreType ?
1550+ var externDecls : [ DeclSyntax ] = [ ]
15501551 let effects : Effects
15511552
15521553 init ( effects: Effects ) {
@@ -1839,7 +1840,7 @@ public class ExportSwift {
18391840 return lines. isEmpty ? " " : lines. joined ( separator: " \n " ) + " \n "
18401841 }
18411842
1842- func renderClosureHelper( signature: ClosureSignature ) throws -> DeclSyntax {
1843+ func renderClosureHelper( signature: ClosureSignature ) throws -> [ DeclSyntax ] {
18431844 let mangledName = signature. mangleName
18441845 let helperName = " _BJS_Closure_ \( mangledName) "
18451846 let boxClassName = " _BJS_ClosureBox_ \( mangledName) "
@@ -1899,25 +1900,31 @@ public class ExportSwift {
18991900 invokeReturnType = " Void "
19001901 }
19011902
1903+ let externName = " invoke_js_callback_ \( signature. moduleName) _ \( mangledName) "
1904+
19021905 let returnLifting : String
19031906 if signature. returnType == . void {
1904- returnLifting = " _invoke (\( invokeCallArgs. joined ( separator: " , " ) ) ) "
1907+ returnLifting = " \( externName ) ( \( invokeCallArgs. joined ( separator: " , " ) ) ) "
19051908 } else if case . optional = signature. returnType {
19061909 returnLifting = """
1907- _invoke ( \( invokeCallArgs. joined ( separator: " , " ) ) )
1910+ \( externName ) ( \( invokeCallArgs. joined ( separator: " , " ) ) )
19081911 return \( signature. returnType. swiftType) .bridgeJSLiftReturnFromSideChannel()
19091912 """
19101913 } else {
19111914 returnLifting = """
1912- let resultId = _invoke ( \( invokeCallArgs. joined ( separator: " , " ) ) )
1915+ let resultId = \( externName ) ( \( invokeCallArgs. joined ( separator: " , " ) ) )
19131916 return \( signature. returnType. swiftType) .bridgeJSLiftReturn(resultId)
19141917 """
19151918 }
19161919
1917- let externName = " invoke_js_callback_ \( signature. moduleName) _ \( mangledName) "
19181920 let optionalLoweringCode = try generateOptionalParameterLowering ( signature: signature)
19191921
1920- return """
1922+ let externDecl : DeclSyntax = """
1923+ @_extern(wasm, module: " bjs " , name: " \( raw: externName) " )
1924+ fileprivate func \( raw: externName) ( \( raw: invokeSignature) ) -> \( raw: invokeReturnType)
1925+ """
1926+
1927+ let boxDecl : DeclSyntax = """
19211928 private final class \( raw: boxClassName) : _BridgedSwiftClosureBox {
19221929 let closure: \( raw: closureType)
19231930 init(_ closure: @escaping \( raw: closureType) ) {
@@ -1935,16 +1942,15 @@ public class ExportSwift {
19351942 let callback = JSObject.bridgeJSLiftParameter(callbackId)
19361943 return { [callback] \( raw: signature. parameters. indices. map { " param \( $0) " } . joined ( separator: " , " ) ) in
19371944 #if arch(wasm32)
1938- @_extern(wasm, module: " bjs " , name: " \( raw: externName) " )
1939- func _invoke( \( raw: invokeSignature) ) -> \( raw: invokeReturnType)
19401945 \( raw: optionalLoweringCode) \( raw: returnLifting)
19411946 #else
19421947 fatalError( " Only available on WebAssembly " )
1943- #endif
1948+ #endif
19441949 }
19451950 }
19461951 }
19471952 """
1953+ return [ externDecl, boxDecl]
19481954 }
19491955
19501956 func renderClosureInvokeHandler( signature: ClosureSignature ) throws -> DeclSyntax {
@@ -2051,28 +2057,28 @@ public class ExportSwift {
20512057 func renderAssociatedValueEnumHelpers( _ enumDef: ExportedEnum ) -> DeclSyntax {
20522058 let typeName = enumDef. swiftCallName
20532059 return """
2054- extension \( raw: typeName) : _BridgedSwiftAssociatedValueEnum {
2060+ extension \( raw: typeName) : _BridgedSwiftAssociatedValueEnum {
20552061 private static func _bridgeJSLiftFromCaseId(_ caseId: Int32) -> \( raw: typeName) {
20562062 switch caseId {
20572063 \( raw: generateStackLiftSwitchCases ( enumDef: enumDef) . joined ( separator: " \n " ) )
20582064 default: fatalError( " Unknown \( raw: typeName) case ID: \\ (caseId) " )
20592065 }
20602066 }
2061-
2067+
20622068 // MARK: Protocol Export
2063-
2069+
20642070 @_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerParameter() -> Int32 {
20652071 switch self {
20662072 \( raw: generateLowerParameterSwitchCases ( enumDef: enumDef) . joined ( separator: " \n " ) )
20672073 }
20682074 }
2069-
2075+
20702076 @_spi(BridgeJS) @_transparent public static func bridgeJSLiftReturn(_ caseId: Int32) -> \( raw: typeName) {
20712077 return _bridgeJSLiftFromCaseId(caseId)
20722078 }
2073-
2079+
20742080 // MARK: ExportSwift
2075-
2081+
20762082 @_spi(BridgeJS) @_transparent public static func bridgeJSLiftParameter(_ caseId: Int32) -> \( raw: typeName) {
20772083 return _bridgeJSLiftFromCaseId(caseId)
20782084 }
@@ -2460,7 +2466,7 @@ public class ExportSwift {
24602466 }
24612467
24622468 // Generate ConvertibleToJSValue extension
2463- decls. append ( renderConvertibleToJSValueExtension ( klass: klass) )
2469+ decls. append ( contentsOf : renderConvertibleToJSValueExtension ( klass: klass) )
24642470
24652471 return decls
24662472 }
@@ -2501,36 +2507,40 @@ public class ExportSwift {
25012507 /// }
25022508 /// }
25032509 /// ```
2504- func renderConvertibleToJSValueExtension( klass: ExportedClass ) -> DeclSyntax {
2510+ func renderConvertibleToJSValueExtension( klass: ExportedClass ) -> [ DeclSyntax ] {
25052511 let wrapFunctionName = " _bjs_ \( klass. name) _wrap "
25062512 let externFunctionName = " bjs_ \( klass. name) _wrap "
25072513
25082514 // If the class has an explicit access control, we need to add it to the extension declaration.
25092515 let accessControl = klass. explicitAccessControl. map { " \( $0) " } ?? " "
2510- return """
2516+ let extensionDecl : DeclSyntax = """
25112517 extension \( raw: klass. swiftCallName) : ConvertibleToJSValue, _BridgedSwiftHeapObject {
25122518 \( raw: accessControl) var jsValue: JSValue {
2513- #if arch(wasm32)
2514- @_extern(wasm, module: " \( raw: moduleName) " , name: " \( raw: externFunctionName) " )
2515- func \( raw: wrapFunctionName) (_: UnsafeMutableRawPointer) -> Int32
2516- #else
2517- func \( raw: wrapFunctionName) (_: UnsafeMutableRawPointer) -> Int32 {
2518- fatalError( " Only available on WebAssembly " )
2519- }
2520- #endif
25212519 return .object(JSObject(id: UInt32(bitPattern: \( raw: wrapFunctionName) (Unmanaged.passRetained(self).toOpaque()))))
25222520 }
25232521 }
25242522 """
2523+ let externDecl : DeclSyntax = """
2524+ #if arch(wasm32)
2525+ @_extern(wasm, module: " \( raw: moduleName) " , name: " \( raw: externFunctionName) " )
2526+ fileprivate func \( raw: wrapFunctionName) (_: UnsafeMutableRawPointer) -> Int32
2527+ #else
2528+ fileprivate func \( raw: wrapFunctionName) (_: UnsafeMutableRawPointer) -> Int32 {
2529+ fatalError( " Only available on WebAssembly " )
2530+ }
2531+ #endif
2532+ """
2533+ return [ extensionDecl, externDecl]
25252534 }
25262535
25272536 /// Creates a struct that wraps a JSObject and implements protocol methods
25282537 /// by calling `@_extern(wasm)` functions that forward to JavaScript via JSObject ID
2529- func renderProtocolWrapper( protocol proto: ExportedProtocol ) throws -> DeclSyntax {
2538+ func renderProtocolWrapper( protocol proto: ExportedProtocol ) throws -> [ DeclSyntax ] {
25302539 let wrapperName = " Any \( proto. name) "
25312540 let protocolName = proto. name
25322541
25332542 var methodDecls : [ DeclSyntax ] = [ ]
2543+ var externDecls : [ DeclSyntax ] = [ ]
25342544
25352545 for method in proto. methods {
25362546 var swiftParams : [ String ] = [ ]
@@ -2617,10 +2627,16 @@ public class ExportSwift {
26172627 """
26182628 }
26192629 }
2630+
2631+ externDecls. append (
2632+ """
2633+ @_extern(wasm, module: " \( raw: moduleName) " , name: " \( raw: method. abiName) " )
2634+ fileprivate func _extern_ \( raw: method. name) ( \( raw: externParams. joined ( separator: " , " ) ) ) \( raw: externReturnType)
2635+ """
2636+ )
2637+
26202638 let methodImplementation : DeclSyntax = """
26212639 func \( raw: method. name) ( \( raw: swiftParams. joined ( separator: " , " ) ) ) \( raw: returnTypeStr) {
2622- @_extern(wasm, module: " \( raw: moduleName) " , name: " \( raw: method. abiName) " )
2623- func _extern_ \( raw: method. name) ( \( raw: externParams. joined ( separator: " , " ) ) ) \( raw: externReturnType)
26242640 \( raw: callCode)
26252641 }
26262642 """
@@ -2631,34 +2647,36 @@ public class ExportSwift {
26312647 var propertyDecls : [ DeclSyntax ] = [ ]
26322648
26332649 for property in proto. properties {
2634- let propertyImpl = try renderProtocolProperty (
2650+ let ( propertyImpl, propertyExternDecls ) = try renderProtocolProperty (
26352651 property: property,
26362652 protocolName: protocolName,
26372653 moduleName: moduleName
26382654 )
26392655 propertyDecls. append ( propertyImpl)
2656+ externDecls. append ( contentsOf: propertyExternDecls)
26402657 }
26412658
26422659 let allDecls = ( methodDecls + propertyDecls) . map { $0. description } . joined ( separator: " \n \n " )
26432660
2644- return """
2661+ let structDecl : DeclSyntax = """
26452662 struct \( raw: wrapperName) : \( raw: protocolName) , _BridgedSwiftProtocolWrapper {
26462663 let jsObject: JSObject
2647-
2664+
26482665 \( raw: allDecls)
2649-
2666+
26502667 static func bridgeJSLiftParameter(_ value: Int32) -> Self {
26512668 return \( raw: wrapperName) (jsObject: JSObject(id: UInt32(bitPattern: value)))
26522669 }
26532670 }
26542671 """
2672+ return [ structDecl] + externDecls
26552673 }
26562674
26572675 private func renderProtocolProperty(
26582676 property: ExportedProtocolProperty ,
26592677 protocolName: String ,
26602678 moduleName: String
2661- ) throws -> DeclSyntax {
2679+ ) throws -> ( propertyDecl : DeclSyntax , externDecls : [ DeclSyntax ] ) {
26622680 let getterAbiName = ABINameGenerator . generateABIName (
26632681 baseName: property. name,
26642682 operation: " get " ,
@@ -2679,33 +2697,39 @@ public class ExportSwift {
26792697 // Optional case/raw enums use side-channel reading (Void return)
26802698 getterReturnType = " "
26812699 getterBody = """
2682- _extern_get (this: Int32(bitPattern: jsObject.id))
2700+ \( getterAbiName ) (this: Int32(bitPattern: jsObject.id))
26832701 return \( property. type. swiftType) .bridgeJSLiftReturnFromSideChannel()
26842702 """
26852703 } else if let abiType = liftingInfo. valueToLift {
26862704 getterReturnType = " -> \( abiType. swiftType) "
26872705 getterBody = """
2688- let ret = _extern_get (this: Int32(bitPattern: jsObject.id))
2706+ let ret = \( getterAbiName ) (this: Int32(bitPattern: jsObject.id))
26892707 return \( property. type. swiftType) .bridgeJSLiftReturn(ret)
26902708 """
26912709 } else {
26922710 getterReturnType = " "
26932711 getterBody = """
2694- _extern_get (this: Int32(bitPattern: jsObject.id))
2712+ \( getterAbiName ) (this: Int32(bitPattern: jsObject.id))
26952713 return \( property. type. swiftType) .bridgeJSLiftReturn()
26962714 """
26972715 }
26982716
2717+ let getterExternDecl : DeclSyntax = """
2718+ @_extern(wasm, module: " \( raw: moduleName) " , name: " \( raw: getterAbiName) " )
2719+ fileprivate func \( raw: getterAbiName) (this: Int32) \( raw: getterReturnType)
2720+ """
2721+
26992722 if property. isReadonly {
2700- return """
2723+ return (
2724+ """
27012725 var \( raw: property. name) : \( raw: property. type. swiftType) {
27022726 get {
2703- @_extern(wasm, module: " \( raw: moduleName) " , name: " \( raw: getterAbiName) " )
2704- func _extern_get(this: Int32) \( raw: getterReturnType)
27052727 \( raw: getterBody)
27062728 }
27072729 }
2708- """
2730+ """ ,
2731+ [ getterExternDecl]
2732+ )
27092733 } else {
27102734 let loweringInfo = try property. type. loweringParameterInfo ( context: . exportSwift)
27112735
@@ -2720,28 +2744,32 @@ public class ExportSwift {
27202744 let wrappedParam = loweringInfo. loweredParameters [ 1 ] . name
27212745 setterBody = """
27222746 let ( \( isSomeParam) , \( wrappedParam) ) = newValue.bridgeJSLowerParameterWithPresence()
2723- _extern_set (this: Int32(bitPattern: jsObject.id), \( isSomeParam) : \( isSomeParam) , \( wrappedParam) : \( wrappedParam) )
2747+ \( setterAbiName ) (this: Int32(bitPattern: jsObject.id), \( isSomeParam) : \( isSomeParam) , \( wrappedParam) : \( wrappedParam) )
27242748 """
27252749 } else {
27262750 let paramName = loweringInfo. loweredParameters [ 0 ] . name
27272751 setterBody =
2728- " _extern_set (this: Int32(bitPattern: jsObject.id), \( paramName) : newValue.bridgeJSLowerParameter()) "
2752+ " \( setterAbiName ) (this: Int32(bitPattern: jsObject.id), \( paramName) : newValue.bridgeJSLowerParameter()) "
27292753 }
27302754
2731- return """
2755+ let setterExternDecl : DeclSyntax = """
2756+ @_extern(wasm, module: " \( raw: moduleName) " , name: " \( raw: setterAbiName) " )
2757+ fileprivate func \( raw: setterAbiName) ( \( raw: setterParams) )
2758+ """
2759+
2760+ return (
2761+ """
27322762 var \( raw: property. name) : \( raw: property. type. swiftType) {
27332763 get {
2734- @_extern(wasm, module: " \( raw: moduleName) " , name: " \( raw: getterAbiName) " )
2735- func _extern_get(this: Int32) \( raw: getterReturnType)
27362764 \( raw: getterBody)
27372765 }
27382766 set {
2739- @_extern(wasm, module: " \( raw: moduleName) " , name: " \( raw: setterAbiName) " )
2740- func _extern_set( \( raw: setterParams) )
27412767 \( raw: setterBody)
27422768 }
27432769 }
2744- """
2770+ """ ,
2771+ [ getterExternDecl, setterExternDecl]
2772+ )
27452773 }
27462774 }
27472775}
0 commit comments