Skip to content

Commit 074b750

Browse files
committed
BridgeJS: Add BridgeTypeDescriptor and refactor ExportSwift/ImportTS to use descriptor-driven dispatch
1 parent 318f3ae commit 074b750

File tree

10 files changed

+442
-285
lines changed

10 files changed

+442
-285
lines changed

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 96 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,23 @@ public class ExportSwift {
147147
} else {
148148
optionalSwiftType = "JSUndefinedOr"
149149
}
150-
typeNameForIntrinsic = "\(optionalSwiftType)<\(wrappedType.swiftType)>"
150+
if case .swiftProtocol(let protocolName) = wrappedType {
151+
let wrapperName = "Any\(protocolName)"
152+
typeNameForIntrinsic = "\(optionalSwiftType)<\(wrapperName)>"
153+
liftingExpr = ExprSyntax(
154+
"\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))"
155+
)
156+
} else {
157+
typeNameForIntrinsic = "\(optionalSwiftType)<\(wrappedType.swiftType)>"
158+
liftingExpr = ExprSyntax(
159+
"\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))"
160+
)
161+
}
162+
case .swiftProtocol(let protocolName):
163+
let wrapperName = "Any\(protocolName)"
164+
typeNameForIntrinsic = wrapperName
151165
liftingExpr = ExprSyntax(
152-
"\(raw: typeNameForIntrinsic).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))"
166+
"\(raw: wrapperName).bridgeJSLiftParameter(\(raw: argumentsToLift.joined(separator: ", ")))"
153167
)
154168
default:
155169
typeNameForIntrinsic = param.type.swiftType
@@ -164,20 +178,6 @@ public class ExportSwift {
164178
}
165179
}
166180

