Skip to content

Commit 3c75e68

Browse files
committed
BridgeJS: Add BridgeABIFamily and refactor ExportSwift/ImportTS to use family-based dispatch
1 parent a77ee78 commit 3c75e68

File tree

3 files changed

+272
-160
lines changed

3 files changed

+272
-160
lines changed

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 85 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -916,30 +916,37 @@ struct StackCodegen {
916916
accessor: String,
917917
varPrefix: String
918918
) -> [CodeBlockItemSyntax] {
919+
// Handle containers and optionals first (recursive/special structure)
919920
switch type {
920-
case .string, .int, .uint, .bool, .float, .double, .jsValue:
921-
return ["\(raw: accessor).bridgeJSLowerStackReturn()"]
922-
case .jsObject(nil):
923-
return ["\(raw: accessor).bridgeJSLowerStackReturn()"]
924-
case .jsObject(_?):
921+
case .nullable(let wrappedType, _):
922+
return lowerOptionalStatements(wrappedType: wrappedType, accessor: accessor, varPrefix: varPrefix)
923+
case .array(let elementType):
924+
return lowerArrayStatements(elementType: elementType, accessor: accessor, varPrefix: varPrefix)
925+
case .dictionary(let valueType):
926+
return lowerDictionaryStatements(valueType: valueType, accessor: accessor, varPrefix: varPrefix)
927+
default:
928+
break
929+
}
930+
931+
// Handle types that need accessor transformation before lowering
932+
switch type {
933+
case .jsObject(let className?) where className != "JSObject":
925934
return ["\(raw: accessor).jsObject.bridgeJSLowerStackReturn()"]
926-
case .swiftHeapObject, .unsafePointer, .closure:
927-
return ["\(raw: accessor).bridgeJSLowerStackReturn()"]
928935
case .swiftProtocol(let protocolName):
929936
let wrapperName = "Any\(protocolName)"
930937
return ["(\(raw: accessor) as! \(raw: wrapperName)).bridgeJSLowerStackReturn()"]
931-
case .caseEnum, .rawValueEnum:
938+
default:
939+
break
940+
}
941+
942+
// Family-based lowering
943+
switch type.abiFamily {
944+
case .directScalar, .directMultiWord:
932945
return ["\(raw: accessor).bridgeJSLowerStackReturn()"]
933-
case .associatedValueEnum, .swiftStruct:
946+
case .taggedPayload, .stackBased:
934947
return ["\(raw: accessor).bridgeJSLowerReturn()"]
935-
case .nullable(let wrappedType, _):
936-
return lowerOptionalStatements(wrappedType: wrappedType, accessor: accessor, varPrefix: varPrefix)
937-
case .void, .namespaceEnum:
948+
case .void:
938949
return []
939-
case .array(let elementType):
940-
return lowerArrayStatements(elementType: elementType, accessor: accessor, varPrefix: varPrefix)
941-
case .dictionary(let valueType):
942-
return lowerDictionaryStatements(valueType: valueType, accessor: accessor, varPrefix: varPrefix)
943950
}
944951
}
945952

