diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift index ef39000b1..7e075a8af 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/SwiftToSkeleton.swift @@ -1986,6 +1986,14 @@ private final class ExportSwiftAPICollector: SyntaxAnyVisitor { guard let effects = collectEffects(signature: node.signature) else { return .skipChildren } + if effects.isAsync || effects.isThrows { + diagnose( + node: node, + message: "@JS struct initializer cannot be async or throw", + hint: "BridgeJS calls this initializer to rebuild struct values passed from JavaScript" + ) + return .skipChildren + } let structAbiName = exportedStructByName[structKey]?.abiName ?? "unknown" let constructor = ExportedConstructor( diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift index 580360bb7..aadf04f00 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift @@ -535,6 +535,21 @@ import Testing #expect(skeleton.exported != nil) } + @Test + func throwingStructInitProducesDiagnostic() throws { + let source = """ + @JS struct Point { + var x: Double + + @JS init(x: Double) throws(JSException) { + self.x = x + } + } + """ + let diagnostics = try #require(moduleDiagnostics(source: source)) + #expect(diagnostics.description.contains("@JS struct initializer cannot be async or throw")) + } + @Test func structWithoutExplicitInitSucceeds() throws { let source = """