From 817c861bb712a9a34f826f21074cd05dee424aef Mon Sep 17 00:00:00 2001 From: Branimir Karadzic Date: Fri, 10 Jul 2026 15:53:08 -0700 Subject: [PATCH 1/2] Win32: surface the real error when opening a URL fails UrlRequest::Impl::Open constructs a WinRT Foundation::Uri, which throws a winrt::hresult_error (not a std::exception) when the input is not a valid, supported URL. Callers such as the JsRuntimeHost XMLHttpRequest polyfill only catch std::exception, so the real failure was collapsed into a generic `Unknown error opening URL` with no HRESULT or message -- making these failures impossible to triage. Convert the hresult_error into a std::runtime_error that includes the offending URL, the system message, and the HRESULT, so the polyfill's existing catch (const std::exception&) reports the real reason. Also stop silently discarding the hresult_error in SendAsync: keep the status-0 (client-side error) contract but record the message/HRESULT into StatusText so send-time failures are diagnosable too. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Source/UrlRequest_Win32.cpp | 10 ++++++++-- Source/UrlRequest_Windows_Shared.h | 17 ++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Source/UrlRequest_Win32.cpp b/Source/UrlRequest_Win32.cpp index 2420b20..80a3199 100644 --- a/Source/UrlRequest_Win32.cpp +++ b/Source/UrlRequest_Win32.cpp @@ -38,9 +38,15 @@ namespace UrlLib return LoadHttpAsync(); } } - catch (winrt::hresult_error) + catch (const winrt::hresult_error& error) { - // Catch WinRT exceptions, but retain the default status code of 0 to indicate a client side error. + // Retain the default status code of 0 to indicate a client-side error, but + // capture the real WinRT error into the status text instead of discarding it, + // so the failure is diagnosable (e.g. surfaced via XMLHttpRequest.statusText). + std::ostringstream message; + message << winrt::to_string(error.message()) << " (HRESULT 0x" << std::hex << std::uppercase + << static_cast(error.code()) << ")"; + m_statusText = message.str(); return arcana::task_from_result(); } } diff --git a/Source/UrlRequest_Windows_Shared.h b/Source/UrlRequest_Windows_Shared.h index 2d04b5a..02a2ec5 100644 --- a/Source/UrlRequest_Windows_Shared.h +++ b/Source/UrlRequest_Windows_Shared.h @@ -1,5 +1,6 @@ #include "UrlRequest_Base.h" +#include #include #include #include @@ -53,7 +54,21 @@ namespace UrlLib #endif m_method = method; - m_uri = Foundation::Uri{winrt::to_hstring(url)}; + try + { + m_uri = Foundation::Uri{winrt::to_hstring(url)}; + } + catch (const winrt::hresult_error& error) + { + // Foundation::Uri rejects some inputs (e.g. malformed or unsupported URLs) + // by throwing a WinRT hresult_error, which is not a std::exception. Rethrow + // as std::runtime_error so callers (e.g. the XMLHttpRequest polyfill) surface + // the real reason instead of a generic "Unknown error opening URL". + std::ostringstream message; + message << "Unable to open URL '" << url << "': " << winrt::to_string(error.message()) + << " (HRESULT 0x" << std::hex << std::uppercase << static_cast(error.code()) << ")"; + throw std::runtime_error{message.str()}; + } } arcana::task SendAsync(); From 97b2206928efed1e2c5ea77ef9f88e1918196f13 Mon Sep 17 00:00:00 2001 From: Branimir Karadzic Date: Fri, 10 Jul 2026 16:08:14 -0700 Subject: [PATCH 2/2] Win32: report send-time WinRT failures via SetError instead of StatusText Address review feedback: transport-level failures should be recorded through the public SetError API (ErrorString/ErrorSymbol/ErrorCode), consistent with the curl (Unix) and NSURL (Apple) backends, rather than written into StatusText -- which is documented as the HTTP reason phrase. The status code still stays 0 (client-side error), preserving the existing contract. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Source/UrlRequest_Win32.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/UrlRequest_Win32.cpp b/Source/UrlRequest_Win32.cpp index 80a3199..b179663 100644 --- a/Source/UrlRequest_Win32.cpp +++ b/Source/UrlRequest_Win32.cpp @@ -40,13 +40,13 @@ namespace UrlLib } catch (const winrt::hresult_error& error) { - // Retain the default status code of 0 to indicate a client-side error, but - // capture the real WinRT error into the status text instead of discarding it, - // so the failure is diagnosable (e.g. surfaced via XMLHttpRequest.statusText). - std::ostringstream message; - message << winrt::to_string(error.message()) << " (HRESULT 0x" << std::hex << std::uppercase - << static_cast(error.code()) << ")"; - m_statusText = message.str(); + // Retain the default status code of 0 to indicate a client-side (transport) + // error, but record the WinRT failure via SetError -- consistent with the + // curl/NSURL backends -- so it is diagnosable through + // ErrorString()/ErrorSymbol()/ErrorCode() instead of being silently discarded. + std::ostringstream symbol; + symbol << "0x" << std::hex << std::uppercase << static_cast(error.code()); + SetError("winrt", symbol.str(), static_cast(error.code()), winrt::to_string(error.message())); return arcana::task_from_result(); } }