BridgeJS: Support all missing types as associated values in exported enums #579
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Overview
Extends associated value enum support to accept all types already supported in struct fields and arrays:
@JS struct,@JS class,JSObject, nested associated value enums, and arrays - including their optional variants.Previously, associated values in exported enums were limited to primitive types (
String,Int,Bool,Float,Double) and simple enums (case/raw value). This PR closes that gap so that any type usable as a struct field can also be used as an enum associated value.Supported types examples
Technical Changes
Enum helper factory scoping
Enum helper factories (lower/lift closures) are now generated inside
createInstantiatoralongside struct helpers, giving them access tostructHelpers,enumHelpers,tmpParamPointers,tmpRetPointers, and class exports via_exports['ClassName']. Previously they were at module scope, which would cause issues when referencing class constructors or struct/enum helpers.Update to
tmpRetTagsingle-register to avoid overwrite for nested enumstmpRetTagwas a single scalar register, not a stack. When an associated value enum contained another associated value enum, the inner enum's_swift_js_push_tag()overwrote the outer enum's tag, causing the JS lift function to misinterpret the case.Fix: Changed
tmpRetTagfrom a scalar to a stack (array with push/pop), matching the other typed stacks. The lift function's first parameter was changed from the array reference to a pre-popped scalartag, allowing both top-level returns (tmpRetTag.pop()) and protocol/closure contexts (already-extracted scalar) to use the same lift function.Additionally,
generateReturnSwitchCasesinExportSwift.swiftnow pushes the tag after payloads (not before). This is required for correctness with the stack-basedtmpRetTag: since stacks use LIFO ordering, the outermost tag must be pushed last so it is popped first. For example, when loweringAllTypesResult.nestedEnum(APIResult.success("nested!")):3pushed → inner enum lowered (pushes inner tag0) → stack is[3, 0]. JS pops and gets0first (wrong — that's the inner tag).0+ payload) → outer tag3pushed last → stack is[0, 3]. JS pops and gets3first (correct outer tag), then when lifting the nested enum payload, pops0(correct inner tag).Refactoring: unified stack
lower/liftfragmentsMostly unified code paths for stack-based types in JSGlueGen, as they handled the same
BridgeType→ stack push/pop logic with near-identical implementations:Tests
AllTypesResultandOptionalAllTypesResultenum definitions in the snapshot input, with updated codegen and link snapshots.Documentation
Exporting Swift Enum doc reflects changes and includes new supported types