@@ -948,6 +955,7 @@ struct StackCodegen {
948955
accessor: String,
949956
varPrefix: String
950957
) -> [CodeBlockItemSyntax] {
958+
// Types needing accessor transformation
951959
switch elementType {
952960
case .jsObject(let className?) where className != "JSObject":
953961
return ["\(raw: accessor).map { $0.jsObject }.bridgeJSLowerReturn()"]
@@ -1052,11 +1060,9 @@ struct StackCodegen {
10521060
accessor: String,
10531061
varPrefix: String
10541062
) -> [CodeBlockItemSyntax] {
1055-
switch wrappedType {
1056-
case .array, .dictionary, .swiftStruct:
1063+
// Stack-based types use the generic Optional conformance directly
1064+
if wrappedType.abiFamily == .stackBased {
10571065
return ["\(raw: accessor).bridgeJSLowerReturn()"]
1058-
default:
1059-
break
10601066
}
10611067

10621068
var statements: [String] = []
@@ -1083,20 +1089,23 @@ struct StackCodegen {
10831089
unwrappedVar: String,
10841090
varPrefix: String
10851091
) -> [CodeBlockItemSyntax] {
1092+
// Handle types needing accessor transformation
10861093
switch wrappedType {
1087-
case .string, .int, .uint, .bool, .float, .double, .jsValue:
1088-
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
1089-
case .caseEnum, .rawValueEnum:
1090-
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
1091-
case .swiftHeapObject:
1092-
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
1093-
case .associatedValueEnum:
1094-
return ["_swift_js_push_i32(\(raw: unwrappedVar).bridgeJSLowerParameter())"]
1095-
case .jsObject(nil):
1096-
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
1097-
case .jsObject(_?):
1094+
case .jsObject(let className?) where className != "JSObject":
10981095
return ["\(raw: unwrappedVar).jsObject.bridgeJSLowerStackReturn()"]
10991096
default:
1097+
break
1098+
}
1099+
1100+
// Family-based lowering for unwrapped optional values
1101+
switch wrappedType.abiFamily {
1102+
case .directScalar, .directMultiWord:
1103+
return ["\(raw: unwrappedVar).bridgeJSLowerStackReturn()"]
1104+
case .taggedPayload:
1105+
return ["_swift_js_push_i32(\(raw: unwrappedVar).bridgeJSLowerParameter())"]
1106+
case .stackBased:
1107+
return ["\(raw: unwrappedVar).bridgeJSLowerReturn()"]
1108+
case .void:
11001109
return ["preconditionFailure(\"BridgeJS: unsupported optional wrapped type\")"]
11011110
}
11021111
}
@@ -1710,17 +1719,6 @@ extension BridgeType {
17101719

17111720
func liftParameterInfo() throws -> LiftingIntrinsicInfo {
17121721
switch self {
1713-
case .bool: return .bool
1714-
case .int, .uint: return .int
1715-
case .float: return .float
1716-
case .double: return .double
1717-
case .string: return .string
1718-
case .jsObject: return .jsObject
1719-
case .jsValue: return .jsValue
1720-
case .swiftHeapObject: return .swiftHeapObject
1721-
case .unsafePointer: return .unsafePointer
1722-
case .swiftProtocol: return .jsObject
1723-
case .void: return .void
17241722
case .nullable(let wrappedType, _):
17251723
let wrappedInfo = try wrappedType.liftParameterInfo()
17261724
if wrappedInfo.parameters.isEmpty {
@@ -1729,19 +1727,39 @@ extension BridgeType {
17291727
var optionalParams: [(name: String, type: WasmCoreType)] = [("isSome", .i32)]
17301728
optionalParams.append(contentsOf: wrappedInfo.parameters)
17311729
return LiftingIntrinsicInfo(parameters: optionalParams)
1732-
case .caseEnum: return .caseEnum
1733-
case .rawValueEnum(_, let rawType):
1734-
return rawType.liftingIntrinsicInfo
1735-
case .associatedValueEnum:
1736-
return .associatedValueEnum
1737-
case .swiftStruct:
1738-
return LiftingIntrinsicInfo(parameters: [])
17391730
case .namespaceEnum:
17401731
throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters")
1741-
case .closure:
1742-
return LiftingIntrinsicInfo(parameters: [("callbackId", .i32)])
1743-
case .array, .dictionary:
1732+
default:
1733+
return liftParameterInfoForNonOptional()
1734+
}
1735+
}
1736+
1737+
private func liftParameterInfoForNonOptional() -> LiftingIntrinsicInfo {
1738+
switch abiFamily {
1739+
case .directScalar(let wasmType):
1740+
let name: String
1741+
switch self {
1742+
case .closure: name = "callbackId"
1743+
default: name = "value"
1744+
}
1745+
return LiftingIntrinsicInfo(parameters: [(name, wasmType)])
1746+
case .directMultiWord:
1747+
switch self {
1748+
case .string:
1749+
return .string
1750+
case .jsValue:
1751+
return .jsValue
1752+
case .rawValueEnum(_, let rawType):
1753+
return rawType.liftingIntrinsicInfo
1754+
default:
1755+
fatalError("Unexpected directMultiWord type: \(self)")
1756+
}
1757+
case .taggedPayload:
1758+
return .associatedValueEnum
1759+
case .stackBased:
17441760
return LiftingIntrinsicInfo(parameters: [])
1761+
case .void:
1762+
return .void
17451763
}
17461764
}
17471765

@@ -1768,31 +1786,23 @@ extension BridgeType {
17681786

17691787
func loweringReturnInfo() throws -> LoweringIntrinsicInfo {
17701788
switch self {
1771-
case .bool: return .bool
1772-
case .int, .uint: return .int
1773-
case .float: return .float
1774-
case .double: return .double
1775-
case .string: return .string
1776-
case .jsObject: return .jsObject
1777-
case .jsValue: return .jsValue
1778-
case .swiftHeapObject: return .swiftHeapObject
1779-
case .unsafePointer: return .unsafePointer
1780-
case .swiftProtocol: return .jsObject
1781-
case .void: return .void
1782-
case .nullable: return .optional
1783-
case .caseEnum: return .caseEnum
1784-
case .rawValueEnum(_, let rawType):
1785-
return rawType.loweringIntrinsicInfo
1786-
case .associatedValueEnum:
1787-
return .associatedValueEnum
1788-
case .swiftStruct:
1789-
return .swiftStruct
1789+
case .nullable:
1790+
return .optional
17901791
case .namespaceEnum:
17911792
throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters")
1792-
case .closure:
1793-
return .jsObject
1794-
case .array, .dictionary:
1795-
return .array
1793+
default:
1794+
return loweringReturnInfoForNonOptional()
1795+
}
1796+
}
1797+
1798+
private func loweringReturnInfoForNonOptional() -> LoweringIntrinsicInfo {
1799+
switch abiFamily {
1800+
case .directScalar(let wasmType):
1801+
return LoweringIntrinsicInfo(returnType: wasmType)
1802+
case .directMultiWord, .stackBased, .taggedPayload:
1803+
return LoweringIntrinsicInfo(returnType: nil)
1804+
case .void:
1805+
return .void
17961806
}
17971807
}
17981808
}

0 commit comments

Comments
 (0)