Skip to content

Commit 5c6213f

Browse files
committed
BridgeJS: Fix codegen for Float/Double raw value enums in struct fields and optional context
1 parent 81885ea commit 5c6213f

File tree

12 files changed

+1032
-6
lines changed

12 files changed

+1032
-6
lines changed

Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,26 +1428,26 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
14281428
for enumCase in exportedEnum.cases {
14291429
for associatedValue in enumCase.associatedValues {
14301430
switch associatedValue.type {
1431-
case .string, .int, .float, .double, .bool:
1431+
case .string, .int, .float, .double, .bool, .caseEnum, .rawValueEnum:
14321432
break
14331433
case .nullable(let wrappedType, _):
14341434
switch wrappedType {
1435-
case .string, .int, .float, .double, .bool:
1435+
case .string, .int, .float, .double, .bool, .caseEnum, .rawValueEnum:
14361436
break
14371437
default:
14381438
diagnose(
14391439
node: node,
14401440
message: "Unsupported associated value type: \(associatedValue.type.swiftType)",
14411441
hint:
1442-
"Only primitive types and optional primitives (String?, Int?, Float?, Double?, Bool?) are supported in associated-value enums"
1442+
"Only primitive types, enums, and their optionals are supported in associated-value enums"
14431443
)
14441444
}
14451445
default:
14461446
diagnose(
14471447
node: node,
14481448
message: "Unsupported associated value type: \(associatedValue.type.swiftType)",
14491449
hint:
1450-
"Only primitive types and optional primitives (String?, Int?, Float?, Double?, Bool?) are supported in associated-value enums"
1450+
"Only primitive types, enums, and their optionals are supported in associated-value enums"
14511451
)
14521452
}
14531453
}

Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,6 +1945,64 @@ struct IntrinsicJSFragment: Sendable {
19451945
return []
19461946
}
19471947
)
1948+
case .caseEnum:
1949+
return IntrinsicJSFragment(
1950+
parameters: ["value"],
1951+
printCode: { arguments, scope, printer, cleanup in
1952+
printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push((\(arguments[0]) | 0));")
1953+
return []
1954+
}
1955+
)
1956+
case .rawValueEnum(_, let rawType):
1957+
switch rawType {
1958+
case .string:
1959+
return IntrinsicJSFragment(
1960+
parameters: ["value"],
1961+
printCode: { arguments, scope, printer, cleanup in
1962+
let value = arguments[0]
1963+
let bytesVar = scope.variable("bytes")
1964+
let idVar = scope.variable("id")
1965+
printer.write(
1966+
"const \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));"
1967+
)
1968+
printer.write(
1969+
"const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));"
1970+
)
1971+
printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(bytesVar).length);")
1972+
printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(idVar));")
1973+
cleanup.write("\(JSGlueVariableScope.reservedSwift).memory.release(\(idVar));")
1974+
return []
1975+
}
1976+
)
1977+
case .float:
1978+
return IntrinsicJSFragment(
1979+
parameters: ["value"],
1980+
printCode: { arguments, scope, printer, cleanup in
1981+
printer.write(
1982+
"\(JSGlueVariableScope.reservedTmpParamF32s).push(Math.fround(\(arguments[0])));"
1983+
)
1984+
return []
1985+
}
1986+
)
1987+
case .double:
1988+
return IntrinsicJSFragment(
1989+
parameters: ["value"],
1990+
printCode: { arguments, scope, printer, cleanup in
1991+
printer.write("\(JSGlueVariableScope.reservedTmpParamF64s).push(\(arguments[0]));")
1992+
return []
1993+
}
1994+
)
1995+
default:
1996+
return IntrinsicJSFragment(
1997+
parameters: ["value"],
1998+
printCode: { arguments, scope, printer, cleanup in
1999+
printer.write(
2000+
"\(JSGlueVariableScope.reservedTmpParamInts).push((\(arguments[0]) | 0));"
2001+
)
2002+
return []
2003+
}
2004+
)
2005+
}
19482006
case .nullable(let wrappedType, let kind):
19492007
return IntrinsicJSFragment(
19502008
parameters: ["value"],
@@ -1999,6 +2057,68 @@ struct IntrinsicJSFragment: Sendable {
19992057
"\(JSGlueVariableScope.reservedTmpParamF64s).push(\(isSomeVar) ? \(value) : 0.0);"
20002058
)
20012059
printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? 1 : 0);")
2060+
case .caseEnum:
2061+
printer.write(
2062+
"\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? (\(value) | 0) : 0);"
2063+
)
2064+
printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? 1 : 0);")
2065+
case .rawValueEnum(_, let rawType):
2066+
switch rawType {
2067+
case .string:
2068+
let idVar = scope.variable("id")
2069+
printer.write("let \(idVar);")
2070+
printer.write("if (\(isSomeVar)) {")
2071+
printer.indent {
2072+
let bytesVar = scope.variable("bytes")
2073+
printer.write(
2074+
"let \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));"
2075+
)
2076+
printer.write(
2077+
"\(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));"
2078+
)
2079+
printer.write(
2080+
"\(JSGlueVariableScope.reservedTmpParamInts).push(\(bytesVar).length);"
2081+
)
2082+
printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(idVar));")
2083+
}
2084+
printer.write("} else {")
2085+
printer.indent {
2086+
printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(0);")
2087+
printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(0);")
2088+
}
2089+
printer.write("}")
2090+
printer.write(
2091+
"\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? 1 : 0);"
2092+
)
2093+
cleanup.write("if(\(idVar)) {")
2094+
cleanup.indent {
2095+
cleanup.write(
2096+
"\(JSGlueVariableScope.reservedSwift).memory.release(\(idVar));"
2097+
)
2098+
}
2099+
cleanup.write("}")
2100+
case .float:
2101+
printer.write(
2102+
"\(JSGlueVariableScope.reservedTmpParamF32s).push(\(isSomeVar) ? Math.fround(\(value)) : 0.0);"
2103+
)
2104+
printer.write(
2105+
"\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? 1 : 0);"
2106+
)
2107+
case .double:
2108+
printer.write(
2109+
"\(JSGlueVariableScope.reservedTmpParamF64s).push(\(isSomeVar) ? \(value) : 0.0);"
2110+
)
2111+
printer.write(
2112+
"\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? 1 : 0);"
2113+
)
2114+
default:
2115+
printer.write(
2116+
"\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? (\(value) | 0) : 0);"
2117+
)
2118+
printer.write(
2119+
"\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? 1 : 0);"
2120+
)
2121+
}
20022122
default:
20032123
printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? 1 : 0);")
20042124
}
@@ -2063,6 +2183,62 @@ struct IntrinsicJSFragment: Sendable {
20632183
return [dVar]
20642184
}
20652185
)
2186+
case .caseEnum:
2187+
return IntrinsicJSFragment(
2188+
parameters: [],
2189+
printCode: { arguments, scope, printer, cleanup in
2190+
let iVar = scope.variable("int")
2191+
printer.write("const \(iVar) = \(JSGlueVariableScope.reservedTmpRetInts).pop();")
2192+
return [iVar]
2193+
}
2194+
)
2195+
case .rawValueEnum(_, let rawType):
2196+
switch rawType {
2197+
case .string:
2198+
return IntrinsicJSFragment(
2199+
parameters: [],
2200+
printCode: { arguments, scope, printer, cleanup in
2201+
let strVar = scope.variable("string")
2202+
printer.write(
2203+
"const \(strVar) = \(JSGlueVariableScope.reservedTmpRetStrings).pop();"
2204+
)
2205+
return [strVar]
2206+
}
2207+
)
2208+
case .float:
2209+
return IntrinsicJSFragment(
2210+
parameters: [],
2211+
printCode: { arguments, scope, printer, cleanup in
2212+
let fVar = scope.variable("f32")
2213+
printer.write(
2214+
"const \(fVar) = \(JSGlueVariableScope.reservedTmpRetF32s).pop();"
2215+
)
2216+
return [fVar]
2217+
}
2218+
)
2219+
case .double:
2220+
return IntrinsicJSFragment(
2221+
parameters: [],
2222+
printCode: { arguments, scope, printer, cleanup in
2223+
let dVar = scope.variable("f64")
2224+
printer.write(
2225+
"const \(dVar) = \(JSGlueVariableScope.reservedTmpRetF64s).pop();"
2226+
)
2227+
return [dVar]
2228+
}
2229+
)
2230+
default:
2231+
return IntrinsicJSFragment(
2232+
parameters: [],
2233+
printCode: { arguments, scope, printer, cleanup in
2234+
let iVar = scope.variable("int")
2235+
printer.write(
2236+
"const \(iVar) = \(JSGlueVariableScope.reservedTmpRetInts).pop();"
2237+
)
2238+
return [iVar]
2239+
}
2240+
)
2241+
}
20662242
case .nullable(let wrappedType, let kind):
20672243
return IntrinsicJSFragment(
20682244
parameters: [],

Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/EnumAssociatedValue.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,27 @@ enum APIOptionalResult {
5555
}
5656
@JS func roundTripOptionalAPIOptionalResult(result: APIOptionalResult?) -> APIOptionalResult?
5757
@JS func compareAPIResults(result1: APIOptionalResult?, result2: APIOptionalResult?) -> APIOptionalResult?
58+
59+
@JS enum Precision: Float {
60+
case rough = 0.1
61+
case fine = 0.001
62+
}
63+
64+
@JS enum CardinalDirection {
65+
case north
66+
case south
67+
case east
68+
case west
69+
}
70+
71+
@JS
72+
enum TypedPayloadResult {
73+
case precision(Precision)
74+
case direction(CardinalDirection)
75+
case optPrecision(Precision?)
76+
case optDirection(CardinalDirection?)
77+
case empty
78+
}
79+
80+
@JS func roundTripTypedPayloadResult(_ result: TypedPayloadResult) -> TypedPayloadResult
81+
@JS func roundTripOptionalTypedPayloadResult(_ result: TypedPayloadResult?) -> TypedPayloadResult?

0 commit comments

Comments
 (0)