From aebcff8ce51571fb1293ac6828d4d634598ddd14 Mon Sep 17 00:00:00 2001 From: Effet Date: Tue, 10 Mar 2026 10:22:43 +0800 Subject: [PATCH] fix(macos): use foundationValue when serializing browser proxy POST body --- .../NodeMode/MacNodeBrowserProxy.swift | 4 +-- .../MacNodeBrowserProxyTests.swift | 33 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/apps/macos/Sources/OpenClaw/NodeMode/MacNodeBrowserProxy.swift b/apps/macos/Sources/OpenClaw/NodeMode/MacNodeBrowserProxy.swift index 0da6510f608..367907f9fb7 100644 --- a/apps/macos/Sources/OpenClaw/NodeMode/MacNodeBrowserProxy.swift +++ b/apps/macos/Sources/OpenClaw/NodeMode/MacNodeBrowserProxy.swift @@ -146,8 +146,8 @@ actor MacNodeBrowserProxy { request.setValue(password, forHTTPHeaderField: "x-openclaw-password") } - if method != "GET", let body = params.body?.value { - request.httpBody = try JSONSerialization.data(withJSONObject: body, options: [.fragmentsAllowed]) + if method != "GET", let body = params.body { + request.httpBody = try JSONSerialization.data(withJSONObject: body.foundationValue, options: [.fragmentsAllowed]) request.setValue("application/json", forHTTPHeaderField: "Content-Type") } diff --git a/apps/macos/Tests/OpenClawIPCTests/MacNodeBrowserProxyTests.swift b/apps/macos/Tests/OpenClawIPCTests/MacNodeBrowserProxyTests.swift index c000f6d4241..a044025562f 100644 --- a/apps/macos/Tests/OpenClawIPCTests/MacNodeBrowserProxyTests.swift +++ b/apps/macos/Tests/OpenClawIPCTests/MacNodeBrowserProxyTests.swift @@ -38,4 +38,37 @@ struct MacNodeBrowserProxyTests { #expect(tabs.count == 1) #expect(tabs[0]["id"] as? String == "tab-1") } + + // Regression test: POST body with nested AnyCodable must not crash with __SwiftValue + @Test func postRequestSerializesNestedBodyWithoutCrash() async throws { + var capturedBody: Data? + let proxy = MacNodeBrowserProxy( + endpointProvider: { + MacNodeBrowserProxy.Endpoint( + baseURL: URL(string: "http://127.0.0.1:18791")!, + token: nil, + password: nil) + }, + performRequest: { request in + capturedBody = request.httpBody + let url = try #require(request.url) + let response = try #require( + HTTPURLResponse( + url: url, + statusCode: 200, + httpVersion: nil, + headerFields: nil)) + return (Data(#"{"ok":true}"#.utf8), response) + }) + + _ = try await proxy.request( + paramsJSON: #"{"method":"POST","path":"/action","body":{"nested":{"key":"val"},"arr":[1,2]}}"#) + + let bodyData = try #require(capturedBody) + let parsed = try #require(JSONSerialization.jsonObject(with: bodyData) as? [String: Any]) + let nested = try #require(parsed["nested"] as? [String: Any]) + #expect(nested["key"] as? String == "val") + let arr = try #require(parsed["arr"] as? [Any]) + #expect(arr.count == 2) + } }