Skip to content

Commit db42577

Browse files
committed
BridgeJS: Add BridgeABIFamily and refactor ExportSwift/ImportTS to use family-based dispatch
1 parent 7018c02 commit db42577

File tree

3 files changed

+274
-156
lines changed

3 files changed

+274
-156
lines changed

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 87 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -888,25 +888,38 @@ struct StackCodegen {
888888
accessor: String,
889889
varPrefix: String
890890
) -> [CodeBlockItemSyntax] {
891+
// Handle containers and optionals first (recursive/special structure)
891892
switch type {
892-
case .string, .int, .uint, .bool, .float, .double, .jsValue,
893-
.jsObject(nil), .swiftHeapObject, .unsafePointer, .closure,
894-
.caseEnum, .rawValueEnum:
895-
return ["\(raw: accessor).bridgeJSLowerStackReturn()"]
896-
case .jsObject(_?):
897-
return ["\(raw: accessor).jsObject.bridgeJSLowerStackReturn()"]
898-
case .swiftProtocol:
899-
return ["(\(raw: accessor) as! \(raw: type.swiftType)).bridgeJSLowerStackReturn()"]
900-
case .associatedValueEnum, .swiftStruct:
901-
return ["\(raw: accessor).bridgeJSLowerReturn()"]
893+
902894
case .nullable(let wrappedType, _):
903895
return lowerOptionalStatements(wrappedType: wrappedType, accessor: accessor, varPrefix: varPrefix)
904-
case .void, .namespaceEnum:
905-
return []
906896
case .array(let elementType):
907897
return lowerArrayStatements(elementType: elementType, accessor: accessor, varPrefix: varPrefix)
908898
case .dictionary(let valueType):
909899
return lowerDictionaryStatements(valueType: valueType, accessor: accessor, varPrefix: varPrefix)
900+
default:
901+
break
902+
}
903+
904+
// Handle types that need accessor transformation before lowering
905+
switch type {
906+
case .jsObject(let className?) where className != "JSObject":
907+
return ["\(raw: accessor).jsObject.bridgeJSLowerStackReturn()"]
908+
case .swiftProtocol(let protocolName):
909+
let wrapperName = "Any\(protocolName)"
910+
return ["(\(raw: accessor) as! \(raw: wrapperName)).bridgeJSLowerStackReturn()"]
911+
default:
912+
break
913+
}
914+
915+
// Family-based lowering
916+
switch type.abiFamily {
917+
case .directScalar, .directMultiWord:
918+
return ["\(raw: accessor).bridgeJSLowerStackReturn()"]
919+
case .taggedPayload, .stackBased:
920+
return ["\(raw: accessor).bridgeJSLowerReturn()"]
921+
case .void:
922+
return []
910923
}
911924
}
912925