167-
private func protocolCastSuffix(for returnType: BridgeType) -> (prefix: String, suffix: String) {
168-
switch returnType {
169-
case .swiftProtocol:
170-
return ("", " as! \(returnType.swiftType)")
171-
case .nullable(let wrappedType, _):
172-
if case .swiftProtocol = wrappedType {
173-
return ("(", ").flatMap { $0 as? \(wrappedType.swiftType) }")
174-
}
175-
return ("", "")
176-
default:
177-
return ("", "")
178-
}
179-
}
180-
181181
private func removeFirstLiftedParameter() -> (parameter: Parameter, expr: ExprSyntax) {
182182
let parameter = parameters.removeFirst()
183183
let expr = liftedParameterExprs.removeFirst()
@@ -211,10 +211,26 @@ public class ExportSwift {
211211
if returnType == .void {
212212
return CodeBlockItemSyntax(item: .init(ExpressionStmtSyntax(expression: callExpr)))
213213
} else {
214-
let (prefix, suffix) = protocolCastSuffix(for: returnType)
215-
return CodeBlockItemSyntax(
216-
item: .init(DeclSyntax("let ret = \(raw: prefix)\(raw: callExpr)\(raw: suffix)"))
217-
)
214+
switch returnType {
215+
case .swiftProtocol(let protocolName):
216+
let wrapperName = "Any\(protocolName)"
217+
return CodeBlockItemSyntax(
218+
item: .init(DeclSyntax("let ret = \(raw: callExpr) as! \(raw: wrapperName)"))
219+
)
220+
case .nullable(let wrappedType, _):
221+
if case .swiftProtocol(let protocolName) = wrappedType {
222+
let wrapperName = "Any\(protocolName)"
223+
return CodeBlockItemSyntax(
224+
item: .init(
225+
DeclSyntax("let ret = (\(raw: callExpr)).flatMap { $0 as? \(raw: wrapperName) }")
226+
)
227+
)
228+
} else {
229+
return CodeBlockItemSyntax(item: .init(DeclSyntax("let ret = \(raw: callExpr)")))
230+
}
231+
default:
232+
return CodeBlockItemSyntax(item: .init(DeclSyntax("let ret = \(raw: callExpr)")))
233+
}
218234
}
219235
}
220236

@@ -228,8 +244,20 @@ public class ExportSwift {
228244
if returnType == .void {
229245
append("\(raw: name)")
230246
} else {
231-
let (prefix, suffix) = protocolCastSuffix(for: returnType)
232-
append("let ret = \(raw: prefix)\(raw: name)\(raw: suffix)")
247+
switch returnType {
248+
case .swiftProtocol(let protocolName):
249+
let wrapperName = "Any\(protocolName)"
250+
append("let ret = \(raw: name) as! \(raw: wrapperName)")
251+
case .nullable(let wrappedType, _):
252+
if case .swiftProtocol(let protocolName) = wrappedType {
253+
let wrapperName = "Any\(protocolName)"
254+
append("let ret = \(raw: name).flatMap { $0 as? \(raw: wrapperName) }")
255+
} else {
256+
append("let ret = \(raw: name)")
257+
}
258+
default:
259+
append("let ret = \(raw: name)")
260+
}
233261
}
234262
}
235263

@@ -273,8 +301,20 @@ public class ExportSwift {
273301
if returnType == .void {
274302
append("\(raw: selfExpr).\(raw: propertyName)")
275303
} else {
276-
let (prefix, suffix) = protocolCastSuffix(for: returnType)
277-
append("let ret = \(raw: prefix)\(raw: selfExpr).\(raw: propertyName)\(raw: suffix)")
304+
switch returnType {
305+
case .swiftProtocol(let protocolName):
306+
let wrapperName = "Any\(protocolName)"
307+
append("let ret = \(raw: selfExpr).\(raw: propertyName) as! \(raw: wrapperName)")
308+
case .nullable(let wrappedType, _):
309+
if case .swiftProtocol(let protocolName) = wrappedType {
310+
let wrapperName = "Any\(protocolName)"
311+
append("let ret = \(raw: selfExpr).\(raw: propertyName).flatMap { $0 as? \(raw: wrapperName) }")
312+
} else {
313+
append("let ret = \(raw: selfExpr).\(raw: propertyName)")
314+
}
315+
default:
316+
append("let ret = \(raw: selfExpr).\(raw: propertyName)")
317+
}
278318
}
279319
}
280320

@@ -849,24 +889,26 @@ struct StackCodegen {
849889
varPrefix: String
850890
) -> [CodeBlockItemSyntax] {
851891
switch type {
852-
case .string, .int, .uint, .bool, .float, .double, .jsValue,
853-
.jsObject(nil), .swiftHeapObject, .unsafePointer, .closure,
854-
.caseEnum, .rawValueEnum:
855-
return ["\(raw: accessor).bridgeJSLowerStackReturn()"]
856-
case .jsObject(_?):
857-
return ["\(raw: accessor).jsObject.bridgeJSLowerStackReturn()"]
858-
case .swiftProtocol:
859-
return ["(\(raw: accessor) as! \(raw: type.swiftType)).bridgeJSLowerStackReturn()"]
860-
case .associatedValueEnum, .swiftStruct:
861-
return ["\(raw: accessor).bridgeJSLowerReturn()"]
892+
862893
case .nullable(let wrappedType, _):
863894
return lowerOptionalStatements(wrappedType: wrappedType, accessor: accessor, varPrefix: varPrefix)
864-
case .void, .namespaceEnum:
865-
return []
866895
case .array(let elementType):
867896
return lowerArrayStatements(elementType: elementType, accessor: accessor, varPrefix: varPrefix)
868897
case .dictionary(let valueType):
869898
return lowerDictionaryStatements(valueType: valueType, accessor: accessor, varPrefix: varPrefix)
899+
default:
900+
break
901+
}
902+
903+
let desc = type.descriptor
904+
let transformed = desc.accessorTransform.apply(accessor)
905+
switch desc.lowerMethod {
906+
case .stackReturn:
907+
return ["\(raw: transformed).bridgeJSLowerStackReturn()"]
908+
case .fullReturn, .pushParameter:
909+
return ["\(raw: transformed).bridgeJSLowerReturn()"]
910+
case .none:
911+
return []
870912
}
871913
}
872914

@@ -875,6 +917,7 @@ struct StackCodegen {
875917
accessor: String,
876918
varPrefix: String
877919
) -> [CodeBlockItemSyntax] {
920+
// Types needing accessor transformation
878921
switch elementType {
879922
case .jsObject(let className?) where className != "JSObject":
880923
return ["\(raw: accessor).map { $0.jsObject }.bridgeJSLowerReturn()"]
@@ -979,11 +1022,8 @@ struct StackCodegen {
9791022
accessor: String,
9801023
varPrefix: String
9811024
) -> [CodeBlockItemSyntax] {
982-
switch wrappedType {
983-
case .array, .dictionary, .swiftStruct:
1025+
if wrappedType.descriptor.optionalUsesStackABI {
9841026
return ["\(raw: accessor).bridgeJSLowerReturn()"]
985-
default:
986-
break
9871027
}
9881028

9891029
var statements: [String] = []
@@ -1010,16 +1050,16 @@ struct StackCodegen {
10101050
unwrappedVar: String,
10111051
varPrefix: String
10121052
) -> [CodeBlockItemSyntax] {
1013-
switch wrappedType {
1014-
case .jsObject(_?):
1015-
return ["\(raw: unwrappedVar).jsObject.bridgeJSLowerStackReturn()"]
1016-
case .swiftProtocol:
1017-
return ["(\(raw: unwrappedVar) as! \(raw: wrappedType.swiftType)).bridgeJSLowerStackReturn()"]
1018-
case .string, .int, .uint, .bool, .float, .double, .jsValue,
1019-
.jsObject(nil), .swiftHeapObject, .unsafePointer, .closure,
1020-
.caseEnum, .rawValueEnum, .associatedValueEnum:
1021-
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
1022-
default:
1053+
let desc = wrappedType.descriptor
1054+
let transformed = desc.accessorTransform.apply(unwrappedVar)
1055+
switch desc.lowerMethod {
1056+
case .stackReturn:
1057+
return ["\(raw: transformed).bridgeJSLowerStackReturn()"]
1058+
case .fullReturn:
1059+
return ["\(raw: transformed).bridgeJSLowerReturn()"]
1060+
case .pushParameter:
1061+
return ["_swift_js_push_i32(\(raw: transformed).bridgeJSLowerParameter())"]
1062+
case .none:
10231063
return ["preconditionFailure(\"BridgeJS: unsupported optional wrapped type\")"]
10241064
}
10251065
}
@@ -1633,17 +1673,6 @@ extension BridgeType {
16331673

16341674
func liftParameterInfo() throws -> LiftingIntrinsicInfo {
16351675
switch self {
1636-
case .bool: return .bool
1637-
case .int, .uint: return .int
1638-
case .float: return .float
1639-
case .double: return .double
1640-
case .string: return .string
1641-
case .jsObject: return .jsObject
1642-
case .jsValue: return .jsValue
1643-
case .swiftHeapObject: return .swiftHeapObject
1644-
case .unsafePointer: return .unsafePointer
1645-
case .swiftProtocol: return .jsObject
1646-
case .void: return .void
16471676
case .nullable(let wrappedType, _):
16481677
let wrappedInfo = try wrappedType.liftParameterInfo()
16491678
if wrappedInfo.parameters.isEmpty {
@@ -1652,92 +1681,25 @@ extension BridgeType {
16521681
var optionalParams: [(name: String, type: WasmCoreType)] = [("isSome", .i32)]
16531682
optionalParams.append(contentsOf: wrappedInfo.parameters)
16541683
return LiftingIntrinsicInfo(parameters: optionalParams)
1655-
case .caseEnum: return .caseEnum
1656-
case .rawValueEnum(_, let rawType):
1657-
return rawType.liftingIntrinsicInfo
1658-
case .associatedValueEnum:
1659-
return .associatedValueEnum
1660-
case .swiftStruct:
1661-
return LiftingIntrinsicInfo(parameters: [])
16621684
case .namespaceEnum:
16631685
throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters")
1664-
case .closure:
1665-
return LiftingIntrinsicInfo(parameters: [("callbackId", .i32)])
1666-
case .array, .dictionary:
1667-
return LiftingIntrinsicInfo(parameters: [])
1686+
default:
1687+
return LiftingIntrinsicInfo(parameters: descriptor.wasmParams)
16681688
}
16691689
}
16701690

16711691
struct LoweringIntrinsicInfo: Sendable {
16721692
let returnType: WasmCoreType?
1673-
1674-
static let bool = LoweringIntrinsicInfo(returnType: .i32)
1675-
static let int = LoweringIntrinsicInfo(returnType: .i32)
1676-
static let float = LoweringIntrinsicInfo(returnType: .f32)
1677-
static let double = LoweringIntrinsicInfo(returnType: .f64)
1678-
static let string = LoweringIntrinsicInfo(returnType: nil)
1679-
static let jsObject = LoweringIntrinsicInfo(returnType: .i32)
1680-
static let jsValue = LoweringIntrinsicInfo(returnType: nil)
1681-
static let swiftHeapObject = LoweringIntrinsicInfo(returnType: .pointer)
1682-
static let unsafePointer = LoweringIntrinsicInfo(returnType: .pointer)
1683-
static let void = LoweringIntrinsicInfo(returnType: nil)
1684-
static let caseEnum = LoweringIntrinsicInfo(returnType: .i32)
1685-
static let rawValueEnum = LoweringIntrinsicInfo(returnType: .i32)
1686-
static let associatedValueEnum = LoweringIntrinsicInfo(returnType: nil)
1687-
static let swiftStruct = LoweringIntrinsicInfo(returnType: nil)
1688-
static let optional = LoweringIntrinsicInfo(returnType: nil)
1689-
static let array = LoweringIntrinsicInfo(returnType: nil)
16901693
}
16911694

16921695
func loweringReturnInfo() throws -> LoweringIntrinsicInfo {
16931696
switch self {
1694-
case .bool: return .bool
1695-
case .int, .uint: return .int
1696-
case .float: return .float
1697-
case .double: return .double
1698-
case .string: return .string
1699-
case .jsObject: return .jsObject
1700-
case .jsValue: return .jsValue
1701-
case .swiftHeapObject: return .swiftHeapObject
1702-
case .unsafePointer: return .unsafePointer
1703-
case .swiftProtocol: return .jsObject
1704-
case .void: return .void
1705-
case .nullable: return .optional
1706-
case .caseEnum: return .caseEnum
1707-
case .rawValueEnum(_, let rawType):
1708-
return rawType.loweringIntrinsicInfo
1709-
case .associatedValueEnum:
1710-
return .associatedValueEnum
1711-
case .swiftStruct:
1712-
return .swiftStruct
1697+
case .nullable:
1698+
return LoweringIntrinsicInfo(returnType: nil)
17131699
case .namespaceEnum:
17141700
throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters")
1715-
case .closure:
1716-
return .jsObject
1717-
case .array, .dictionary:
1718-
return .array
1719-
}
1720-
}
1721-
}
1722-
1723-
extension SwiftEnumRawType {
1724-
var liftingIntrinsicInfo: BridgeType.LiftingIntrinsicInfo {
1725-
switch self {
1726-
case .bool: return .bool
1727-
case .int, .int32, .int64, .uint, .uint32, .uint64: return .int
1728-
case .float: return .float
1729-
case .double: return .double
1730-
case .string: return .string
1731-
}
1732-
}
1733-
1734-
var loweringIntrinsicInfo: BridgeType.LoweringIntrinsicInfo {
1735-
switch self {
1736-
case .bool: return .bool
1737-
case .int, .int32, .int64, .uint, .uint32, .uint64: return .int
1738-
case .float: return .float
1739-
case .double: return .double
1740-
case .string: return .string
1701+
default:
1702+
return LoweringIntrinsicInfo(returnType: descriptor.wasmReturnType)
17411703
}
17421704
}
17431705
}

0 commit comments

Comments
 (0)