Skip to content

Commit 461360a

Browse files
authored
Merge pull request #824 from PassiveLogic/kr/bridgejs-throw-before-lift
2 parents a0961dd + 99bfd1e commit 461360a

16 files changed

Lines changed: 208 additions & 55 deletions

File tree

‎.github/workflows/test.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ jobs:
163163
# which collapses the wall-clock time from ~1h to that of the slowest single example.
164164
build-examples:
165165
if: github.event_name == 'pull_request'
166-
runs-on: ubuntu-latest
166+
runs-on: ubuntu-22.04
167167
strategy:
168168
fail-fast: false
169169
matrix:
@@ -196,7 +196,7 @@ jobs:
196196
# main: build all examples in release and publish them to GitHub Pages.
197197
build-examples-deploy:
198198
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
199-
runs-on: ubuntu-latest
199+
runs-on: ubuntu-22.04
200200
steps:
201201
- uses: actions/checkout@v7
202202
- uses: ./.github/actions/install-swift

‎Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,6 +1809,7 @@ public struct BridgeJSLink {
18091809
body.write("const \(returnVariable) = \(call);")
18101810
fragmentArguments = [returnVariable]
18111811
}
1812+
body.write(lines: checkExceptionLines())
18121813
let liftedValues = try liftingFragment.printCode(fragmentArguments, context)
18131814
assert(liftedValues.count <= 1, "Lifting fragment should produce at most one value")
18141815
return liftedValues.first
@@ -1818,10 +1819,11 @@ public struct BridgeJSLink {
18181819
let call =
18191820
"\(JSGlueVariableScope.reservedInstance).exports.\(abiName)(\(parameterForwardings.joined(separator: ", ")))"
18201821
body.write("const ret = \(call);")
1822+
body.write(lines: checkExceptionLines())
18211823
return "ret"
18221824
}
18231825

1824-
func checkExceptionLines() -> [String] {
1826+
private func checkExceptionLines() -> [String] {
18251827
guard effects.isThrows else {
18261828
return []
18271829
}
@@ -1837,10 +1839,9 @@ public struct BridgeJSLink {
18371839
]
18381840
}
18391841

1840-
/// Renders the thunk body (body code, exception handling, and optional return) into a printer.
1842+
/// Renders the thunk body and optional return; `call`/`callConstructor` put the exception check in `body`.
18411843
func renderFunctionBody(into printer: CodeFragmentPrinter, returnExpr: String?) {
18421844
printer.write(contentsOf: body)
1843-
printer.write(lines: checkExceptionLines())
18441845
if let returnExpr = returnExpr {
18451846
printer.write("return \(returnExpr);")
18461847
}
@@ -3490,7 +3491,6 @@ extension BridgeJSLink {
34903491
getterPrinter.write("get \(property.resolvedJSName)() {")
34913492
getterPrinter.indent {
34923493
getterPrinter.write(contentsOf: getterThunkBuilder.body)
3493-
getterPrinter.write(lines: getterThunkBuilder.checkExceptionLines())
34943494
if let returnExpr = getterReturnExpr {
34953495
getterPrinter.write("return \(returnExpr);")
34963496
}
@@ -3517,7 +3517,6 @@ extension BridgeJSLink {
35173517
setterPrinter.write("set \(property.resolvedJSName)(\(setterThunkBuilder.parameterList)) {")
35183518
setterPrinter.indent {
35193519
setterPrinter.write(contentsOf: setterThunkBuilder.body)
3520-
setterPrinter.write(lines: setterThunkBuilder.checkExceptionLines())
35213520
}
35223521
setterPrinter.write("},")
35233522

‎Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/MacroSwift/Protocol.swift‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ import JavaScriptKit
107107
@JS func loadLabel(_ key: String) async throws(JSException) -> String {
108108
return try await delegate.loadLabel(key)
109109
}
110+
111+
@JS func validatedDelegate() throws(JSException) -> MyViewControllerDelegate {
112+
_ = try delegate.validate(0)
113+
return delegate
114+
}
110115
}
111116

112117
// Protocol array support

‎Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.json‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,23 @@
286286

287287
}
288288
}
289+
},
290+
{
291+
"abiName" : "bjs_MyViewController_validatedDelegate",
292+
"effects" : {
293+
"isAsync" : false,
294+
"isStatic" : false,
295+
"isThrows" : true
296+
},
297+
"name" : "validatedDelegate",
298+
"parameters" : [
299+
300+
],
301+
"returnType" : {
302+
"swiftProtocol" : {
303+
"_0" : "MyViewControllerDelegate"
304+
}
305+
}
289306
}
290307
],
291308
"name" : "MyViewController",