@@ -915,6 +928,7 @@ struct StackCodegen {
915928
accessor: String,
916929
varPrefix: String
917930
) -> [CodeBlockItemSyntax] {
931+
// Types needing accessor transformation
918932
switch elementType {
919933
case .jsObject(let className?) where className != "JSObject":
920934
return ["\(raw: accessor).map { $0.jsObject }.bridgeJSLowerReturn()"]
@@ -1019,11 +1033,9 @@ struct StackCodegen {
10191033
accessor: String,
10201034
varPrefix: String
10211035
) -> [CodeBlockItemSyntax] {
1022-
switch wrappedType {
1023-
case .array, .dictionary, .swiftStruct:
1036+
// Stack-based types use the generic Optional conformance directly
1037+
if wrappedType.abiFamily == .stackBased {
10241038
return ["\(raw: accessor).bridgeJSLowerReturn()"]
1025-
default:
1026-
break
10271039
}
10281040

10291041
var statements: [String] = []
@@ -1050,20 +1062,23 @@ struct StackCodegen {
10501062
unwrappedVar: String,
10511063
varPrefix: String
10521064
) -> [CodeBlockItemSyntax] {
1065+
// Handle types needing accessor transformation
10531066
switch wrappedType {
1054-
case .string, .int, .uint, .bool, .float, .double, .jsValue:
1055-
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
1056-
case .caseEnum, .rawValueEnum:
1057-
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
1058-
case .swiftHeapObject:
1059-
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
1060-
case .associatedValueEnum:
1061-
return ["_swift_js_push_i32(\(raw: unwrappedVar).bridgeJSLowerParameter())"]
1062-
case .jsObject(nil):
1063-
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
1064-
case .jsObject(_?):
1067+
case .jsObject(let className?) where className != "JSObject":
10651068
return ["\(raw: unwrappedVar).jsObject.bridgeJSLowerStackReturn()"]
10661069
default:
1070+
break
1071+
}
1072+
1073+
// Family-based lowering for unwrapped optional values
1074+
switch wrappedType.abiFamily {
1075+
case .directScalar, .directMultiWord:
1076+
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
1077+
case .taggedPayload:
1078+
return ["_swift_js_push_i32(\(raw: unwrappedVar).bridgeJSLowerParameter())"]
1079+
case .stackBased:
1080+
return ["\(raw: unwrappedVar).bridgeJSLowerReturn()"]
1081+
case .void:
10671082
return ["preconditionFailure(\"BridgeJS: unsupported optional wrapped type\")"]
10681083
}
10691084
}
@@ -1677,17 +1692,6 @@ extension BridgeType {
16771692

16781693
func liftParameterInfo() throws -> LiftingIntrinsicInfo {
16791694
switch self {
1680-
case .bool: return .bool
1681-
case .int, .uint: return .int
1682-
case .float: return .float
1683-
case .double: return .double
1684-
case .string: return .string
1685-
case .jsObject: return .jsObject
1686-
case .jsValue: return .jsValue
1687-
case .swiftHeapObject: return .swiftHeapObject
1688-
case .unsafePointer: return .unsafePointer
1689-
case .swiftProtocol: return .jsObject
1690-
case .void: return .void
16911695
case .nullable(let wrappedType, _):
16921696
let wrappedInfo = try wrappedType.liftParameterInfo()
16931697
if wrappedInfo.parameters.isEmpty {
@@ -1696,19 +1700,39 @@ extension BridgeType {
16961700
var optionalParams: [(name: String, type: WasmCoreType)] = [("isSome", .i32)]
16971701
optionalParams.append(contentsOf: wrappedInfo.parameters)
16981702
return LiftingIntrinsicInfo(parameters: optionalParams)
1699-
case .caseEnum: return .caseEnum
1700-
case .rawValueEnum(_, let rawType):
1701-
return rawType.liftingIntrinsicInfo
1702-
case .associatedValueEnum:
1703-
return .associatedValueEnum
1704-
case .swiftStruct:
1705-
return LiftingIntrinsicInfo(parameters: [])
17061703
case .namespaceEnum:
17071704
throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters")
1708-
case .closure:
1709-
return LiftingIntrinsicInfo(parameters: [("callbackId", .i32)])
1710-
case .array, .dictionary:
1705+
default:
1706+
return liftParameterInfoForNonOptional()
1707+
}
1708+
}
1709+
1710+
private func liftParameterInfoForNonOptional() -> LiftingIntrinsicInfo {
1711+
switch abiFamily {
1712+
case .directScalar(let wasmType):
1713+
let name: String
1714+
switch self {
1715+
case .closure: name = "callbackId"
1716+
default: name = "value"
1717+
}
1718+
return LiftingIntrinsicInfo(parameters: [(name, wasmType)])
1719+
case .directMultiWord:
1720+
switch self {
1721+
case .string:
1722+
return .string
1723+
case .jsValue:
1724+
return .jsValue
1725+
case .rawValueEnum(_, let rawType):
1726+
return rawType.liftingIntrinsicInfo
1727+
default:
1728+
fatalError("Unexpected directMultiWord type: \(self)")
1729+
}
1730+
case .taggedPayload:
1731+
return .associatedValueEnum
1732+
case .stackBased:
17111733
return LiftingIntrinsicInfo(parameters: [])
1734+
case .void:
1735+
return .void
17121736
}
17131737
}
17141738

@@ -1735,31 +1759,23 @@ extension BridgeType {
17351759

17361760
func loweringReturnInfo() throws -> LoweringIntrinsicInfo {
17371761
switch self {
1738-
case .bool: return .bool
1739-
case .int, .uint: return .int
1740-
case .float: return .float
1741-
case .double: return .double
1742-
case .string: return .string
1743-
case .jsObject: return .jsObject
1744-
case .jsValue: return .jsValue
1745-
case .swiftHeapObject: return .swiftHeapObject
1746-
case .unsafePointer: return .unsafePointer
1747-
case .swiftProtocol: return .jsObject
1748-
case .void: return .void
1749-
case .nullable: return .optional
1750-
case .caseEnum: return .caseEnum
1751-
case .rawValueEnum(_, let rawType):
1752-
return rawType.loweringIntrinsicInfo
1753-
case .associatedValueEnum:
1754-
return .associatedValueEnum
1755-
case .swiftStruct:
1756-
return .swiftStruct
1762+
case .nullable:
1763+
return .optional
17571764
case .namespaceEnum:
17581765
throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters")
1759-
case .closure:
1760-
return .jsObject
1761-
case .array, .dictionary:
1762-
return .array
1766+
default:
1767+
return loweringReturnInfoForNonOptional()
1768+
}
1769+
}
1770+
1771+
private func loweringReturnInfoForNonOptional() -> LoweringIntrinsicInfo {
1772+
switch abiFamily {
1773+
case .directScalar(let wasmType):
1774+
return LoweringIntrinsicInfo(returnType: wasmType)
1775+
case .directMultiWord, .stackBased, .taggedPayload:
1776+
return LoweringIntrinsicInfo(returnType: nil)
1777+
case .void:
1778+
return .void
17631779
}
17641780
}
17651781
}

0 commit comments

Comments
 (0)