diff --git a/change/react-native-windows-dce01c53-5395-463d-bbfd-9162cd9f309d.json b/change/react-native-windows-dce01c53-5395-463d-bbfd-9162cd9f309d.json
new file mode 100644
index 00000000000..6f9c48cce80
--- /dev/null
+++ b/change/react-native-windows-dce01c53-5395-463d-bbfd-9162cd9f309d.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "C++ 20: Move vnext to C++ 20 and C++ 20 coroutines",
+ "packageName": "react-native-windows",
+ "email": "ngerlem@fb.com",
+ "dependentChangeType": "patch"
+}
diff --git a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj
index c117e37a61e..6cfa6a9194a 100644
--- a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj
+++ b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj
@@ -69,7 +69,6 @@
$(VCInstallDir)UnitTest\include;
%(AdditionalIncludeDirectories)
- %(AdditionalOptions) /await
diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj
index d14e1c1910a..10617b136f4 100644
--- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj
+++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj
@@ -95,7 +95,7 @@
$(IntDir)pch.pch
pch.h
Level4
- /await %(AdditionalOptions) /bigobj /ZH:SHA_256
+ %(AdditionalOptions) /bigobj /ZH:SHA_256
$(FmtDir)\include;
$(ReactNativeWindowsDir)Microsoft.ReactNative;
diff --git a/vnext/Microsoft.ReactNative/Utils/LocalBundleReader.cpp b/vnext/Microsoft.ReactNative/Utils/LocalBundleReader.cpp
index 08e5fe4d20b..9f8d8fdcf1f 100644
--- a/vnext/Microsoft.ReactNative/Utils/LocalBundleReader.cpp
+++ b/vnext/Microsoft.ReactNative/Utils/LocalBundleReader.cpp
@@ -53,7 +53,8 @@ std::string GetBundleFromEmbeddedResource(const winrt::Windows::Foundation::Uri
return std::string(start, start + size);
}
-std::future LocalBundleReader::LoadBundleAsync(const std::wstring bundleUri) {
+winrt::Windows::Foundation::IAsyncOperation LocalBundleReader::LoadBundleAsync(
+ const std::wstring bundleUri) {
co_await winrt::resume_background();
winrt::Windows::Storage::StorageFile file{nullptr};
@@ -65,7 +66,7 @@ std::future LocalBundleReader::LoadBundleAsync(const std::wstring b
file = co_await winrt::Windows::Storage::StorageFile::GetFileFromApplicationUriAsync(uri);
} else if (bundleUri._Starts_with(L"resource://")) {
winrt::Windows::Foundation::Uri uri(bundleUri);
- co_return GetBundleFromEmbeddedResource(uri);
+ co_return winrt::to_hstring(GetBundleFromEmbeddedResource(uri));
} else {
file = co_await winrt::Windows::Storage::StorageFile::GetFileFromPathAsync(bundleUri);
}
@@ -86,10 +87,10 @@ std::future LocalBundleReader::LoadBundleAsync(const std::wstring b
reinterpret_cast(&script[0]), reinterpret_cast(&script[script.length()])});
dataReader.Close();
- co_return script;
+ co_return winrt::to_hstring(script);
}
-std::string LocalBundleReader::LoadBundle(const std::wstring &bundlePath) {
+winrt::hstring LocalBundleReader::LoadBundle(const std::wstring &bundlePath) {
return LoadBundleAsync(bundlePath).get();
}
@@ -113,7 +114,7 @@ size_t StorageFileBigString::size() const {
void StorageFileBigString::ensure() const {
if (m_string.empty()) {
- m_string = m_futureBuffer.get();
+ m_string = winrt::to_string(m_futureBuffer.get());
}
}
diff --git a/vnext/Microsoft.ReactNative/Utils/LocalBundleReader.h b/vnext/Microsoft.ReactNative/Utils/LocalBundleReader.h
index 8671ebf59ee..12c8bda970a 100644
--- a/vnext/Microsoft.ReactNative/Utils/LocalBundleReader.h
+++ b/vnext/Microsoft.ReactNative/Utils/LocalBundleReader.h
@@ -3,15 +3,15 @@
#pragma once
#include
-#include
+#include
#include
namespace Microsoft::ReactNative {
class LocalBundleReader {
public:
- static std::future LoadBundleAsync(const std::wstring bundlePath);
- static std::string LoadBundle(const std::wstring &bundlePath);
+ static winrt::Windows::Foundation::IAsyncOperation LoadBundleAsync(const std::wstring bundleUri);
+ static winrt::hstring LoadBundle(const std::wstring &bundlePath);
};
class StorageFileBigString : public facebook::react::JSBigString {
@@ -24,7 +24,7 @@ class StorageFileBigString : public facebook::react::JSBigString {
void ensure() const;
private:
- mutable std::future m_futureBuffer;
+ mutable winrt::Windows::Foundation::IAsyncOperation m_futureBuffer;
mutable std::string m_string;
};
diff --git a/vnext/Microsoft.ReactNative/Utils/UwpScriptStore.cpp b/vnext/Microsoft.ReactNative/Utils/UwpScriptStore.cpp
index 59bb0c805db..0130afcdfda 100644
--- a/vnext/Microsoft.ReactNative/Utils/UwpScriptStore.cpp
+++ b/vnext/Microsoft.ReactNative/Utils/UwpScriptStore.cpp
@@ -43,7 +43,8 @@ facebook::jsi::ScriptVersion_t UwpScriptStore::getScriptVersion(const std::strin
return version;
}
-std::future UwpScriptStore::getScriptVersionAsync(const std::string &bundleUri) {
+winrt::Windows::Foundation::IAsyncOperation UwpScriptStore::getScriptVersionAsync(
+ const std::string &bundleUri) {
co_await winrt::resume_background();
const winrt::hstring fileUrl(Microsoft::Common::Unicode::Utf8ToUtf16("ms-appx:///Bundle/" + bundleUri + ".bundle"));
diff --git a/vnext/Microsoft.ReactNative/Utils/UwpScriptStore.h b/vnext/Microsoft.ReactNative/Utils/UwpScriptStore.h
index 6b77db3f9e7..78b1ff112ae 100644
--- a/vnext/Microsoft.ReactNative/Utils/UwpScriptStore.h
+++ b/vnext/Microsoft.ReactNative/Utils/UwpScriptStore.h
@@ -1,6 +1,6 @@
#pragma once
#include
-#include
+#include
namespace Microsoft::ReactNative {
@@ -16,7 +16,8 @@ class UwpScriptStore : public facebook::jsi::ScriptStore {
static facebook::jsi::ScriptVersion_t GetFileVersion(const std::wstring &filePath);
private:
- std::future getScriptVersionAsync(const std::string &bundleUri);
+ winrt::Windows::Foundation::IAsyncOperation getScriptVersionAsync(
+ const std::string &bundleUri);
};
} // namespace Microsoft::ReactNative
diff --git a/vnext/Mso.UnitTests/Mso.UnitTests.vcxproj b/vnext/Mso.UnitTests/Mso.UnitTests.vcxproj
index 65e4c389605..bfda7bc3af2 100644
--- a/vnext/Mso.UnitTests/Mso.UnitTests.vcxproj
+++ b/vnext/Mso.UnitTests/Mso.UnitTests.vcxproj
@@ -62,7 +62,7 @@
$(IntDir)pch.pch
_CONSOLE;MS_TARGET_WINDOWS;MSO_MOTIFCPP;%(PreprocessorDefinitions)
Level4
- /await %(AdditionalOptions) /bigobj
+ %(AdditionalOptions) /bigobj
true
Cdecl
@@ -148,4 +148,4 @@
-
\ No newline at end of file
+
diff --git a/vnext/PropertySheets/React.Cpp.props b/vnext/PropertySheets/React.Cpp.props
index bc7739fe4f2..bf946633f95 100644
--- a/vnext/PropertySheets/React.Cpp.props
+++ b/vnext/PropertySheets/React.Cpp.props
@@ -152,4 +152,4 @@
-
\ No newline at end of file
+
diff --git a/vnext/Shared/DevSupportManager.cpp b/vnext/Shared/DevSupportManager.cpp
index a6935bb8aa9..53e54ed07d8 100644
--- a/vnext/Shared/DevSupportManager.cpp
+++ b/vnext/Shared/DevSupportManager.cpp
@@ -15,6 +15,7 @@
#include "Utilities.h"
#include
+#include
#include
#include
#include
@@ -30,7 +31,6 @@
#include
#pragma warning(pop)
-#include
#include
#include
@@ -44,7 +44,9 @@ using namespace facebook::react;
namespace Microsoft::ReactNative {
-std::future> GetJavaScriptFromServerAsync(const std::string &url) {
+winrt::Windows::Foundation::IAsyncOperation<
+ winrt::Windows::Foundation::Collections::IKeyValuePair>
+GetJavaScriptFromServerAsync(const std::string &url) {
winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter filter;
filter.CacheControl().ReadBehavior(winrt::Windows::Web::Http::Filters::HttpCacheReadBehavior::NoCache);
winrt::Windows::Web::Http::HttpClient httpClient(filter);
@@ -58,8 +60,9 @@ std::future> GetJavaScriptFromServerAsync(const std
try {
winrt::Windows::Web::Http::HttpResponseMessage response = co_await asyncRequest;
} catch (winrt::hresult_error const &e) {
- co_return std::make_pair(
- Microsoft::Common::Unicode::Utf16ToUtf8(e.message().c_str(), e.message().size()).c_str(), false);
+ co_return winrt::pair(
+ winrt::to_hstring(Microsoft::Common::Unicode::Utf16ToUtf8(e.message().c_str(), e.message().size()).c_str()),
+ false);
}
#else
co_await lessthrow_await_adapter> GetJavaScriptFromServerAsync(const std
} else {
error = fmt::format("Error 0x{:x} downloading {}.", static_cast(asyncRequest.ErrorCode()), url);
}
- co_return std::make_pair(error, false);
+ co_return winrt::pair(winrt::to_hstring(error), false);
}
winrt::Windows::Web::Http::HttpResponseMessage response = asyncRequest.GetResults();
@@ -98,7 +101,7 @@ std::future> GetJavaScriptFromServerAsync(const std
result = fmt::format("HTTP Error {} downloading {}.", static_cast(response.StatusCode()), url);
}
- co_return std::make_pair(std::move(result), response.IsSuccessStatusCode());
+ co_return winrt::pair(winrt::to_hstring(std::move(result)), response.IsSuccessStatusCode());
}
void LaunchDevTools(const facebook::react::DevSettings &settings) {
@@ -171,7 +174,8 @@ bool IsIgnorablePollHResult(HRESULT hr) {
return hr == WININET_E_INVALID_SERVER_RESPONSE;
}
-std::future PollForLiveReload(const std::string &url) {
+winrt::Windows::Foundation::IAsyncOperation PollForLiveReload(
+ const std::string url) {
winrt::Windows::Web::Http::HttpClient httpClient;
winrt::Windows::Foundation::Uri uri(Microsoft::Common::Unicode::Utf8ToUtf16(url));
httpClient.DefaultRequestHeaders().Connection().TryParseAdd(L"keep-alive");
@@ -290,7 +294,8 @@ std::pair GetJavaScriptFromServer(
inlineSourceMap,
hermesBytecodeVersion);
try {
- return GetJavaScriptFromServerAsync(bundleUrl).get();
+ auto result = GetJavaScriptFromServerAsync(bundleUrl).get();
+ return std::make_pair(winrt::to_string(result.Key()), result.Value());
} catch (winrt::hresult_error const &e) {
return std::make_pair(
"Error: " + Microsoft::Common::Unicode::Utf16ToUtf8(e.message().c_str(), e.message().size()), false);
diff --git a/vnext/Shared/DevSupportManager.h b/vnext/Shared/DevSupportManager.h
index 5c33ed1de02..ad95a39d9f3 100644
--- a/vnext/Shared/DevSupportManager.h
+++ b/vnext/Shared/DevSupportManager.h
@@ -7,6 +7,7 @@
#include
+#include
#include
#include
#include
@@ -22,6 +23,29 @@ struct DevSettings;
}
} // namespace facebook
+namespace winrt {
+
+template
+struct pair_impl : implements, Windows::Foundation::Collections::IKeyValuePair> {
+ pair_impl(K k, V v) : m_k(k), m_v(v) {}
+ K Key() {
+ return m_k;
+ }
+ V Value() {
+ return m_v;
+ }
+
+ private:
+ K m_k;
+ V m_v;
+};
+
+template
+Windows::Foundation::Collections::IKeyValuePair pair(K key, V value) {
+ return make>(key, value);
+}
+} // namespace winrt
+
namespace Microsoft::ReactNative {
std::pair GetJavaScriptFromServer(
diff --git a/vnext/Shared/HermesSamplingProfiler.cpp b/vnext/Shared/HermesSamplingProfiler.cpp
index 442dba36887..2c25e568ee2 100644
--- a/vnext/Shared/HermesSamplingProfiler.cpp
+++ b/vnext/Shared/HermesSamplingProfiler.cpp
@@ -5,7 +5,7 @@
#include
#include
-#include
+#include
#include "HermesRuntimeHolder.h"
#include "HermesSamplingProfiler.h"
@@ -32,10 +32,8 @@ auto resume_in_dispatcher(const IReactDispatcher &dispatcher) noexcept {
void await_resume() const noexcept {}
- void await_suspend(std::experimental::coroutine_handle<> resume) noexcept {
- callback_ = [context = resume.address()]() noexcept {
- std::experimental::coroutine_handle<>::from_address(context)();
- };
+ void await_suspend(std::coroutine_handle<> resume) noexcept {
+ callback_ = [context = resume.address()]() noexcept { std::coroutine_handle<>::from_address(context)(); };
dispatcher_.Post(std::move(callback_));
}
@@ -54,8 +52,7 @@ IAsyncOperation getTraceFilePath() noexcept {
.count();
os << hermesDataPath.c_str() << L"\\cpu_" << now << L".cpuprofile";
- // TODO: Use C++ 20 `os.view()` to avoid a copy
- co_return winrt::hstring(os.str());
+ co_return winrt::hstring(os.view());
}
} // namespace
diff --git a/vnext/Shared/Networking/WinRTWebSocketResource.cpp b/vnext/Shared/Networking/WinRTWebSocketResource.cpp
index aa227c00632..4b06f27b8f0 100644
--- a/vnext/Shared/Networking/WinRTWebSocketResource.cpp
+++ b/vnext/Shared/Networking/WinRTWebSocketResource.cpp
@@ -20,6 +20,7 @@
#include
// Standard Library
+#include
#include
using Microsoft::Common::Utilities::CheckedReinterpretCast;
@@ -67,10 +68,8 @@ auto resume_in_queue(const Mso::DispatchQueue &queue) noexcept {
void await_resume() const noexcept {}
- void await_suspend(std::experimental::coroutine_handle<> resume) noexcept {
- m_callback = [context = resume.address()]() noexcept {
- std::experimental::coroutine_handle<>::from_address(context)();
- };
+ void await_suspend(std::coroutine_handle<> resume) noexcept {
+ m_callback = [context = resume.address()]() noexcept { std::coroutine_handle<>::from_address(context)(); };
m_queue.Post(std::move(m_callback));
}
diff --git a/vnext/Shared/Utils/CppWinrtLessExceptions.h b/vnext/Shared/Utils/CppWinrtLessExceptions.h
index 9bd4b4fc323..83eddc1bc13 100644
--- a/vnext/Shared/Utils/CppWinrtLessExceptions.h
+++ b/vnext/Shared/Utils/CppWinrtLessExceptions.h
@@ -22,6 +22,7 @@
#define SHARED_UTILS_CPPWINRTLESSEXCEPTIONS_H_
#include
+#include
// #define DEFAULT_CPPWINRT_EXCEPTIONS
#ifndef DEFAULT_CPPWINRT_EXCEPTIONS
@@ -35,7 +36,7 @@ struct lessthrow_await_adapter {
return async.Status() == winrt::Windows::Foundation::AsyncStatus::Completed;
}
- void await_suspend(std::experimental::coroutine_handle<> handle) const {
+ void await_suspend(std::coroutine_handle<> handle) const {
auto context = winrt::capture(WINRT_IMPL_CoGetObjectContext);
async.Completed([handle, context = std::move(context)](auto const &, winrt::Windows::Foundation::AsyncStatus) {
@@ -43,7 +44,7 @@ struct lessthrow_await_adapter {
args.data = handle.address();
auto callback = [](winrt::impl::com_callback_args *args) noexcept -> int32_t {
- std::experimental::coroutine_handle<>::from_address(args->data)();
+ std::coroutine_handle<>::from_address(args->data)();
return S_OK;
};