Skip to content

Commit 19f9d4f

Browse files
committed
BridgeJS: Move optional JSObject to stack ABI, enabling Optional<@jsclass>
1 parent 824c051 commit 19f9d4f

13 files changed

Lines changed: 295 additions & 109 deletions

File tree

Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,10 @@ extension BridgeType {
10321032
case .namespaceEnum:
10331033
throw BridgeJSCoreError("Namespace enums cannot be used as return values")
10341034
case .nullable(let wrappedType, _):
1035+
if !self.usesSideChannelForOptionalReturn() {
1036+
// Stack ABI: the extern returns void, values go through typed stacks
1037+
return LiftingReturnInfo(valueToLift: nil)
1038+
}
10351039
let wrappedInfo = try wrappedType.liftingReturnInfo(context: context)
10361040
return LiftingReturnInfo(valueToLift: wrappedInfo.valueToLift)
10371041
case .array, .dictionary:

Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2648,7 +2648,7 @@ private extension BridgeType {
26482648
case .string:
26492649
return .sideChannelReturn(.storage)
26502650
case .jsObject:
2651-
return .sideChannelReturn(.retainedObject)
2651+
return .stackABI
26522652
case .jsValue:
26532653
return .inlineFlag
26542654
case .swiftHeapObject:
@@ -2685,7 +2685,7 @@ private extension BridgeType {
26852685

26862686
var nilSentinel: NilSentinel {
26872687
switch self {
2688-
case .jsObject, .swiftProtocol:
2688+
case .swiftProtocol:
26892689
return .i32(0)
26902690
case .swiftHeapObject:
26912691
return .pointer

Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,7 +1655,7 @@ extension BridgeType {
16551655
}
16561656

16571657
switch wrappedType {
1658-
case .string, .integer, .float, .double, .jsObject, .swiftProtocol:
1658+
case .string, .integer, .float, .double, .swiftProtocol:
16591659
return true
16601660
case .rawValueEnum(_, let rawType):
16611661
switch rawType {
@@ -1666,7 +1666,7 @@ extension BridgeType {
16661666
default:
16671667
return false
16681668
}
1669-
case .bool, .caseEnum, .swiftHeapObject, .associatedValueEnum:
1669+
case .bool, .caseEnum, .swiftHeapObject, .associatedValueEnum, .jsObject:
16701670
return false
16711671
default:
16721672
return false

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,10 @@ func testMixedOptionals(firstName: String?, lastName: String?, age: Int?, active
155155
@JSSetter func setIntOrUndefined(_ value: JSUndefinedOr<Int>) throws(JSException)
156156
@JSFunction func roundTripIntOrNull(value: Int?) throws(JSException) -> Int?
157157
@JSFunction func roundTripIntOrUndefined(value: JSUndefinedOr<Int>) throws(JSException) -> JSUndefinedOr<Int>
158+
159+
@JSGetter var childOrNull: WithOptionalJSClass?
160+
@JSSetter func setChildOrNull(_ value: WithOptionalJSClass?) throws(JSException)
161+
@JSFunction func roundTripChildOrNull(
162+
value: WithOptionalJSClass?
163+
) throws(JSException) -> WithOptionalJSClass?
158164
}

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.json

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,20 @@
11581158
"_1" : "undefined"
11591159
}
11601160
}
1161+
},
1162+
{
1163+
"accessLevel" : "internal",
1164+
"name" : "childOrNull",
1165+
"type" : {
1166+
"nullable" : {
1167+
"_0" : {
1168+
"jsObject" : {
1169+
"_0" : "WithOptionalJSClass"
1170+
}
1171+
},
1172+
"_1" : "null"
1173+
}
1174+
}
11611175
}
11621176
],
11631177
"methods" : [
@@ -1444,6 +1458,40 @@
14441458
"_1" : "undefined"
14451459
}
14461460
}
1461+
},
1462+
{
1463+
"accessLevel" : "internal",
1464+
"effects" : {
1465+
"isAsync" : false,
1466+
"isStatic" : false,
1467+
"isThrows" : true
1468+
},
1469+
"name" : "roundTripChildOrNull",
1470+
"parameters" : [
1471+
{
1472+
"name" : "value",
1473+
"type" : {
1474+
"nullable" : {
1475+
"_0" : {
1476+
"jsObject" : {
1477+
"_0" : "WithOptionalJSClass"
1478+
}
1479+
},
1480+
"_1" : "null"
1481+
}
1482+
}
1483+
}
1484+
],
1485+
"returnType" : {
1486+
"nullable" : {
1487+
"_0" : {
1488+
"jsObject" : {
1489+
"_0" : "WithOptionalJSClass"
1490+
}
1491+
},
1492+
"_1" : "null"
1493+
}
1494+
}
14471495
}
14481496
],
14491497
"name" : "WithOptionalJSClass",
@@ -1573,6 +1621,21 @@
15731621
"_1" : "undefined"
15741622
}
15751623
}
1624+
},
1625+
{
1626+
"accessLevel" : "internal",
1627+
"functionName" : "childOrNull_set",
1628+
"name" : "childOrNull",
1629+
"type" : {
1630+
"nullable" : {
1631+
"_0" : {
1632+
"jsObject" : {
1633+
"_0" : "WithOptionalJSClass"
1634+
}
1635+
},
1636+
"_1" : "null"
1637+
}
1638+
}
15761639
}
15771640
],
15781641
"staticMethods" : [

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.swift

Lines changed: 84 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -480,25 +480,25 @@ fileprivate func bjs_WithOptionalJSClass_doubleOrUndefined_get_extern(_ self: In
480480

481481
#if arch(wasm32)
482482
@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_boolOrNull_get")
483-
fileprivate func bjs_WithOptionalJSClass_boolOrNull_get_extern(_ self: Int32) -> Int32
483+
fileprivate func bjs_WithOptionalJSClass_boolOrNull_get_extern(_ self: Int32) -> Void
484484
#else
485-
fileprivate func bjs_WithOptionalJSClass_boolOrNull_get_extern(_ self: Int32) -> Int32 {
485+
fileprivate func bjs_WithOptionalJSClass_boolOrNull_get_extern(_ self: Int32) -> Void {
486486
fatalError("Only available on WebAssembly")
487487
}
488488
#endif
489-
@inline(never) fileprivate func bjs_WithOptionalJSClass_boolOrNull_get(_ self: Int32) -> Int32 {
489+
@inline(never) fileprivate func bjs_WithOptionalJSClass_boolOrNull_get(_ self: Int32) -> Void {
490490
return bjs_WithOptionalJSClass_boolOrNull_get_extern(self)
491491
}
492492

493493
#if arch(wasm32)
494494
@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_boolOrUndefined_get")
495-
fileprivate func bjs_WithOptionalJSClass_boolOrUndefined_get_extern(_ self: Int32) -> Int32
495+
fileprivate func bjs_WithOptionalJSClass_boolOrUndefined_get_extern(_ self: Int32) -> Void
496496
#else
497-
fileprivate func bjs_WithOptionalJSClass_boolOrUndefined_get_extern(_ self: Int32) -> Int32 {
497+
fileprivate func bjs_WithOptionalJSClass_boolOrUndefined_get_extern(_ self: Int32) -> Void {
498498
fatalError("Only available on WebAssembly")
499499
}
500500
#endif
501-
@inline(never) fileprivate func bjs_WithOptionalJSClass_boolOrUndefined_get(_ self: Int32) -> Int32 {
501+
@inline(never) fileprivate func bjs_WithOptionalJSClass_boolOrUndefined_get(_ self: Int32) -> Void {
502502
return bjs_WithOptionalJSClass_boolOrUndefined_get_extern(self)
503503
}
504504

@@ -526,6 +526,18 @@ fileprivate func bjs_WithOptionalJSClass_intOrUndefined_get_extern(_ self: Int32
526526
return bjs_WithOptionalJSClass_intOrUndefined_get_extern(self)
527527
}
528528

529+
#if arch(wasm32)
530+
@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_childOrNull_get")
531+
fileprivate func bjs_WithOptionalJSClass_childOrNull_get_extern(_ self: Int32) -> Void
532+
#else
533+
fileprivate func bjs_WithOptionalJSClass_childOrNull_get_extern(_ self: Int32) -> Void {
534+
fatalError("Only available on WebAssembly")
535+
}
536+
#endif
537+
@inline(never) fileprivate func bjs_WithOptionalJSClass_childOrNull_get(_ self: Int32) -> Void {
538+
return bjs_WithOptionalJSClass_childOrNull_get_extern(self)
539+
}
540+
529541
#if arch(wasm32)
530542
@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_stringOrNull_set")
531543
fileprivate func bjs_WithOptionalJSClass_stringOrNull_set_extern(_ self: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void
@@ -622,6 +634,18 @@ fileprivate func bjs_WithOptionalJSClass_intOrUndefined_set_extern(_ self: Int32
622634
return bjs_WithOptionalJSClass_intOrUndefined_set_extern(self, newValueIsSome, newValueValue)
623635
}
624636

637+
#if arch(wasm32)
638+
@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_childOrNull_set")
639+
fileprivate func bjs_WithOptionalJSClass_childOrNull_set_extern(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void
640+
#else
641+
fileprivate func bjs_WithOptionalJSClass_childOrNull_set_extern(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void {
642+
fatalError("Only available on WebAssembly")
643+
}
644+
#endif
645+
@inline(never) fileprivate func bjs_WithOptionalJSClass_childOrNull_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueValue: Int32) -> Void {
646+
return bjs_WithOptionalJSClass_childOrNull_set_extern(self, newValueIsSome, newValueValue)
647+
}
648+
625649
#if arch(wasm32)
626650
@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripStringOrNull")
627651
fileprivate func bjs_WithOptionalJSClass_roundTripStringOrNull_extern(_ self: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void
@@ -672,25 +696,25 @@ fileprivate func bjs_WithOptionalJSClass_roundTripDoubleOrUndefined_extern(_ sel
672696

673697
#if arch(wasm32)
674698
@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripBoolOrNull")
675-
fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrNull_extern(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Int32
699+
fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrNull_extern(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void
676700
#else
677-
fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrNull_extern(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Int32 {
701+
fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrNull_extern(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void {
678702
fatalError("Only available on WebAssembly")
679703
}
680704
#endif
681-
@inline(never) fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrNull(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Int32 {
705+
@inline(never) fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrNull(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void {
682706
return bjs_WithOptionalJSClass_roundTripBoolOrNull_extern(self, valueIsSome, valueValue)
683707
}
684708

685709
#if arch(wasm32)
686710
@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripBoolOrUndefined")
687-
fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrUndefined_extern(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Int32
711+
fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrUndefined_extern(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void
688712
#else
689-
fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrUndefined_extern(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Int32 {
713+
fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrUndefined_extern(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void {
690714
fatalError("Only available on WebAssembly")
691715
}
692716
#endif
693-
@inline(never) fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrUndefined(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Int32 {
717+
@inline(never) fileprivate func bjs_WithOptionalJSClass_roundTripBoolOrUndefined(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void {
694718
return bjs_WithOptionalJSClass_roundTripBoolOrUndefined_extern(self, valueIsSome, valueValue)
695719
}
696720

@@ -718,6 +742,18 @@ fileprivate func bjs_WithOptionalJSClass_roundTripIntOrUndefined_extern(_ self:
718742
return bjs_WithOptionalJSClass_roundTripIntOrUndefined_extern(self, valueIsSome, valueValue)
719743
}
720744

745+
#if arch(wasm32)
746+
@_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripChildOrNull")
747+
fileprivate func bjs_WithOptionalJSClass_roundTripChildOrNull_extern(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void
748+
#else
749+
fileprivate func bjs_WithOptionalJSClass_roundTripChildOrNull_extern(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void {
750+
fatalError("Only available on WebAssembly")
751+
}
752+
#endif
753+
@inline(never) fileprivate func bjs_WithOptionalJSClass_roundTripChildOrNull(_ self: Int32, _ valueIsSome: Int32, _ valueValue: Int32) -> Void {
754+
return bjs_WithOptionalJSClass_roundTripChildOrNull_extern(self, valueIsSome, valueValue)
755+
}
756+
721757
func _$WithOptionalJSClass_init(_ valueOrNull: Optional<String>, _ valueOrUndefined: JSUndefinedOr<String>) throws(JSException) -> JSObject {
722758
let ret0 = valueOrNull.bridgeJSWithLoweredParameter { (valueOrNullIsSome, valueOrNullBytes, valueOrNullLength) in
723759
let ret1 = valueOrUndefined.bridgeJSWithLoweredParameter { (valueOrUndefinedIsSome, valueOrUndefinedBytes, valueOrUndefinedLength) in
@@ -771,20 +807,20 @@ func _$WithOptionalJSClass_doubleOrUndefined_get(_ self: JSObject) throws(JSExce
771807

772808
func _$WithOptionalJSClass_boolOrNull_get(_ self: JSObject) throws(JSException) -> Optional<Bool> {
773809
let selfValue = self.bridgeJSLowerParameter()
774-
let ret = bjs_WithOptionalJSClass_boolOrNull_get(selfValue)
810+
bjs_WithOptionalJSClass_boolOrNull_get(selfValue)
775811
if let error = _swift_js_take_exception() {
776812
throw error
777813
}
778-
return Optional<Bool>.bridgeJSLiftReturn(ret)
814+
return Optional<Bool>.bridgeJSLiftReturn()
779815
}
780816

781817
func _$WithOptionalJSClass_boolOrUndefined_get(_ self: JSObject) throws(JSException) -> JSUndefinedOr<Bool> {
782818
let selfValue = self.bridgeJSLowerParameter()
783-
let ret = bjs_WithOptionalJSClass_boolOrUndefined_get(selfValue)
819+
bjs_WithOptionalJSClass_boolOrUndefined_get(selfValue)
784820
if let error = _swift_js_take_exception() {
785821
throw error
786822
}
787-
return JSUndefinedOr<Bool>.bridgeJSLiftReturn(ret)
823+
return JSUndefinedOr<Bool>.bridgeJSLiftReturn()
788824
}
789825

790826
func _$WithOptionalJSClass_intOrNull_get(_ self: JSObject) throws(JSException) -> Optional<Int> {
@@ -805,6 +841,15 @@ func _$WithOptionalJSClass_intOrUndefined_get(_ self: JSObject) throws(JSExcepti
805841
return JSUndefinedOr<Int>.bridgeJSLiftReturnFromSideChannel()
806842
}
807843

844+
func _$WithOptionalJSClass_childOrNull_get(_ self: JSObject) throws(JSException) -> Optional<WithOptionalJSClass> {
845+
let selfValue = self.bridgeJSLowerParameter()
846+
bjs_WithOptionalJSClass_childOrNull_get(selfValue)
847+
if let error = _swift_js_take_exception() {
848+
throw error
849+
}
850+
return Optional<WithOptionalJSClass>.bridgeJSLiftReturn()
851+
}
852+
808853
func _$WithOptionalJSClass_stringOrNull_set(_ self: JSObject, _ newValue: Optional<String>) throws(JSException) -> Void {
809854
let selfValue = self.bridgeJSLowerParameter()
810855
newValue.bridgeJSWithLoweredParameter { (newValueIsSome, newValueBytes, newValueLength) in
@@ -879,6 +924,15 @@ func _$WithOptionalJSClass_intOrUndefined_set(_ self: JSObject, _ newValue: JSUn
879924
}
880925
}
881926

927+
func _$WithOptionalJSClass_childOrNull_set(_ self: JSObject, _ newValue: Optional<WithOptionalJSClass>) throws(JSException) -> Void {
928+
let selfValue = self.bridgeJSLowerParameter()
929+
let (newValueIsSome, newValueValue) = newValue.bridgeJSLowerParameter()
930+
bjs_WithOptionalJSClass_childOrNull_set(selfValue, newValueIsSome, newValueValue)
931+
if let error = _swift_js_take_exception() {
932+
throw error
933+
}
934+
}
935+
882936
func _$WithOptionalJSClass_roundTripStringOrNull(_ self: JSObject, _ value: Optional<String>) throws(JSException) -> Optional<String> {
883937
let selfValue = self.bridgeJSLowerParameter()
884938
value.bridgeJSWithLoweredParameter { (valueIsSome, valueBytes, valueLength) in
@@ -924,21 +978,21 @@ func _$WithOptionalJSClass_roundTripDoubleOrUndefined(_ self: JSObject, _ value:
924978
func _$WithOptionalJSClass_roundTripBoolOrNull(_ self: JSObject, _ value: Optional<Bool>) throws(JSException) -> Optional<Bool> {
925979
let selfValue = self.bridgeJSLowerParameter()
926980
let (valueIsSome, valueValue) = value.bridgeJSLowerParameter()
927-
let ret = bjs_WithOptionalJSClass_roundTripBoolOrNull(selfValue, valueIsSome, valueValue)
981+
bjs_WithOptionalJSClass_roundTripBoolOrNull(selfValue, valueIsSome, valueValue)
928982
if let error = _swift_js_take_exception() {
929983
throw error
930984
}
931-
return Optional<Bool>.bridgeJSLiftReturn(ret)
985+
return Optional<Bool>.bridgeJSLiftReturn()
932986
}
933987

934988
func _$WithOptionalJSClass_roundTripBoolOrUndefined(_ self: JSObject, _ value: JSUndefinedOr<Bool>) throws(JSException) -> JSUndefinedOr<Bool> {
935989
let selfValue = self.bridgeJSLowerParameter()
936990
let (valueIsSome, valueValue) = value.bridgeJSLowerParameter()
937-
let ret = bjs_WithOptionalJSClass_roundTripBoolOrUndefined(selfValue, valueIsSome, valueValue)
991+
bjs_WithOptionalJSClass_roundTripBoolOrUndefined(selfValue, valueIsSome, valueValue)
938992
if let error = _swift_js_take_exception() {
939993
throw error
940994
}
941-
return JSUndefinedOr<Bool>.bridgeJSLiftReturn(ret)
995+
return JSUndefinedOr<Bool>.bridgeJSLiftReturn()
942996
}
943997

944998
func _$WithOptionalJSClass_roundTripIntOrNull(_ self: JSObject, _ value: Optional<Int>) throws(JSException) -> Optional<Int> {
@@ -959,4 +1013,14 @@ func _$WithOptionalJSClass_roundTripIntOrUndefined(_ self: JSObject, _ value: JS
9591013
throw error
9601014
}
9611015
return JSUndefinedOr<Int>.bridgeJSLiftReturnFromSideChannel()
1016+
}
1017+
1018+
func _$WithOptionalJSClass_roundTripChildOrNull(_ self: JSObject, _ value: Optional<WithOptionalJSClass>) throws(JSException) -> Optional<WithOptionalJSClass> {
1019+
let selfValue = self.bridgeJSLowerParameter()
1020+
let (valueIsSome, valueValue) = value.bridgeJSLowerParameter()
1021+
bjs_WithOptionalJSClass_roundTripChildOrNull(selfValue, valueIsSome, valueValue)
1022+
if let error = _swift_js_take_exception() {
1023+
throw error
1024+
}
1025+
return Optional<WithOptionalJSClass>.bridgeJSLiftReturn()
9621026
}

0 commit comments

Comments
 (0)