Skip to content

Commit 2536334

Browse files
committed
NFC: BridgeJS: Refactor to descriptor-driven codegen with BridgeTypeDescriptor
1 parent 2c51958 commit 2536334

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+4077
-4944
lines changed

Plugins/BridgeJS/Sources/BridgeJSCore/ClosureCodegen.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,23 +123,23 @@ public struct ClosureCodegen {
123123

124124
for (index, paramType) in signature.parameters.enumerated() {
125125
let paramName = "param\(index)"
126-
let liftInfo = try paramType.liftParameterInfo()
126+
let liftParams = try paramType.liftParameterInfo()
127127

128-
for (argName, wasmType) in liftInfo.parameters {
128+
for (argName, wasmType) in liftParams {
129129
let fullName =
130-
liftInfo.parameters.count > 1 ? "\(paramName)\(argName.capitalizedFirstLetter)" : paramName
130+
liftParams.count > 1 ? "\(paramName)\(argName.capitalizedFirstLetter)" : paramName
131131
abiParams.append((fullName, wasmType))
132132
}
133133

134-
let argNames = liftInfo.parameters.map { (argName, _) in
135-
liftInfo.parameters.count > 1 ? "\(paramName)\(argName.capitalizedFirstLetter)" : paramName
134+
let argNames = liftParams.map { (argName, _) in
135+
liftParams.count > 1 ? "\(paramName)\(argName.capitalizedFirstLetter)" : paramName
136136
}
137137
liftedParams.append("\(paramType.swiftType).bridgeJSLiftParameter(\(argNames.joined(separator: ", ")))")
138138
}
139139

140140
let closureCallExpr = ExprSyntax("closure(\(raw: liftedParams.joined(separator: ", ")))")
141141

142-
let abiReturnWasmType = try signature.returnType.loweringReturnInfo().returnType
142+
let abiReturnWasmType = try signature.returnType.loweringReturnInfo()
143143

144144
// Build signature using SwiftSignatureBuilder
145145
let funcSignature = SwiftSignatureBuilder.buildABIFunctionSignature(

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 112 additions & 288 deletions
Large diffs are not rendered by default.

Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift

Lines changed: 33 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -103,31 +103,27 @@ public struct ImportTS {
103103
}
104104

105105
func lowerParameter(param: Parameter) throws {
106-
let loweringInfo = try param.type.loweringParameterInfo(context: context)
106+
let loweredParams = try param.type.loweringParameterInfo(context: context)
107107

108108
switch param.type {
109109
case .closure(let signature, useJSTypedClosure: false):
110110
let jsTypedClosureType = BridgeType.closure(signature, useJSTypedClosure: true).swiftType
111111
body.write("let \(param.name) = \(jsTypedClosureType)(\(param.name))")
112-
// The just created JSObject is not owned by the caller unlike those passed in parameters,
113-
// so we need to extend its lifetime during the call to ensure the JSObject.id is valid.
114112
valuesToExtendLifetimeDuringCall.append(param.name)
115113
default:
116114
break
117115
}
118116
let initializerExpr = ExprSyntax("\(raw: param.name).bridgeJSLowerParameter()")
119117

120-
if loweringInfo.loweredParameters.isEmpty {
118+
if loweredParams.isEmpty {
121119
stackLoweringStmts.insert("let _ = \(initializerExpr)", at: 0)
122120
return
123121
}
124122

125-
// Generate destructured variable names for all lowered parameters
126-
let destructuredNames = loweringInfo.loweredParameters.map {
123+
let destructuredNames = loweredParams.map {
127124
"\(param.name)\($0.name.capitalizedFirstLetter)"
128125
}
129126

130-
// Always add destructuring statement to body (unified for single and multiple)
131127
let pattern: String
132128
if destructuredNames.count == 1 {
133129
pattern = destructuredNames[0]
@@ -138,31 +134,26 @@ public struct ImportTS {
138134
body.write("let \(pattern) = \(initializerExpr)")
139135
destructuredVarNames.append(contentsOf: destructuredNames)
140136

141-
// Add to signatures and forwardings (unified for both single and multiple)
142-
for (index, (paramName, type)) in loweringInfo.loweredParameters.enumerated() {
143-
// For single parameter, use param.name; for multiple, use constructed name
137+
for (index, (paramName, type)) in loweredParams.enumerated() {
144138
let abiParamName: String
145-
if loweringInfo.loweredParameters.count == 1 {
139+
if loweredParams.count == 1 {
146140
abiParamName = param.name
147141
} else {
148142
abiParamName = "\(param.name)\(paramName.capitalizedFirstLetter)"
149143
}
150144
abiParameterSignatures.append((abiParamName, type))
151-
152-
// Always use destructured variable in call without labels
153-
// Swift allows omitting labels when they match parameter names
154145
abiParameterForwardings.append(destructuredNames[index])
155146
}
156147
}
157148

158149
func call(returnType: BridgeType) throws {
159-
let liftingInfo: BridgeType.LiftingReturnInfo = try returnType.liftingReturnInfo(context: context)
150+
let liftingReturn = try returnType.liftingReturnType(context: context)
160151
for stmt in stackLoweringStmts {
161152
body.write(stmt.description)
162153
}
163154

164155
let assign =
165-
(returnType == .void || returnType.usesSideChannelForOptionalReturn() || liftingInfo.valueToLift == nil)
156+
(returnType == .void || returnType.usesSideChannelForOptionalReturn || liftingReturn == nil)
166157
? "" : "let ret = "
167158
let callExpr = "\(abiName)(\(abiParameterForwardings.joined(separator: ", ")))"
168159

@@ -185,25 +176,24 @@ public struct ImportTS {
185176
}
186177

187178
func liftReturnValue(returnType: BridgeType) throws {
188-
let liftingInfo = try returnType.liftingReturnInfo(context: context)
179+
let liftingReturn = try returnType.liftingReturnType(context: context)
189180

190181
if returnType == .void {
191182
abiReturnType = nil
192183
return
193184
}
194185

195-
if returnType.usesSideChannelForOptionalReturn() {
196-
// Side channel returns: extern function returns Void, value is retrieved via side channel
186+
if returnType.usesSideChannelForOptionalReturn {
197187
abiReturnType = nil
198188
body.write("return \(returnType.swiftType).bridgeJSLiftReturnFromSideChannel()")
199189
} else {
200-
abiReturnType = liftingInfo.valueToLift
190+
abiReturnType = liftingReturn
201191
let liftExpr: String
202192
switch returnType {
203193
case .closure(let signature, _):
204194
liftExpr = "_BJS_Closure_\(signature.mangleName).bridgeJSLift(ret)"
205195
default:
206-
if liftingInfo.valueToLift != nil {
196+
if liftingReturn != nil {
207197
liftExpr = "\(returnType.swiftType).bridgeJSLiftReturn(ret)"
208198
} else {
209199
liftExpr = "\(returnType.swiftType).bridgeJSLiftReturn()"
@@ -693,145 +683,42 @@ enum SwiftCodePattern {
693683
}
694684

695685
extension BridgeType {
696-
struct LoweringParameterInfo {
697-
let loweredParameters: [(name: String, type: WasmCoreType)]
698-
699-
static let bool = LoweringParameterInfo(loweredParameters: [("value", .i32)])
700-
static let int = LoweringParameterInfo(loweredParameters: [("value", .i32)])
701-
static let float = LoweringParameterInfo(loweredParameters: [("value", .f32)])
702-
static let double = LoweringParameterInfo(loweredParameters: [("value", .f64)])
703-
static let string = LoweringParameterInfo(loweredParameters: [("value", .i32)])
704-
static let jsObject = LoweringParameterInfo(loweredParameters: [("value", .i32)])
705-
static let jsValue = LoweringParameterInfo(loweredParameters: [
706-
("kind", .i32),
707-
("payload1", .i32),
708-
("payload2", .f64),
709-
])
710-
static let void = LoweringParameterInfo(loweredParameters: [])
711-
}
712-
713-
func loweringParameterInfo(context: BridgeContext = .importTS) throws -> LoweringParameterInfo {
686+
func loweringParameterInfo(context: BridgeContext = .importTS) throws -> [(name: String, type: WasmCoreType)] {
714687
switch self {
715-
case .bool: return .bool
716-
case .int, .uint: return .int
717-
case .float: return .float
718-
case .double: return .double
719-
case .string: return .string
720-
case .jsObject: return .jsObject
721-
case .jsValue: return .jsValue
722-
case .void: return .void
723-
case .closure:
724-
// Swift closure is passed to JS as a JS function reference.
725-
return LoweringParameterInfo(loweredParameters: [("funcRef", .i32)])
726-
case .unsafePointer:
727-
return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)])
728-
case .swiftHeapObject:
729-
return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)])
688+
case .nullable(let wrappedType, _):
689+
let wrappedParams = try wrappedType.loweringParameterInfo(context: context)
690+
return [("isSome", WasmCoreType.i32)] + wrappedParams
691+
case .namespaceEnum:
692+
throw BridgeJSCoreError("Namespace enums cannot be used as parameters")
730693
case .swiftProtocol:
731694
throw BridgeJSCoreError("swiftProtocol is not supported in imported signatures")
732-
case .caseEnum:
733-
switch context {
734-
case .importTS:
735-
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
736-
case .exportSwift:
737-
return LoweringParameterInfo(loweredParameters: [("value", .i32)])
738-
}
739-
case .rawValueEnum(_, let rawType):
740-
let wasmType = rawType.wasmCoreType ?? .i32
741-
return LoweringParameterInfo(loweredParameters: [("value", wasmType)])
742-
case .associatedValueEnum:
743-
switch context {
744-
case .importTS:
695+
case .caseEnum, .associatedValueEnum:
696+
if context == .importTS {
745697
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
746-
case .exportSwift:
747-
return LoweringParameterInfo(loweredParameters: [("caseId", .i32)])
748698
}
749-
case .swiftStruct:
750-
switch context {
751-
case .importTS:
752-
// Swift structs are bridged as JS objects (object IDs) in imported signatures.
753-
return LoweringParameterInfo(loweredParameters: [("objectId", .i32)])
754-
case .exportSwift:
755-
return LoweringParameterInfo(loweredParameters: [])
756-
}
757-
case .namespaceEnum:
758-
throw BridgeJSCoreError("Namespace enums cannot be used as parameters")
759-
case .nullable(let wrappedType, _):
760-
let wrappedInfo = try wrappedType.loweringParameterInfo(context: context)
761-
var params = [("isSome", WasmCoreType.i32)]
762-
params.append(contentsOf: wrappedInfo.loweredParameters)
763-
return LoweringParameterInfo(loweredParameters: params)
764-
case .array, .dictionary:
765-
return LoweringParameterInfo(loweredParameters: [])
699+
fallthrough
700+
default:
701+
return descriptor.importParams
766702
}
767703
}
768704

769-
struct LiftingReturnInfo {
770-
let valueToLift: WasmCoreType?
771-
772-
static let bool = LiftingReturnInfo(valueToLift: .i32)
773-
static let int = LiftingReturnInfo(valueToLift: .i32)
774-
static let float = LiftingReturnInfo(valueToLift: .f32)
775-
static let double = LiftingReturnInfo(valueToLift: .f64)
776-
static let string = LiftingReturnInfo(valueToLift: .i32)
777-
static let jsObject = LiftingReturnInfo(valueToLift: .i32)
778-
static let jsValue = LiftingReturnInfo(valueToLift: nil)
779-
static let void = LiftingReturnInfo(valueToLift: nil)
780-
}
781-
782-
func liftingReturnInfo(
705+
func liftingReturnType(
783706
context: BridgeContext = .importTS
784-
) throws -> LiftingReturnInfo {
707+
) throws -> WasmCoreType? {
785708
switch self {
786-
case .bool: return .bool
787-
case .int, .uint: return .int
788-
case .float: return .float
789-
case .double: return .double
790-
case .string: return .string
791-
case .jsObject: return .jsObject
792-
case .jsValue: return .jsValue
793-
case .void: return .void
794-
case .closure:
795-
// JS returns a callback ID for closures, which Swift lifts to a typed closure.
796-
return LiftingReturnInfo(valueToLift: .i32)
797-
case .unsafePointer:
798-
return LiftingReturnInfo(valueToLift: .pointer)
799-
case .swiftHeapObject:
800-
return LiftingReturnInfo(valueToLift: .pointer)
709+
case .nullable(let wrappedType, _):
710+
return try wrappedType.liftingReturnType(context: context)
711+
case .namespaceEnum:
712+
throw BridgeJSCoreError("Namespace enums cannot be used as return values")
801713
case .swiftProtocol:
802714
throw BridgeJSCoreError("swiftProtocol is not supported in imported signatures")
803-
case .caseEnum:
804-
switch context {
805-
case .importTS:
806-
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
807-
case .exportSwift:
808-
return LiftingReturnInfo(valueToLift: .i32)
809-
}
810-
case .rawValueEnum(_, let rawType):
811-
let wasmType = rawType.wasmCoreType ?? .i32
812-
return LiftingReturnInfo(valueToLift: wasmType)
813-
case .associatedValueEnum:
814-
switch context {
815-
case .importTS:
715+
case .caseEnum, .associatedValueEnum:
716+
if context == .importTS {
816717
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
817-
case .exportSwift:
818-
return LiftingReturnInfo(valueToLift: .i32)
819-
}
820-
case .swiftStruct:
821-
switch context {
822-
case .importTS:
823-
// Swift structs are bridged as JS objects (object IDs) in imported signatures.
824-
return LiftingReturnInfo(valueToLift: .i32)
825-
case .exportSwift:
826-
return LiftingReturnInfo(valueToLift: nil)
827718
}
828-
case .namespaceEnum:
829-
throw BridgeJSCoreError("Namespace enums cannot be used as return values")
830-
case .nullable(let wrappedType, _):
831-
let wrappedInfo = try wrappedType.liftingReturnInfo(context: context)
832-
return LiftingReturnInfo(valueToLift: wrappedInfo.valueToLift)
833-
case .array, .dictionary:
834-
return LiftingReturnInfo(valueToLift: nil)
719+
fallthrough
720+
default:
721+
return descriptor.importReturnType
835722
}
836723
}
837724
}

0 commit comments

Comments
 (0)