Skip to content
Merged
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
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Fix unhandled synchronous throw from ConnectAsync",
"packageName": "react-native-windows",
"email": "julio.rocha@microsoft.com",
"dependentChangeType": "patch"
}
33 changes: 33 additions & 0 deletions vnext/Desktop.UnitTests/WinRTWebSocketResourceUnitTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,39 @@ TEST_CLASS (WinRTWebSocketResourceUnitTest) {
Assert::IsFalse(connected);
}

BEGIN_TEST_METHOD_ATTRIBUTE(ConnectAsyncThrowsSynchronously)
END_TEST_METHOD_ATTRIBUTE()
TEST_METHOD(ConnectAsyncThrowsSynchronously) {
Logger::WriteMessage("Microsoft::React::Test::WinRTWebSocketResourceUnitTest::ConnectAsyncThrowsSynchronously");
bool connected = false;
string errorMessage;
promise<void> donePromise;

auto imws{winrt::make<MockMessageWebSocket>()};
auto mws{imws.as<MockMessageWebSocket>()};
// Simulate a synchronous throw from ConnectAsync (e.g. WININET_E_INVALID_CA)
// before any IAsyncAction is returned.
mws->Mocks.ConnectAsync = [](const Uri &) -> IAsyncAction {
throw winrt::hresult_error(winrt::hresult(0x80072EE1), L"Invalid CA");
};

auto rc = make_shared<WinRTWebSocketResource2>(
std::move(imws), MockDataWriter{}, CertExceptions{}, Mso::DispatchQueue::MakeSerialQueue());
rc->SetOnConnect([&connected]() { connected = true; });
rc->SetOnError([&errorMessage, &donePromise](Error &&error) {
errorMessage = error.Message;
donePromise.set_value();
});

rc->Connect(testUrl, {}, {});
rc->Close(CloseCode::Normal, {});

donePromise.get_future().wait();

Assert::AreEqual({"[0x80072ee1] Invalid CA"}, errorMessage);
Assert::IsFalse(connected);
}

BEGIN_TEST_METHOD_ATTRIBUTE(SetRequestHeaderFails)
END_TEST_METHOD_ATTRIBUTE()
TEST_METHOD(SetRequestHeaderFails) {
Expand Down
9 changes: 5 additions & 4 deletions vnext/Shared/Networking/WinRTWebSocketResource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,12 @@ fire_and_forget WinRTWebSocketResource2::PerformConnect(Uri &&uri) noexcept {
[self = self->shared_from_this(), coUri = std::move(movedUri)]() -> IAsyncAction {
auto coSelf = self->shared_from_this();

auto async = coSelf->m_socket.ConnectAsync(coUri);
co_await lessthrow_await_adapter<IAsyncAction>{async};

auto result = async.ErrorCode();
try {
// `ConnectAsync` MAY throw synchronously (e.g. WININET_E_INVALID_CA)
auto async = coSelf->m_socket.ConnectAsync(coUri);
co_await lessthrow_await_adapter<IAsyncAction>{async};

auto result = async.ErrorCode();
if (result >= 0) { // Non-failing HRESULT
coSelf->m_readyState = ReadyState::Open;

Expand Down
Loading