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