Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -182,16 +182,7 @@ public func _bjs_PlayBridgeJS_updateDetailed(_ _self: UnsafeMutableRawPointer, _
let ret = try PlayBridgeJS.bridgeJSLiftParameter(_self).updateDetailed(swiftSource: String.bridgeJSLiftParameter(swiftSourceBytes, swiftSourceLength), dtsSource: String.bridgeJSLiftParameter(dtsSourceBytes, dtsSourceLength))
return ret.bridgeJSLowerReturn()
} catch let error {
if let error = error.thrownValue.object {
withExtendedLifetime(error) {
_swift_js_throw(Int32(bitPattern: $0.id))
}
} else {
let jsError = JSError(message: String(describing: error))
withExtendedLifetime(jsError.jsObject) {
_swift_js_throw(Int32(bitPattern: $0.id))
}
}
error.bridgeJSLowerThrow()
return
}
#else
Expand Down
36 changes: 16 additions & 20 deletions Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift
Original file line number Diff line number Diff line change
Expand Up @@ -318,20 +318,25 @@ public class ExportSwift {

func render(abiName: String) -> DeclSyntax {
let body: CodeBlockItemListSyntax
if effects.isAsync {
if effects.isAsync, effects.isThrows {
// Explicit closure type annotation needed when throws is present
// so Swift infers throws(JSException) instead of throws(any Error)
// See: https://github.com/swiftlang/swift/issues/76165
let closureHead: String
if effects.isThrows {
let hasReturn = self.body.contains { $0.description.contains("return ") }
let ret = hasReturn ? " -> JSValue" : ""
closureHead = " () async throws(JSException)\(ret) in"
} else {
closureHead = ""
}
let hasReturn = self.body.contains { $0.description.contains("return ") }
let ret = hasReturn ? " -> JSValue" : ""
body = """
let ret = JSPromise.async {\(raw: closureHead)
let ret = JSPromise.async { () async throws(JSException)\(raw: ret) in
do {
\(CodeBlockItemListSyntax(self.body))
} catch let error {
throw error.bridgeJSLowerThrowAsync()
}
}.jsObject
return ret.bridgeJSLowerReturn()
"""
} else if effects.isAsync {
body = """
let ret = JSPromise.async {
\(CodeBlockItemListSyntax(self.body))
}.jsObject
return ret.bridgeJSLowerReturn()
Expand All @@ -341,16 +346,7 @@ public class ExportSwift {
do {
\(CodeBlockItemListSyntax(self.body))
} catch let error {
if let error = error.thrownValue.object {
withExtendedLifetime(error) {
_swift_js_throw(Int32(bitPattern: $0.id))
}
} else {
let jsError = JSError(message: String(describing: error))
withExtendedLifetime(jsError.jsObject) {
_swift_js_throw(Int32(bitPattern: $0.id))
}
}
error.bridgeJSLowerThrow()
\(raw: returnPlaceholderStmt())
}
"""
Expand Down
14 changes: 4 additions & 10 deletions Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1122,18 +1122,12 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor {
let isAsync = signature.effectSpecifiers?.asyncSpecifier != nil
var isThrows = false
if let throwsClause: ThrowsClauseSyntax = signature.effectSpecifiers?.throwsClause {
// Limit the thrown type to JSException for now
guard let thrownType = throwsClause.type else {
// Require typed throws for now
guard throwsClause.type != nil else {
diagnose(
node: throwsClause,
message: "Thrown type is not specified, only JSException is supported for now"
)
return nil
}
guard thrownType.trimmedDescription == "JSException" else {
diagnose(
node: throwsClause,
message: "Only JSException is supported for thrown type, got \(thrownType.trimmedDescription)"
message:
"Thrown type must be specified. Only JSException or any error conforming to ConvertibleToJSException is supported"
)
return nil
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@JS func asyncThrowsVoid() async throws(JSException) {
throw JSException(message: "TestError")
}

@JS func asyncThrowsWithResult() async throws(JSException) -> Int {
return 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"exported" : {
"classes" : [

],
"enums" : [

],
"exposeToGlobal" : false,
"functions" : [
{
"abiName" : "bjs_asyncThrowsVoid",
"effects" : {
"isAsync" : true,
"isStatic" : false,
"isThrows" : true
},
"name" : "asyncThrowsVoid",
"parameters" : [

],
"returnType" : {
"void" : {

}
}
},
{
"abiName" : "bjs_asyncThrowsWithResult",
"effects" : {
"isAsync" : true,
"isStatic" : false,
"isThrows" : true
},
"name" : "asyncThrowsWithResult",
"parameters" : [

],
"returnType" : {
"int" : {

}
}
}
],
"protocols" : [

],
"structs" : [

]
},
"moduleName" : "TestModule"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@_expose(wasm, "bjs_asyncThrowsVoid")
@_cdecl("bjs_asyncThrowsVoid")
public func _bjs_asyncThrowsVoid() -> Int32 {
#if arch(wasm32)
let ret = JSPromise.async { () async throws(JSException) in
do {
try await asyncThrowsVoid()
} catch let error {
throw error.bridgeJSLowerThrowAsync()
}
}.jsObject
return ret.bridgeJSLowerReturn()
#else
fatalError("Only available on WebAssembly")
#endif
}

@_expose(wasm, "bjs_asyncThrowsWithResult")
@_cdecl("bjs_asyncThrowsWithResult")
public func _bjs_asyncThrowsWithResult() -> Int32 {
#if arch(wasm32)
let ret = JSPromise.async { () async throws(JSException) -> JSValue in
do {
return try await asyncThrowsWithResult().jsValue
} catch let error {
throw error.bridgeJSLowerThrowAsync()
}
}.jsObject
return ret.bridgeJSLowerReturn()
#else
fatalError("Only available on WebAssembly")
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,7 @@ public func _bjs_Services_Graph_GraphOperations_static_validate(_ graphId: Int32
let ret = try GraphOperations.validate(graphId: Int.bridgeJSLiftParameter(graphId))
return ret.bridgeJSLowerReturn()
} catch let error {
if let error = error.thrownValue.object {
withExtendedLifetime(error) {
_swift_js_throw(Int32(bitPattern: $0.id))
}
} else {
let jsError = JSError(message: String(describing: error))
withExtendedLifetime(jsError.jsObject) {
_swift_js_throw(Int32(bitPattern: $0.id))
}
}
error.bridgeJSLowerThrow()
return 0
}
#else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,7 @@ public func _bjs_Services_Graph_GraphOperations_static_validate(_ graphId: Int32
let ret = try GraphOperations.validate(graphId: Int.bridgeJSLiftParameter(graphId))
return ret.bridgeJSLowerReturn()
} catch let error {
if let error = error.thrownValue.object {
withExtendedLifetime(error) {
_swift_js_throw(Int32(bitPattern: $0.id))
}
} else {
let jsError = JSError(message: String(describing: error))
withExtendedLifetime(jsError.jsObject) {
_swift_js_throw(Int32(bitPattern: $0.id))
}
}
error.bridgeJSLowerThrow()
return 0
}
#else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,7 @@ public func _bjs_makeFoo() -> Int32 {
let ret = try makeFoo()
return ret.bridgeJSLowerReturn()
} catch let error {
if let error = error.thrownValue.object {
withExtendedLifetime(error) {
_swift_js_throw(Int32(bitPattern: $0.id))
}
} else {
let jsError = JSError(message: String(describing: error))
withExtendedLifetime(jsError.jsObject) {
_swift_js_throw(Int32(bitPattern: $0.id))
}
}
error.bridgeJSLowerThrow()
return 0
}
#else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,7 @@ public func _bjs_throwsSomething() -> Void {
do {
try throwsSomething()
} catch let error {
if let error = error.thrownValue.object {
withExtendedLifetime(error) {
_swift_js_throw(Int32(bitPattern: $0.id))
}
} else {
let jsError = JSError(message: String(describing: error))
withExtendedLifetime(jsError.jsObject) {
_swift_js_throw(Int32(bitPattern: $0.id))
}
}
error.bridgeJSLowerThrow()
return
}
#else
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// NOTICE: This is auto-generated code by BridgeJS from JavaScriptKit,
// DO NOT EDIT.
//
// To update this file, just rebuild your project or run
// `swift package bridge-js`.

export type Exports = {
asyncThrowsVoid(): Promise<void>;
asyncThrowsWithResult(): Promise<number>;
}
export type Imports = {
}
export function createInstantiator(options: {
imports: Imports;
}, swift: any): Promise<{
addImports: (importObject: WebAssembly.Imports) => void;
setInstance: (instance: WebAssembly.Instance) => void;
createExports: (instance: WebAssembly.Instance) => Exports;
}>;
Loading
Loading