fix(mac): avoid crash decoding gateway frames

This commit is contained in:
Peter Steinberger
2025-12-09 17:36:16 +00:00
parent 1f19ca1665
commit fcc8d59588
3 changed files with 38 additions and 2 deletions

View File

@@ -62,7 +62,7 @@ let package = Package(
]),
.testTarget(
name: "ClawdisIPCTests",
dependencies: ["ClawdisIPC", "Clawdis"],
dependencies: ["ClawdisIPC", "Clawdis", "ClawdisProtocol"],
swiftSettings: [
.enableUpcomingFeature("StrictConcurrency"),
.enableExperimentalFeature("SwiftTesting"),

View File

@@ -500,7 +500,12 @@ public enum GatewayFrame: Codable {
}
private static func decodePayload<T: Decodable>(_ type: T.Type, from raw: [String: AnyCodable]) throws -> T {
let data = try JSONSerialization.data(withJSONObject: raw)
// Re-encode the already-decoded map using `JSONEncoder` instead of
// `JSONSerialization` because `AnyCodable` values are not bridged to
// Objective-C types and `JSONSerialization` throws an ObjC exception,
// crashing the app (seen on macOS 26.1). `JSONEncoder` understands
// `Encodable` values and stays in Swift land.
let data = try JSONEncoder().encode(raw)
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
}

View File

@@ -0,0 +1,31 @@
import Foundation
import Testing
import ClawdisProtocol
@Suite struct GatewayFrameDecodeTests {
@Test func decodesEventFrameWithAnyCodablePayload() throws {
let json = """
{
"type": "event",
"event": "presence",
"payload": { "foo": "bar", "count": 1 },
"seq": 7
}
"""
let frame = try JSONDecoder().decode(GatewayFrame.self, from: Data(json.utf8))
#expect({
if case .event = frame { true } else { false }
}(), "expected .event frame")
guard case let .event(evt) = frame else {
return
}
let payload = evt.payload?.value as? [String: AnyCodable]
#expect(payload?["foo"]?.value as? String == "bar")
#expect(payload?["count"]?.value as? Int == 1)
#expect(evt.seq == 7)
}
}