diff --git a/change/react-native-windows-2020-04-21-14-06-12-master.json b/change/react-native-windows-2020-04-21-14-06-12-master.json new file mode 100644 index 00000000000..260fedf7a90 --- /dev/null +++ b/change/react-native-windows-2020-04-21-14-06-12-master.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Hook up to packager websocket to allow 'r' to reload instance", + "packageName": "react-native-windows", + "email": "acoates@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-21T21:06:12.961Z" +} \ No newline at end of file diff --git a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp index 0a6f50829b8..e779e411905 100644 --- a/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +++ b/vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp @@ -513,7 +513,7 @@ std::shared_ptr ReactInstanceWin::GetRedBoxHandler() noexcept { std::function ReactInstanceWin::GetLiveReloadCallback() noexcept { // Live reload is enabled if we provide a callback function. - if (m_options.DeveloperSettings.UseLiveReload) { + if (m_options.DeveloperSettings.UseLiveReload || m_options.DeveloperSettings.UseFastRefresh) { return Mso::MakeWeakMemberStdFunction(this, &ReactInstanceWin::OnLiveReload); } return std::function{}; diff --git a/vnext/ReactUWP/Modules/DevSupportManagerUwp.cpp b/vnext/ReactUWP/Modules/DevSupportManagerUwp.cpp index 5cb7e348178..84280333503 100644 --- a/vnext/ReactUWP/Modules/DevSupportManagerUwp.cpp +++ b/vnext/ReactUWP/Modules/DevSupportManagerUwp.cpp @@ -16,6 +16,7 @@ #include "Utilities.h" #include +#include #include #include #include @@ -73,12 +74,64 @@ void DevSupportManager::LaunchDevTools(const facebook::react::DevSettings &setti DownloadFromAsync(facebook::react::DevServerHelper::get_LaunchDevToolsCommandUrl(settings.debugHost)).get(); } +std::future DevSupportManager::CreatePackagerConnection(const facebook::react::DevSettings &settings) { + m_ws = winrt::Windows::Networking::Sockets::MessageWebSocket(); + + m_wsMessageRevoker = m_ws.MessageReceived( + winrt::auto_revoke, [reloadCallback = settings.liveReloadCallback](auto && /*sender*/, auto &&args) noexcept { + try { + auto reader = args.GetDataReader(); + + uint32_t len = reader.UnconsumedBufferLength(); + if (args.MessageType() == winrt::Windows::Networking::Sockets::SocketMessageType::Utf8) { + reader.UnicodeEncoding(winrt::Windows::Storage::Streams::UnicodeEncoding::Utf8); + std::vector data(len); + reader.ReadBytes(data); + + auto response = + std::string(Microsoft::Common::Utilities::CheckedReinterpretCast(data.data()), data.size()); + auto json = + winrt::Windows::Data::Json::JsonObject::Parse(Microsoft::Common::Unicode::Utf8ToUtf16(response)); + + auto version = (int)json.GetNamedNumber(L"version", 0.0); + if (version != 2) { + return; + } + auto method = std::wstring(json.GetNamedString(L"method", L"")); + if (method.empty()) { + return; + } + + if (!method.compare(L"reload")) { + reloadCallback(); + } else if (!method.compare(L"devMenu")) { + // TODO showDevMenu + } else if (!method.compare(L"captureHeap")) { + // TODO captureHeap + } + } + } catch (winrt::hresult_error const &e) { + } + }); + + winrt::Windows::Foundation::Uri uri( + Microsoft::Common::Unicode::Utf8ToUtf16("ws://" + settings.debugHost + "/message")); + auto async = m_ws.ConnectAsync(uri); + +#ifdef DEFAULT_CPPWINRT_EXCEPTIONS + co_await async; +#else + co_await lessthrow_await_adapter{async}; +#endif +} + facebook::react::JSECreator DevSupportManager::LoadJavaScriptInProxyMode(const facebook::react::DevSettings &settings) { // Reset exception state since client is requesting new service m_exceptionCaught = false; try { LaunchDevTools(settings); + CreatePackagerConnection(settings); return [this, settings]( std::shared_ptr delegate, diff --git a/vnext/ReactUWP/Modules/DevSupportManagerUwp.h b/vnext/ReactUWP/Modules/DevSupportManagerUwp.h index 13ccda97aca..be3aa05b994 100644 --- a/vnext/ReactUWP/Modules/DevSupportManagerUwp.h +++ b/vnext/ReactUWP/Modules/DevSupportManagerUwp.h @@ -7,6 +7,7 @@ #include +#include #include #include #include @@ -39,8 +40,11 @@ class DevSupportManager : public facebook::react::IDevSupportManager { private: void LaunchDevTools(const facebook::react::DevSettings &settings); + std::future CreatePackagerConnection(const facebook::react::DevSettings &settings); private: + winrt::Windows::Networking::Sockets::MessageWebSocket m_ws{nullptr}; + winrt::Windows::Networking::Sockets::MessageWebSocket::MessageReceived_revoker m_wsMessageRevoker; bool m_exceptionCaught = false; std::atomic_bool m_cancellation_token; }; diff --git a/vnext/Shared/OInstance.cpp b/vnext/Shared/OInstance.cpp index 2da2a031bd1..3a9ba283c58 100644 --- a/vnext/Shared/OInstance.cpp +++ b/vnext/Shared/OInstance.cpp @@ -661,7 +661,7 @@ std::vector> InstanceImpl::GetDefaultNativeModules void InstanceImpl::RegisterForReloadIfNecessary() noexcept { // setup polling for live reload - if (!m_devManager->HasException() && m_devSettings->liveReloadCallback != nullptr) { + if (!m_devManager->HasException() && !m_devSettings->useFastRefresh && m_devSettings->liveReloadCallback != nullptr) { m_devManager->StartPollingLiveReload(m_devSettings->debugHost, m_devSettings->liveReloadCallback); } }