‎Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,6 +1257,32 @@ public func _bjs_MyViewController_loadLabel(_ _self: UnsafeMutableRawPointer, _
12571257
#endif
12581258
}
12591259

1260+
@_expose(wasm, "bjs_MyViewController_validatedDelegate")
1261+
@_cdecl("bjs_MyViewController_validatedDelegate")
1262+
public func _bjs_MyViewController_validatedDelegate(_ _self: UnsafeMutableRawPointer) -> Int32 {
1263+
#if arch(wasm32)
1264+
let _self = MyViewController.bridgeJSLiftParameter(_self)
1265+
do {
1266+
let ret = _bridgeJSUnwrapProtocolExportable(try _self.validatedDelegate(), "MyViewControllerDelegate")
1267+
return ret.bridgeJSLowerAsProtocolReturn()
1268+
} catch let error {
1269+
if let error = error.thrownValue.object {
1270+
withExtendedLifetime(error) {
1271+
_swift_js_throw(Int32(bitPattern: $0.id))
1272+
}
1273+
} else {
1274+
let jsError = JSError(message: error.description)
1275+
withExtendedLifetime(jsError.jsObject) {
1276+
_swift_js_throw(Int32(bitPattern: $0.id))
1277+
}
1278+
}
1279+
return 0
1280+
}
1281+
#else
1282+
fatalError("Only available on WebAssembly")
1283+
#endif
1284+
}
1285+
12601286
@_expose(wasm, "bjs_MyViewController_delegate_get")
12611287
@_cdecl("bjs_MyViewController_delegate_get")
12621288
public func _bjs_MyViewController_delegate_get(_ _self: UnsafeMutableRawPointer) -> Int32 {

‎Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -944,26 +944,26 @@ export async function createInstantiator(options, swift) {
944944
asyncRoundTripStructThrows: function bjs_asyncRoundTripStructThrows(v) {
945945
structHelpers.M10TestModuleT10AsyncPoint.lower(v);
946946
const ret = instance.exports.bjs_asyncRoundTripStructThrows();
947-
const ret1 = swift.memory.getObject(ret);
948-
swift.memory.release(ret);
949947
if (tmpRetException) {
950948
const error = swift.memory.getObject(tmpRetException);
951949
swift.memory.release(tmpRetException);
952950
tmpRetException = undefined;
953951
throw error;
954952
}
953+
const ret1 = swift.memory.getObject(ret);
954+
swift.memory.release(ret);
955955
return ret1;
956956
},
957957
asyncThrowsZeroArg: function bjs_asyncThrowsZeroArg() {
958958
const ret = instance.exports.bjs_asyncThrowsZeroArg();
959-
const ret1 = swift.memory.getObject(ret);
960-
swift.memory.release(ret);
961959
if (tmpRetException) {
962960
const error = swift.memory.getObject(tmpRetException);
963961
swift.memory.release(tmpRetException);
964962
tmpRetException = undefined;
965963
throw error;
966964
}
965+
const ret1 = swift.memory.getObject(ret);
966+
swift.memory.release(ret);
967967
return ret1;
968968
},
969969
asyncCombineStructs: function bjs_asyncCombineStructs(a, b) {

‎Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -755,14 +755,14 @@ export async function createInstantiator(options, swift) {
755755
const exports = {
756756
makeFoo: function bjs_makeFoo() {
757757
const ret = instance.exports.bjs_makeFoo();
758-
const ret1 = swift.memory.getObject(ret);
759-
swift.memory.release(ret);
760758
if (tmpRetException) {
761759
const error = swift.memory.getObject(tmpRetException);
762760
swift.memory.release(tmpRetException);
763761
tmpRetException = undefined;
764762
throw error;
765763
}
764+
const ret1 = swift.memory.getObject(ret);
765+
swift.memory.release(ret);
766766
return ret1;
767767
},
768768
processFooArray: function bjs_processFooArray(foos) {

‎Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.d.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export interface MyViewController extends SwiftHeapObject {
9393
sendHelper(helper: Helper): void;
9494
validateValue(value: number): number;
9595
loadLabel(key: string): Promise<string>;
96+
validatedDelegate(): MyViewControllerDelegate;
9697
delegate: MyViewControllerDelegate;
9798
secondDelegate: MyViewControllerDelegate | null;
9899
}

‎Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,14 +1363,26 @@ export async function createInstantiator(options, swift) {
13631363
const keyBytes = textEncoder.encode(key);
13641364
const keyId = swift.memory.retain(keyBytes);
13651365
const ret = instance.exports.bjs_MyViewController_loadLabel(this.pointer, keyId, keyBytes.length);
1366+
if (tmpRetException) {
1367+
const error = swift.memory.getObject(tmpRetException);
1368+
swift.memory.release(tmpRetException);
1369+
tmpRetException = undefined;
1370+
throw error;
1371+
}
13661372
const ret1 = swift.memory.getObject(ret);
13671373
swift.memory.release(ret);
1374+
return ret1;
1375+
}
1376+
validatedDelegate() {
1377+
const ret = instance.exports.bjs_MyViewController_validatedDelegate(this.pointer);
13681378
if (tmpRetException) {
13691379
const error = swift.memory.getObject(tmpRetException);
13701380
swift.memory.release(tmpRetException);
13711381
tmpRetException = undefined;
13721382
throw error;
13731383
}
1384+
const ret1 = swift.memory.getObject(ret);
1385+
swift.memory.release(ret);
13741386
return ret1;
13751387
}
13761388
get delegate() {

‎Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -248,14 +248,14 @@ export async function createInstantiator(options, swift) {
248248
bjs["make_swift_closure_TestModule_10TestModule10RenderableP_10RenderableP"] = function(boxPtr, file, line) {
249249
const lower_closure_TestModule_10TestModule10RenderableP_10RenderableP = function(param0) {
250250
const ret = instance.exports.invoke_swift_closure_TestModule_10TestModule10RenderableP_10RenderableP(boxPtr, swift.memory.retain(param0));
251-
const ret1 = swift.memory.getObject(ret);
252-
swift.memory.release(ret);
253251
if (tmpRetException) {
254252
const error = swift.memory.getObject(tmpRetException);
255253
swift.memory.release(tmpRetException);
256254
tmpRetException = undefined;
257255
throw error;
258256
}
257+
const ret1 = swift.memory.getObject(ret);
258+
swift.memory.release(ret);
259259
return ret1;
260260
};
261261
return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule10RenderableP_10RenderableP);
@@ -273,14 +273,14 @@ export async function createInstantiator(options, swift) {
273273
bjs["make_swift_closure_TestModule_10TestModule10RenderableP_SS"] = function(boxPtr, file, line) {
274274
const lower_closure_TestModule_10TestModule10RenderableP_SS = function(param0) {
275275
instance.exports.invoke_swift_closure_TestModule_10TestModule10RenderableP_SS(boxPtr, swift.memory.retain(param0));
276-
const ret = tmpRetString;
277-
tmpRetString = undefined;
278276
if (tmpRetException) {
279277
const error = swift.memory.getObject(tmpRetException);
280278
swift.memory.release(tmpRetException);
281279
tmpRetException = undefined;
282280
throw error;
283281
}
282+
const ret = tmpRetString;
283+
tmpRetString = undefined;
284284
return ret;
285285
};
286286
return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule10RenderableP_SS);
@@ -305,14 +305,14 @@ export async function createInstantiator(options, swift) {
305305
result = 0;
306306
}
307307
instance.exports.invoke_swift_closure_TestModule_10TestModuleSq10RenderableP_SS(boxPtr, +isSome, result);
308-
const ret = tmpRetString;
309-
tmpRetString = undefined;
310308
if (tmpRetException) {
311309
const error = swift.memory.getObject(tmpRetException);
312310
swift.memory.release(tmpRetException);
313311
tmpRetException = undefined;
314312
throw error;
315313
}
314+
const ret = tmpRetString;
315+
tmpRetString = undefined;
316316
return ret;
317317
};
318318
return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq10RenderableP_SS);
@@ -330,14 +330,14 @@ export async function createInstantiator(options, swift) {
330330
bjs["make_swift_closure_TestModule_10TestModuley_10RenderableP"] = function(boxPtr, file, line) {
331331
const lower_closure_TestModule_10TestModuley_10RenderableP = function() {
332332
const ret = instance.exports.invoke_swift_closure_TestModule_10TestModuley_10RenderableP(boxPtr);
333-
const ret1 = swift.memory.getObject(ret);
334-
swift.memory.release(ret);
335333
if (tmpRetException) {
336334
const error = swift.memory.getObject(tmpRetException);
337335
swift.memory.release(tmpRetException);
338336
tmpRetException = undefined;
339337
throw error;
340338
}
339+
const ret1 = swift.memory.getObject(ret);
340+
swift.memory.release(ret);
341341
return ret1;
342342
};
343343
return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuley_10RenderableP);

0 commit comments

Comments
 (0)