Skip to content

Commit e837432

Browse files
committed
BridgeJS: Add BridgeABIFamily and refactor ExportSwift/ImportTS to use family-based dispatch
1 parent 9ddfda9 commit e837432

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
}
@@ -1761,17 +1770,6 @@ extension BridgeType {
17611770

17621771
func liftParameterInfo() throws -> LiftingIntrinsicInfo {
17631772
switch self {
1764-
case .bool: return .bool
1765-
case .int, .uint: return .int
1766-
case .float: return .float
1767-
case .double: return .double
1768-
case .string: return .string
1769-
case .jsObject: return .jsObject
1770-
case .jsValue: return .jsValue
1771-
case .swiftHeapObject: return .swiftHeapObject
1772-
case .unsafePointer: return .unsafePointer
1773-
case .swiftProtocol: return .jsObject
1774-
case .void: return .void
17751773
case .nullable(let wrappedType, _):
17761774
let wrappedInfo = try wrappedType.liftParameterInfo()
17771775
if wrappedInfo.parameters.isEmpty {
@@ -1780,19 +1778,39 @@ extension BridgeType {
17801778
var optionalParams: [(name: String, type: WasmCoreType)] = [("isSome", .i32)]
17811779
optionalParams.append(contentsOf: wrappedInfo.parameters)
17821780
return LiftingIntrinsicInfo(parameters: optionalParams)
1783-
case .caseEnum: return .caseEnum
1784-
case .rawValueEnum(_, let rawType):
1785-
return rawType.liftingIntrinsicInfo
1786-
case .associatedValueEnum:
1787-
return .associatedValueEnum
1788-
case .swiftStruct:
1789-
return LiftingIntrinsicInfo(parameters: [])
17901781
case .namespaceEnum:
17911782
throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters")
1792-
case .closure:
1793-
return LiftingIntrinsicInfo(parameters: [("callbackId", .i32)])
1794-
case .array, .dictionary:
1783+
default:
1784+
return liftParameterInfoForNonOptional()
1785+
}
1786+
}
1787+
1788+
private func liftParameterInfoForNonOptional() -> LiftingIntrinsicInfo {
1789+
switch abiFamily {
1790+
case .directScalar(let wasmType):
1791+
let name: String
1792+
switch self {
1793+
case .closure: name = "callbackId"
1794+
default: name = "value"
1795+
}
1796+
return LiftingIntrinsicInfo(parameters: [(name, wasmType)])
1797+
case .directMultiWord:
1798+
switch self {
1799+
case .string:
1800+
return .string
1801+
case .jsValue:
1802+
return .jsValue
1803+
case .rawValueEnum(_, let rawType):
1804+
return rawType.liftingIntrinsicInfo
1805+
default:
1806+
fatalError("Unexpected directMultiWord type: \(self)")
1807+
}
1808+
case .taggedPayload:
1809+
return .associatedValueEnum
1810+
case .stackBased:
17951811
return LiftingIntrinsicInfo(parameters: [])
1812+
case .void:
1813+
return .void
17961814
}
17971815
}
17981816

@@ -1819,31 +1837,23 @@ extension BridgeType {
18191837

18201838
func loweringReturnInfo() throws -> LoweringIntrinsicInfo {
18211839
switch self {
1822-
case .bool: return .bool
1823-
case .int, .uint: return .int
1824-
case .float: return .float
1825-
case .double: return .double
1826-
case .string: return .string
1827-
case .jsObject: return .jsObject
1828-
case .jsValue: return .jsValue
1829-
case .swiftHeapObject: return .swiftHeapObject
1830-
case .unsafePointer: return .unsafePointer
1831-
case .swiftProtocol: return .jsObject
1832-
case .void: return .void
1833-
case .nullable: return .optional
1834-
case .caseEnum: return .caseEnum
1835-
case .rawValueEnum(_, let rawType):
1836-
return rawType.loweringIntrinsicInfo
1837-
case .associatedValueEnum:
1838-
return .associatedValueEnum
1839-
case .swiftStruct:
1840-
return .swiftStruct
1840+
case .nullable:
1841+
return .optional
18411842
case .namespaceEnum:
18421843
throw BridgeJSCoreError("Namespace enums are not supported to pass as parameters")
1843-
case .closure:
1844-
return .jsObject
1845-
case .array, .dictionary:
1846-
return .array
1844+
default:
1845+
return loweringReturnInfoForNonOptional()
1846+
}
1847+
}
1848+
1849+
private func loweringReturnInfoForNonOptional() -> LoweringIntrinsicInfo {
1850+
switch abiFamily {
1851+
case .directScalar(let wasmType):
1852+
return LoweringIntrinsicInfo(returnType: wasmType)
1853+
case .directMultiWord, .stackBased, .taggedPayload:
1854+
return LoweringIntrinsicInfo(returnType: nil)
1855+
case .void:
1856+
return .void
18471857
}
18481858
}
18491859
}

0 commit comments

Comments
 (0)