Skip to content

Commit b41ccf0

Browse files
committed
BridgeJS: Support all missing types as associated values in exported enums
1 parent 81885ea commit b41ccf0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+3837
-1293
lines changed

Benchmarks/Sources/Generated/BridgeJS.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,20 +64,20 @@ extension APIResult: _BridgedSwiftAssociatedValueEnum {
6464
@_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() {
6565
switch self {
6666
case .success(let param0):
67-
_swift_js_push_tag(Int32(0))
6867
param0.bridgeJSLowerStackReturn()
68+
_swift_js_push_tag(Int32(0))
6969
case .failure(let param0):
70-
_swift_js_push_tag(Int32(1))
7170
param0.bridgeJSLowerStackReturn()
71+
_swift_js_push_tag(Int32(1))
7272
case .flag(let param0):
73-
_swift_js_push_tag(Int32(2))
7473
param0.bridgeJSLowerStackReturn()
74+
_swift_js_push_tag(Int32(2))
7575
case .rate(let param0):
76-
_swift_js_push_tag(Int32(3))
7776
param0.bridgeJSLowerStackReturn()
77+
_swift_js_push_tag(Int32(3))
7878
case .precise(let param0):
79-
_swift_js_push_tag(Int32(4))
8079
param0.bridgeJSLowerStackReturn()
80+
_swift_js_push_tag(Int32(4))
8181
case .info:
8282
_swift_js_push_tag(Int32(5))
8383
}
@@ -161,29 +161,28 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum {
161161
@_spi(BridgeJS) @_transparent public consuming func bridgeJSLowerReturn() {
162162
switch self {
163163
case .success(let param0):
164-
_swift_js_push_tag(Int32(0))
165164
param0.bridgeJSLowerStackReturn()
165+
_swift_js_push_tag(Int32(0))
166166
case .error(let param0, let param1):
167-
_swift_js_push_tag(Int32(1))
168167
param0.bridgeJSLowerStackReturn()
169168
param1.bridgeJSLowerStackReturn()
169+
_swift_js_push_tag(Int32(1))
170170
case .location(let param0, let param1, let param2):
171-
_swift_js_push_tag(Int32(2))
172171
param0.bridgeJSLowerStackReturn()
173172
param1.bridgeJSLowerStackReturn()
174173
param2.bridgeJSLowerStackReturn()
174+
_swift_js_push_tag(Int32(2))
175175
case .status(let param0, let param1, let param2):
176-
_swift_js_push_tag(Int32(3))
177176
param0.bridgeJSLowerStackReturn()
178177
param1.bridgeJSLowerStackReturn()
179178
param2.bridgeJSLowerStackReturn()
179+
_swift_js_push_tag(Int32(3))
180180
case .coordinates(let param0, let param1, let param2):
181-
_swift_js_push_tag(Int32(4))
182181
param0.bridgeJSLowerStackReturn()
183182
param1.bridgeJSLowerStackReturn()
184183
param2.bridgeJSLowerStackReturn()
184+
_swift_js_push_tag(Int32(4))
185185
case .comprehensive(let param0, let param1, let param2, let param3, let param4, let param5, let param6, let param7, let param8):
186-
_swift_js_push_tag(Int32(5))
187186
param0.bridgeJSLowerStackReturn()
188187
param1.bridgeJSLowerStackReturn()
189188
param2.bridgeJSLowerStackReturn()
@@ -193,6 +192,7 @@ extension ComplexResult: _BridgedSwiftAssociatedValueEnum {
193192
param6.bridgeJSLowerStackReturn()
194193
param7.bridgeJSLowerStackReturn()
195194
param8.bridgeJSLowerStackReturn()
195+
_swift_js_push_tag(Int32(5))
196196
case .info:
197197
_swift_js_push_tag(Int32(6))
198198
}

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1221,9 +1221,11 @@ struct EnumCodegen {
12211221
.map { index, associatedValue in "let \(associatedValue.label ?? "param\(index)")" }
12221222
.joined(separator: ", ")
12231223
cases.append("case .\(enumCase.name)(\(pattern)):")
1224-
cases.append("_swift_js_push_tag(Int32(\(caseIndex)))")
12251224
let payloadCode = generatePayloadPushingCode(associatedValues: enumCase.associatedValues)
12261225
cases.append(contentsOf: payloadCode)
1226+
// Push tag AFTER payloads so it's popped first (LIFO) by the JS lift function.
1227+
// This ensures nested enum tags don't overwrite the outer tag.
1228+
cases.append("_swift_js_push_tag(Int32(\(caseIndex)))")
12271229
}
12281230
}
12291231
return cases

Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,26 +1428,28 @@ 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,
1432+
.swiftStruct, .swiftHeapObject, .jsObject, .associatedValueEnum, .array:
14321433
break
14331434
case .nullable(let wrappedType, _):
14341435
switch wrappedType {
1435-
case .string, .int, .float, .double, .bool:
1436+
case .string, .int, .float, .double, .bool, .caseEnum, .rawValueEnum,
1437+
.swiftStruct, .swiftHeapObject, .jsObject, .associatedValueEnum, .array:
14361438
break
14371439
default:
14381440
diagnose(
14391441
node: node,
14401442
message: "Unsupported associated value type: \(associatedValue.type.swiftType)",
14411443
hint:
1442-
"Only primitive types and optional primitives (String?, Int?, Float?, Double?, Bool?) are supported in associated-value enums"
1444+
"Only primitive types, enums, structs, classes, JSObject, arrays, and their optionals are supported in associated-value enums"
14431445
)
14441446
}
14451447
default:
14461448
diagnose(
14471449
node: node,
14481450
message: "Unsupported associated value type: \(associatedValue.type.swiftType)",
14491451
hint:
1450-
"Only primitive types and optional primitives (String?, Int?, Float?, Double?, Bool?) are supported in associated-value enums"
1452+
"Only primitive types, enums, structs, classes, JSObject, arrays, and their optionals are supported in associated-value enums"
14511453
)
14521454
}
14531455
}

Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ public struct BridgeJSLink {
245245
"let \(JSGlueVariableScope.reservedStorageToReturnOptionalFloat);",
246246
"let \(JSGlueVariableScope.reservedStorageToReturnOptionalDouble);",
247247
"let \(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject);",
248-
"let \(JSGlueVariableScope.reservedTmpRetTag);",
248+
"let \(JSGlueVariableScope.reservedTmpRetTag) = [];",
249249
"let \(JSGlueVariableScope.reservedTmpRetStrings) = [];",
250250
"let \(JSGlueVariableScope.reservedTmpRetInts) = [];",
251251
"let \(JSGlueVariableScope.reservedTmpRetF32s) = [];",
@@ -387,7 +387,7 @@ public struct BridgeJSLink {
387387
printer.write("}")
388388
printer.write("bjs[\"swift_js_push_tag\"] = function(tag) {")
389389
printer.indent {
390-
printer.write("\(JSGlueVariableScope.reservedTmpRetTag) = tag;")
390+
printer.write("\(JSGlueVariableScope.reservedTmpRetTag).push(tag);")
391391
}
392392
printer.write("}")
393393
printer.write("bjs[\"swift_js_push_i32\"] = function(v) {")
@@ -1051,6 +1051,18 @@ public struct BridgeJSLink {
10511051
_ = fragment.printCode([structDef.name], structScope, structPrinter, structCleanup)
10521052
printer.write(lines: structPrinter.lines)
10531053
}
1054+
1055+
let allAssocEnums = exportedSkeletons.flatMap {
1056+
$0.enums.filter { $0.enumType == .associatedValue }
1057+
}
1058+
for enumDef in allAssocEnums {
1059+
let enumPrinter = CodeFragmentPrinter()
1060+
let enumScope = JSGlueVariableScope()
1061+
let enumCleanup = CodeFragmentPrinter()
1062+
let fragment = IntrinsicJSFragment.associatedValueEnumHelperFactory(enumDefinition: enumDef)
1063+
_ = fragment.printCode([enumDef.valuesName], enumScope, enumPrinter, enumCleanup)
1064+
printer.write(lines: enumPrinter.lines)
1065+
}
10541066
printer.nextLine()
10551067
printer.write(contentsOf: generateAddImports(needsImportsObject: data.needsImportsObject))
10561068
}
@@ -1079,8 +1091,6 @@ public struct BridgeJSLink {
10791091
"\(JSGlueVariableScope.reservedMemory) = \(JSGlueVariableScope.reservedInstance).exports.memory;",
10801092
])
10811093
printer.nextLine()
1082-
// Enum helpers section
1083-
printer.write(contentsOf: enumHelperAssignments())
10841094
// Error handling
10851095
printer.write("\(JSGlueVariableScope.reservedSetException) = (error) => {")
10861096
printer.indent {
@@ -1104,8 +1114,9 @@ public struct BridgeJSLink {
11041114

11051115
printer.write(lines: data.classLines)
11061116

1107-
// Struct helpers must be initialized AFTER classes are defined (to allow _exports access)
1117+
// Struct and enum helpers must be initialized AFTER classes are defined (to allow _exports access)
11081118
printer.write(contentsOf: structHelperAssignments())
1119+
printer.write(contentsOf: enumHelperAssignments())
11091120
let namespaceInitCode = namespaceBuilder.buildNamespaceInitialization(
11101121
exportedSkeletons: exportedSkeletons
11111122
)
@@ -1140,7 +1151,7 @@ public struct BridgeJSLink {
11401151
for skeleton in skeletons.compactMap(\.exported) {
11411152
for enumDef in skeleton.enums where enumDef.enumType == .associatedValue {
11421153
printer.write(
1143-
"const \(enumDef.name)Helpers = __bjs_create\(enumDef.valuesName)Helpers()(\(JSGlueVariableScope.reservedTmpParamInts), \(JSGlueVariableScope.reservedTmpParamF32s), \(JSGlueVariableScope.reservedTmpParamF64s), \(JSGlueVariableScope.reservedTextEncoder), \(JSGlueVariableScope.reservedSwift));"
1154+
"const \(enumDef.name)Helpers = __bjs_create\(enumDef.valuesName)Helpers()(\(JSGlueVariableScope.reservedTmpParamInts), \(JSGlueVariableScope.reservedTmpParamF32s), \(JSGlueVariableScope.reservedTmpParamF64s), \(JSGlueVariableScope.reservedTmpParamPointers), \(JSGlueVariableScope.reservedTmpRetPointers), \(JSGlueVariableScope.reservedTextEncoder), \(JSGlueVariableScope.reservedSwift), \(JSGlueVariableScope.reservedStructHelpers), \(JSGlueVariableScope.reservedEnumHelpers));"
11441155
)
11451156
printer.write("\(JSGlueVariableScope.reservedEnumHelpers).\(enumDef.name) = \(enumDef.name)Helpers;")
11461157
printer.nextLine()
@@ -1601,7 +1612,7 @@ public struct BridgeJSLink {
16011612
_ = fragment.printCode([enumValuesName], scope, printer, cleanup)
16021613
jsTopLevelLines.append(contentsOf: printer.lines)
16031614
case .associatedValue:
1604-
let fragment = IntrinsicJSFragment.associatedValueEnumHelper(enumDefinition: enumDefinition)
1615+
let fragment = IntrinsicJSFragment.associatedValueEnumValues(enumDefinition: enumDefinition)
16051616
_ = fragment.printCode([enumValuesName], scope, printer, cleanup)
16061617
jsTopLevelLines.append(contentsOf: printer.lines)
16071618
case .namespace:

0 commit comments

Comments
 (0)