Skip to content

Commit 1c4d924

Browse files
committed
BridgeJS: Exception checking on protocol wrapper methods
1 parent c814901 commit 1c4d924

File tree

8 files changed

+287
-91
lines changed

8 files changed

+287
-91
lines changed

Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1410,7 +1410,7 @@ struct ProtocolCodegen {
14101410
let builder = ImportTS.CallJSEmission(
14111411
moduleName: moduleName,
14121412
abiName: "_extern_\(method.name)",
1413-
context: .exportSwift
1413+
context: .exportSwiftProtocol
14141414
)
14151415
try builder.lowerParameter(param: Parameter(label: nil, name: "jsObject", type: .jsObject(nil)))
14161416
for param in method.parameters {

Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,8 @@ public struct ImportTS {
187187
body.append("let ret = \(raw: callExpr)")
188188
}
189189

190-
// Add exception check for ImportTS context
191-
if context == .importTS {
190+
// Add exception check for contexts that call INTO JavaScript
191+
if context == .importTS || context == .exportSwiftProtocol {
192192
body.append("if let error = _swift_js_take_exception() { throw error }")
193193
}
194194
}
@@ -887,7 +887,7 @@ extension BridgeType {
887887
Swift classes can only be used in @JS protocols where Swift owns the instance.
888888
"""
889889
)
890-
case .exportSwift:
890+
case .exportSwift, .exportSwiftProtocol:
891891
return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)])
892892
}
893893
case .swiftProtocol:
@@ -896,30 +896,30 @@ extension BridgeType {
896896
switch context {
897897
case .importTS:
898898
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
899-
case .exportSwift:
899+
case .exportSwift, .exportSwiftProtocol:
900900
return LoweringParameterInfo(loweredParameters: [("value", .i32)])
901901
}
902902
case .rawValueEnum(_, let rawType):
903903
switch context {
904904
case .importTS:
905905
return LoweringParameterInfo(loweredParameters: [("value", rawType.wasmCoreType ?? .i32)])
906-
case .exportSwift:
906+
case .exportSwift, .exportSwiftProtocol:
907907
// For protocol export we return .i32 for String raw value type instead of nil
908908
return LoweringParameterInfo(loweredParameters: [("value", rawType.wasmCoreType ?? .i32)])
909909
}
910910
case .associatedValueEnum:
911911
switch context {
912912
case .importTS:
913913
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
914-
case .exportSwift:
914+
case .exportSwift, .exportSwiftProtocol:
915915
return LoweringParameterInfo(loweredParameters: [("caseId", .i32)])
916916
}
917917
case .swiftStruct:
918918
switch context {
919919
case .importTS:
920920
// Swift structs are bridged as JS objects (object IDs) in imported signatures.
921921
return LoweringParameterInfo(loweredParameters: [("objectId", .i32)])
922-
case .exportSwift:
922+
case .exportSwift, .exportSwiftProtocol:
923923
return LoweringParameterInfo(loweredParameters: [])
924924
}
925925
case .namespaceEnum:
@@ -928,7 +928,7 @@ extension BridgeType {
928928
switch context {
929929
case .importTS:
930930
throw BridgeJSCoreError("Optional types are not yet supported in TypeScript imports")
931-
case .exportSwift:
931+
case .exportSwift, .exportSwiftProtocol:
932932
let wrappedInfo = try wrappedType.loweringParameterInfo(context: context)
933933
var params = [("isSome", WasmCoreType.i32)]
934934
params.append(contentsOf: wrappedInfo.loweredParameters)
@@ -938,7 +938,7 @@ extension BridgeType {
938938
switch context {
939939
case .importTS:
940940
throw BridgeJSCoreError("Array types are not yet supported in TypeScript imports")
941-
case .exportSwift:
941+
case .exportSwift, .exportSwiftProtocol:
942942
return LoweringParameterInfo(loweredParameters: [])
943943
}
944944
}
@@ -981,7 +981,7 @@ extension BridgeType {
981981
JavaScript cannot create Swift heap objects.
982982
"""
983983
)
984-
case .exportSwift:
984+
case .exportSwift, .exportSwiftProtocol:
985985
return LiftingReturnInfo(valueToLift: .pointer)
986986
}
987987
case .swiftProtocol:
@@ -990,30 +990,30 @@ extension BridgeType {
990990
switch context {
991991
case .importTS:
992992
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
993-
case .exportSwift:
993+
case .exportSwift, .exportSwiftProtocol:
994994
return LiftingReturnInfo(valueToLift: .i32)
995995
}
996996
case .rawValueEnum(_, let rawType):
997997
switch context {
998998
case .importTS:
999999
return LiftingReturnInfo(valueToLift: rawType.wasmCoreType ?? .i32)
1000-
case .exportSwift:
1000+
case .exportSwift, .exportSwiftProtocol:
10011001
// For protocol export we return .i32 for String raw value type instead of nil
10021002
return LiftingReturnInfo(valueToLift: rawType.wasmCoreType ?? .i32)
10031003
}
10041004
case .associatedValueEnum:
10051005
switch context {
10061006
case .importTS:
10071007
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
1008-
case .exportSwift:
1008+
case .exportSwift, .exportSwiftProtocol:
10091009
return LiftingReturnInfo(valueToLift: .i32)
10101010
}
10111011
case .swiftStruct:
10121012
switch context {
10131013
case .importTS:
10141014
// Swift structs are bridged as JS objects (object IDs) in imported signatures.
10151015
return LiftingReturnInfo(valueToLift: .i32)
1016-
case .exportSwift:
1016+
case .exportSwift, .exportSwiftProtocol:
10171017
return LiftingReturnInfo(valueToLift: nil)
10181018
}
10191019
case .namespaceEnum:
@@ -1022,15 +1022,15 @@ extension BridgeType {
10221022
switch context {
10231023
case .importTS:
10241024
throw BridgeJSCoreError("Optional types are not yet supported in TypeScript imports")
1025-
case .exportSwift:
1025+
case .exportSwift, .exportSwiftProtocol:
10261026
let wrappedInfo = try wrappedType.liftingReturnInfo(context: context)
10271027
return LiftingReturnInfo(valueToLift: wrappedInfo.valueToLift)
10281028
}
10291029
case .array:
10301030
switch context {
10311031
case .importTS:
10321032
throw BridgeJSCoreError("Array types are not yet supported in TypeScript imports")
1033-
case .exportSwift:
1033+
case .exportSwift, .exportSwiftProtocol:
10341034
return LiftingReturnInfo(valueToLift: nil)
10351035
}
10361036
}

Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,7 +1477,7 @@ struct IntrinsicJSFragment: Sendable {
14771477
throw BridgeJSLinkError(
14781478
message: "swiftHeapObject '\(name)' can only be used in protocol exports, not in \(context)"
14791479
)
1480-
case .exportSwift:
1480+
case .exportSwift, .exportSwiftProtocol:
14811481
return .swiftHeapObjectLiftParameter(name)
14821482
}
14831483
case .swiftProtocol: return .jsObjectLiftParameter
@@ -1491,7 +1491,7 @@ struct IntrinsicJSFragment: Sendable {
14911491
throw BridgeJSLinkError(
14921492
message: "Optional types are not supported for imported JS functions: \(wrappedType)"
14931493
)
1494-
case .exportSwift:
1494+
case .exportSwift, .exportSwiftProtocol:
14951495
return try .optionalLiftParameter(wrappedType: wrappedType)
14961496
}
14971497
case .caseEnum: return .identity
@@ -1508,7 +1508,7 @@ struct IntrinsicJSFragment: Sendable {
15081508
message:
15091509
"Associated value enums are not supported to be passed as parameters to imported JS functions: \(fullName)"
15101510
)
1511-
case .exportSwift:
1511+
case .exportSwift, .exportSwiftProtocol:
15121512
let base = fullName.components(separatedBy: ".").last ?? fullName
15131513
return IntrinsicJSFragment(
15141514
parameters: ["caseId"],
@@ -1526,7 +1526,7 @@ struct IntrinsicJSFragment: Sendable {
15261526
switch context {
15271527
case .importTS:
15281528
return .jsObjectLiftRetainedObjectId
1529-
case .exportSwift:
1529+
case .exportSwift, .exportSwiftProtocol:
15301530
let base = fullName.components(separatedBy: ".").last ?? fullName
15311531
return IntrinsicJSFragment(
15321532
parameters: [],
@@ -1558,7 +1558,7 @@ struct IntrinsicJSFragment: Sendable {
15581558
throw BridgeJSLinkError(
15591559
message: "Arrays are not yet supported to be passed as parameters to imported JS functions"
15601560
)
1561-
case .exportSwift:
1561+
case .exportSwift, .exportSwiftProtocol:
15621562
return try arrayLift(elementType: elementType)
15631563
}
15641564
}
@@ -1578,7 +1578,7 @@ struct IntrinsicJSFragment: Sendable {
15781578
throw BridgeJSLinkError(
15791579
message: "swiftHeapObject '\(name)' can only be used in protocol exports, not in \(context)"
15801580
)
1581-
case .exportSwift:
1581+
case .exportSwift, .exportSwiftProtocol:
15821582
return .swiftHeapObjectLowerReturn
15831583
}
15841584
case .swiftProtocol: return .jsObjectLowerReturn
@@ -1589,7 +1589,7 @@ struct IntrinsicJSFragment: Sendable {
15891589
throw BridgeJSLinkError(
15901590
message: "Optional types are not supported for imported JS functions: \(wrappedType)"
15911591
)
1592-
case .exportSwift:
1592+
case .exportSwift, .exportSwiftProtocol:
15931593
return try .optionalLowerReturn(wrappedType: wrappedType)
15941594
}
15951595
case .caseEnum: return .identity
@@ -1606,15 +1606,15 @@ struct IntrinsicJSFragment: Sendable {
16061606
message:
16071607
"Associated value enums are not supported to be returned from imported JS functions: \(fullName)"
16081608
)
1609-
case .exportSwift:
1609+
case .exportSwift, .exportSwiftProtocol:
16101610
return associatedValueLowerReturn(fullName: fullName)
16111611
}
16121612
case .swiftStruct(let fullName):
16131613
switch context {
16141614
case .importTS:
16151615
// ImportTS expects Swift structs to come back as a retained JS object ID.
16161616
return .jsObjectLowerReturn
1617-
case .exportSwift:
1617+
case .exportSwift, .exportSwiftProtocol:
16181618
return swiftStructLowerReturn(fullName: fullName)
16191619
}
16201620
case .closure:
@@ -1640,7 +1640,7 @@ struct IntrinsicJSFragment: Sendable {
16401640
throw BridgeJSLinkError(
16411641
message: "Arrays are not yet supported to be returned from imported JS functions"
16421642
)
1643-
case .exportSwift:
1643+
case .exportSwift, .exportSwiftProtocol:
16441644
return try arrayLower(elementType: elementType)
16451645
}
16461646
}

Plugins/BridgeJS/Sources/BridgeJSSkeleton/BridgeJSSkeleton.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public struct ABINameGenerator {
7171
public enum BridgeContext: Sendable {
7272
case importTS
7373
case exportSwift
74+
case exportSwiftProtocol
7475
}
7576

7677
public struct ClosureSignature: Codable, Equatable, Hashable, Sendable {

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/ExportSwiftTests/Protocol.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,27 @@ struct AnyMyViewControllerDelegate: MyViewControllerDelegate, _BridgedSwiftProto
44
func onSomethingHappened() throws(JSException) -> Void {
55
let jsObjectValue = jsObject.bridgeJSLowerParameter()
66
_extern_onSomethingHappened(jsObjectValue)
7+
if let error = _swift_js_take_exception() {
8+
throw error
9+
}
710
}
811

912
func onValueChanged(_ value: String) throws(JSException) -> Void {
1013
let jsObjectValue = jsObject.bridgeJSLowerParameter()
1114
let valueValue = value.bridgeJSLowerParameter()
1215
_extern_onValueChanged(jsObjectValue, valueValue)
16+
if let error = _swift_js_take_exception() {
17+
throw error
18+
}
1319
}
1420

1521
func onCountUpdated(count: Int) throws(JSException) -> Bool {
1622
let jsObjectValue = jsObject.bridgeJSLowerParameter()
1723
let countValue = count.bridgeJSLowerParameter()
1824
let ret = _extern_onCountUpdated(jsObjectValue, countValue)
25+
if let error = _swift_js_take_exception() {
26+
throw error
27+
}
1928
return Bool.bridgeJSLiftReturn(ret)
2029
}
2130

@@ -24,53 +33,80 @@ struct AnyMyViewControllerDelegate: MyViewControllerDelegate, _BridgedSwiftProto
2433
let prefixValue = prefix.bridgeJSLowerParameter()
2534
let suffixValue = suffix.bridgeJSLowerParameter()
2635
_extern_onLabelUpdated(jsObjectValue, prefixValue, suffixValue)
36+
if let error = _swift_js_take_exception() {
37+
throw error
38+
}
2739
}
2840

2941
func isCountEven() throws(JSException) -> Bool {
3042
let jsObjectValue = jsObject.bridgeJSLowerParameter()
3143
let ret = _extern_isCountEven(jsObjectValue)
44+
if let error = _swift_js_take_exception() {
45+
throw error
46+
}
3247
return Bool.bridgeJSLiftReturn(ret)
3348
}
3449

3550
func onHelperUpdated(_ helper: Helper) throws(JSException) -> Void {
3651
let jsObjectValue = jsObject.bridgeJSLowerParameter()
3752
let helperPointer = helper.bridgeJSLowerParameter()
3853
_extern_onHelperUpdated(jsObjectValue, helperPointer)
54+
if let error = _swift_js_take_exception() {
55+
throw error
56+
}
3957
}
4058

4159
func createHelper() throws(JSException) -> Helper {
4260
let jsObjectValue = jsObject.bridgeJSLowerParameter()
4361
let ret = _extern_createHelper(jsObjectValue)
62+
if let error = _swift_js_take_exception() {
63+
throw error
64+
}
4465
return Helper.bridgeJSLiftReturn(ret)
4566
}
4667

4768
func onOptionalHelperUpdated(_ helper: Optional<Helper>) throws(JSException) -> Void {
4869
let jsObjectValue = jsObject.bridgeJSLowerParameter()
4970
let (helperIsSome, helperPointer) = helper.bridgeJSLowerParameter()
5071
_extern_onOptionalHelperUpdated(jsObjectValue, helperIsSome, helperPointer)
72+
if let error = _swift_js_take_exception() {
73+
throw error
74+
}
5175
}
5276

5377
func createOptionalHelper() throws(JSException) -> Optional<Helper> {
5478
let jsObjectValue = jsObject.bridgeJSLowerParameter()
5579
let ret = _extern_createOptionalHelper(jsObjectValue)
80+
if let error = _swift_js_take_exception() {
81+
throw error
82+
}
5683
return Optional<Helper>.bridgeJSLiftReturn(ret)
5784
}
5885

5986
func createEnum() throws(JSException) -> ExampleEnum {
6087
let jsObjectValue = jsObject.bridgeJSLowerParameter()
6188
let ret = _extern_createEnum(jsObjectValue)
89+
if let error = _swift_js_take_exception() {
90+
throw error
91+
}
6292
return ExampleEnum.bridgeJSLiftReturn(ret)
6393
}
6494

6595
func handleResult(_ result: Result) throws(JSException) -> Void {
6696
let jsObjectValue = jsObject.bridgeJSLowerParameter()
6797
let resultCaseId = result.bridgeJSLowerParameter()
6898
_extern_handleResult(jsObjectValue, resultCaseId)
99+
if let error = _swift_js_take_exception() {
100+
throw error
101+
}
69102
}
70103

71104
func getResult() throws(JSException) -> Result {
72105
let jsObjectValue = jsObject.bridgeJSLowerParameter()
73106
let ret = _extern_getResult(jsObjectValue)
107+
if let error = _swift_js_take_exception() {
108+
throw error
109+
}
74110
return Result.bridgeJSLiftReturn(ret)
75111
}
76112

0 commit comments

Comments
 (0)