Skip to content

Commit dcc148f

Browse files
committed
BridgeJS: Support all missing types as associated values in exported enums
1 parent 16e3f44 commit dcc148f

Some content is hidden

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

57 files changed

+3911
-1297
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: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ public struct BridgeJSLink {
246246
"let \(JSGlueVariableScope.reservedStorageToReturnOptionalFloat);",
247247
"let \(JSGlueVariableScope.reservedStorageToReturnOptionalDouble);",
248248
"let \(JSGlueVariableScope.reservedStorageToReturnOptionalHeapObject);",
249-
"let \(JSGlueVariableScope.reservedTmpRetTag);",
249+
"let \(JSGlueVariableScope.reservedTmpRetTag) = [];",
250250
"let \(JSGlueVariableScope.reservedTmpRetStrings) = [];",
251251
"let \(JSGlueVariableScope.reservedTmpRetInts) = [];",
252252
"let \(JSGlueVariableScope.reservedTmpRetF32s) = [];",
@@ -388,7 +388,7 @@ public struct BridgeJSLink {
388388
printer.write("}")
389389
printer.write("bjs[\"swift_js_push_tag\"] = function(tag) {")
390390
printer.indent {
391-
printer.write("\(JSGlueVariableScope.reservedTmpRetTag) = tag;")
391+
printer.write("\(JSGlueVariableScope.reservedTmpRetTag).push(tag);")
392392
}
393393
printer.write("}")
394394
printer.write("bjs[\"swift_js_push_i32\"] = function(v) {")
@@ -1059,6 +1059,18 @@ public struct BridgeJSLink {
10591059
_ = fragment.printCode([structDef.name], structScope, structPrinter, structCleanup)
10601060
bodyPrinter.write(lines: structPrinter.lines)
10611061
}
1062+
1063+
let allAssocEnums = exportedSkeletons.flatMap {
1064+
$0.enums.filter { $0.enumType == .associatedValue }
1065+
}
1066+
for enumDef in allAssocEnums {
1067+
let enumPrinter = CodeFragmentPrinter()
1068+
let enumScope = JSGlueVariableScope()
1069+
let enumCleanup = CodeFragmentPrinter()
1070+
let fragment = IntrinsicJSFragment.associatedValueEnumHelperFactory(enumDefinition: enumDef)
1071+
_ = fragment.printCode([enumDef.valuesName], enumScope, enumPrinter, enumCleanup)
1072+
bodyPrinter.write(lines: enumPrinter.lines)
1073+
}
10621074
bodyPrinter.nextLine()
10631075
bodyPrinter.write(contentsOf: generateAddImports(needsImportsObject: data.needsImportsObject))
10641076

@@ -1094,8 +1106,6 @@ public struct BridgeJSLink {
10941106
"\(JSGlueVariableScope.reservedMemory) = \(JSGlueVariableScope.reservedInstance).exports.memory;",
10951107
])
10961108
printer.nextLine()
1097-
// Enum helpers section
1098-
printer.write(contentsOf: enumHelperAssignments())
10991109
// Error handling
11001110
printer.write("\(JSGlueVariableScope.reservedSetException) = (error) => {")
11011111
printer.indent {
@@ -1109,18 +1119,19 @@ public struct BridgeJSLink {
11091119
}
11101120

11111121
// createExports method
1112-
try printer.indent {
1122+
printer.indent {
11131123
printer.write(lines: [
11141124
"/** @param {WebAssembly.Instance} instance */",
11151125
"createExports: (instance) => {",
11161126
])
1117-
try printer.indent {
1127+
printer.indent {
11181128
printer.write("const js = \(JSGlueVariableScope.reservedSwift).memory.heap;")
11191129

11201130
printer.write(lines: data.classLines)
11211131

1122-
// Struct helpers must be initialized AFTER classes are defined (to allow _exports access)
1132+
// Struct and enum helpers must be initialized AFTER classes are defined (to allow _exports access)
11231133
printer.write(contentsOf: structHelperAssignments())
1134+
printer.write(contentsOf: enumHelperAssignments())
11241135
let namespaceInitCode = namespaceBuilder.buildNamespaceInitialization(
11251136
exportedSkeletons: exportedSkeletons
11261137
)
@@ -1151,7 +1162,7 @@ public struct BridgeJSLink {
11511162
for skeleton in skeletons.compactMap(\.exported) {
11521163
for enumDef in skeleton.enums where enumDef.enumType == .associatedValue {
11531164
printer.write(
1154-
"const \(enumDef.name)Helpers = __bjs_create\(enumDef.valuesName)Helpers()(\(JSGlueVariableScope.reservedTmpParamInts), \(JSGlueVariableScope.reservedTmpParamF32s), \(JSGlueVariableScope.reservedTmpParamF64s), \(JSGlueVariableScope.reservedTextEncoder), \(JSGlueVariableScope.reservedSwift));"
1165+
"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));"
11551166
)
11561167
printer.write("\(JSGlueVariableScope.reservedEnumHelpers).\(enumDef.name) = \(enumDef.name)Helpers;")
11571168
printer.nextLine()
@@ -1616,7 +1627,7 @@ public struct BridgeJSLink {
16161627
_ = fragment.printCode([enumValuesName], scope, printer, cleanup)
16171628
jsTopLevelLines.append(contentsOf: printer.lines)
16181629
case .associatedValue:
1619-
let fragment = IntrinsicJSFragment.associatedValueEnumHelper(enumDefinition: enumDefinition)
1630+
let fragment = IntrinsicJSFragment.associatedValueEnumValues(enumDefinition: enumDefinition)
16201631
_ = fragment.printCode([enumValuesName], scope, printer, cleanup)
16211632
jsTopLevelLines.append(contentsOf: printer.lines)
16221633
case .namespace:

0 commit comments

Comments
 (0)