react-native-windows 0.83.0 → 0.83.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/Common/unicode.cpp +36 -0
  2. package/Common/unicode.h +8 -0
  3. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +6 -4
  4. package/Microsoft.ReactNative/Fabric/Composition/TextDrawing.cpp +1 -1
  5. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/WindowsTextLayoutManager.cpp +1 -1
  6. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +3 -2
  7. package/Microsoft.ReactNative/ReactNativeAppBuilder.idl +3 -0
  8. package/Microsoft.ReactNative/Utils/LocalBundleReader.cpp +33 -25
  9. package/Microsoft.ReactNative/Utils/LocalBundleReader.h +5 -3
  10. package/Microsoft.ReactNative/Utils/UwpScriptStore.cpp +2 -2
  11. package/Microsoft.ReactNative/Utils/UwpScriptStore.h +3 -2
  12. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +16 -0
  13. package/Microsoft.ReactNative.Managed/Microsoft.ReactNative.Managed.csproj +3 -3
  14. package/Microsoft.ReactNative.Managed.CodeGen/Microsoft.ReactNative.Managed.CodeGen.csproj +10 -10
  15. package/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Debug.pubxml +1 -1
  16. package/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Release.pubxml +1 -1
  17. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  18. package/PropertySheets/React.Cpp.props +4 -3
  19. package/PropertySheets/WinUI.props +2 -2
  20. package/Scripts/JustMyXaml.ps1 +8 -8
  21. package/Scripts/UnitTest.ps1 +3 -1
  22. package/Scripts/creaternwapp.cmd +12 -2
  23. package/Scripts/creaternwlib.cmd +12 -2
  24. package/Scripts/rnw-dependencies.ps1 +15 -16
  25. package/Shared/DevSupportManager.cpp +55 -48
  26. package/Shared/DevSupportManager.h +0 -1
  27. package/Shared/Modules/IWebSocketModuleContentHandler.h +15 -0
  28. package/Shared/Modules/WebSocketModule.cpp +8 -3
  29. package/Shared/Networking/DefaultBlobResource.cpp +37 -0
  30. package/Shared/Networking/DefaultBlobResource.h +12 -0
  31. package/Shared/Networking/WinRTWebSocketResource.h +5 -1
  32. package/just-task.js +13 -2
  33. package/package.json +5 -5
  34. package/templates/cpp-app/windows/MyApp/MyApp.vcxproj +1 -1
  35. package/templates/cpp-lib/windows/MyLib/MyLib.vcxproj +1 -1
@@ -93,6 +93,42 @@ std::wstring Utf8ToUtf16(const std::string &utf8) {
93
93
  return Utf8ToUtf16(utf8.c_str(), utf8.length());
94
94
  }
95
95
 
96
+ size_t Utf8ToUtf16Length(const char *utf8, size_t utf8Len) {
97
+ if (utf8Len == 0) {
98
+ return 0;
99
+ }
100
+
101
+ if (utf8Len > static_cast<size_t>((std::numeric_limits<int>::max)())) {
102
+ throw std::overflow_error("Length of input string to Utf8ToUtf16Length() must fit into an int.");
103
+ }
104
+
105
+ const int utf8Length = static_cast<int>(utf8Len);
106
+
107
+ constexpr DWORD flags = 0;
108
+
109
+ const int utf16Length = ::MultiByteToWideChar(
110
+ CP_UTF8, // Source string is in UTF-8.
111
+ flags, // Conversion flags.
112
+ utf8, // Source UTF-8 string pointer.
113
+ utf8Length, // Length of the source UTF-8 string, in chars.
114
+ nullptr, // Do not convert, just request the size.
115
+ 0 // Request size of destination buffer, in wchar_ts.
116
+ );
117
+
118
+ if (utf16Length == 0) {
119
+ throw UnicodeConversionException(
120
+ "Cannot get result string length when converting from UTF-8 to UTF-16 "
121
+ "(MultiByteToWideChar failed).",
122
+ GetLastError());
123
+ }
124
+
125
+ return static_cast<size_t>(utf16Length);
126
+ }
127
+
128
+ size_t Utf8ToUtf16Length(const std::string &utf8) {
129
+ return Utf8ToUtf16Length(utf8.c_str(), utf8.length());
130
+ }
131
+
96
132
  #if _HAS_CXX17
97
133
  std::wstring Utf8ToUtf16(const std::string_view &utf8) {
98
134
  return Utf8ToUtf16(utf8.data(), utf8.length());
package/Common/unicode.h CHANGED
@@ -55,6 +55,14 @@ class UnicodeConversionException : public std::runtime_error {
55
55
  /* (4) */ std::wstring Utf8ToUtf16(const std::string_view &utf8);
56
56
  #endif
57
57
 
58
+ // The following functions return the length of the UTF-16 string that would
59
+ // result from converting the input UTF-8 string, without actually performing
60
+ // the conversion or allocating a temporary std::wstring. This is useful in
61
+ // hot paths where only the length is needed (e.g. DirectWrite text ranges).
62
+ //
63
+ size_t Utf8ToUtf16Length(const char *utf8, size_t utf8Len);
64
+ size_t Utf8ToUtf16Length(const std::string &utf8);
65
+
58
66
  // The following functions convert UTF-16BE strings to UTF-8 strings. Their
59
67
  // behaviors mirror those of the above Utf8ToUtf16 functions.
60
68
  //
@@ -153,11 +153,12 @@ facebook::react::SharedViewEventEmitter ParagraphComponentView::eventEmitterAtPo
153
153
  uint32_t textPosition = metrics.textPosition;
154
154
 
155
155
  for (auto fragment : m_attributedStringBox.getValue().getFragments()) {
156
- if (textPosition < fragment.string.length()) {
156
+ uint32_t utf16Length = static_cast<uint32_t>(::Microsoft::Common::Unicode::Utf8ToUtf16Length(fragment.string));
157
+ if (textPosition < utf16Length) {
157
158
  return std::static_pointer_cast<const facebook::react::ViewEventEmitter>(
158
159
  fragment.parentShadowView.eventEmitter);
159
160
  }
160
- textPosition -= static_cast<uint32_t>(fragment.string.length());
161
+ textPosition -= utf16Length;
161
162
  }
162
163
  }
163
164
  }
@@ -210,10 +211,11 @@ bool ParagraphComponentView::IsTextSelectableAtPoint(facebook::react::Point pt)
210
211
 
211
212
  // Finds which fragment contains this text position
212
213
  for (auto fragment : m_attributedStringBox.getValue().getFragments()) {
213
- if (textPosition < fragment.string.length()) {
214
+ uint32_t utf16Length = static_cast<uint32_t>(::Microsoft::Common::Unicode::Utf8ToUtf16Length(fragment.string));
215
+ if (textPosition < utf16Length) {
214
216
  return true;
215
217
  }
216
- textPosition -= static_cast<uint32_t>(fragment.string.length());
218
+ textPosition -= utf16Length;
217
219
  }
218
220
  }
219
221
  }
@@ -66,7 +66,7 @@ void RenderText(
66
66
  unsigned int position = 0;
67
67
  unsigned int length = 0;
68
68
  for (auto fragment : attributedString.getFragments()) {
69
- length = static_cast<UINT32>(fragment.string.length());
69
+ length = static_cast<UINT32>(::Microsoft::Common::Unicode::Utf8ToUtf16Length(fragment.string));
70
70
  DWRITE_TEXT_RANGE range = {position, length};
71
71
  if (fragment.textAttributes.foregroundColor &&
72
72
  (fragment.textAttributes.foregroundColor != textAttributes.foregroundColor) ||
@@ -267,7 +267,7 @@ void WindowsTextLayoutManager::GetTextLayout(
267
267
  attachments.push_back(attachment);
268
268
  position += 1;
269
269
  } else {
270
- unsigned int length = static_cast<UINT32>(fragment.string.length());
270
+ unsigned int length = static_cast<UINT32>(Microsoft::Common::Unicode::Utf8ToUtf16Length(fragment.string));
271
271
  DWRITE_TEXT_RANGE range = {position, length};
272
272
  TextAttributes attributes = fragment.textAttributes;
273
273
  DWRITE_FONT_STYLE fragmentStyle = DWRITE_FONT_STYLE_NORMAL;
@@ -10,7 +10,7 @@
10
10
  <ProjectName>Microsoft.ReactNative</ProjectName>
11
11
  <RootNamespace>Microsoft.ReactNative</RootNamespace>
12
12
  <DefaultLanguage>en-US</DefaultLanguage>
13
- <MinimumVisualStudioVersion>17.0</MinimumVisualStudioVersion>
13
+ <MinimumVisualStudioVersion>18.0</MinimumVisualStudioVersion>
14
14
  <AppContainerApplication>true</AppContainerApplication>
15
15
  <ApplicationType>Windows Store</ApplicationType>
16
16
  <ApplicationTypeRevision>10.0</ApplicationTypeRevision>
@@ -96,7 +96,8 @@
96
96
  <PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
97
97
  <ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
98
98
  <WarningLevel>Level4</WarningLevel>
99
- <AdditionalOptions>/await %(AdditionalOptions) /bigobj /ZH:SHA_256</AdditionalOptions>
99
+ <AdditionalOptions>%(AdditionalOptions) /bigobj /ZH:SHA_256</AdditionalOptions>
100
+ <AdditionalOptions Condition="$(PlatformToolsetVersion)&lt;145">%(AdditionalOptions) /await</AdditionalOptions>
100
101
  <AdditionalIncludeDirectories>
101
102
  $(FmtDir)\include;
102
103
  $(ReactNativeWindowsDir)Microsoft.ReactNative;
@@ -3,6 +3,7 @@ import "ReactNativeHost.idl";
3
3
  import "ReactNativeIsland.idl";
4
4
  import "ReactInstanceSettings.idl";
5
5
  import "IReactPackageProvider.idl";
6
+ import "ReactNativeWindow.idl";
6
7
 
7
8
  #include "DocString.h"
8
9
 
@@ -14,6 +15,8 @@ namespace Microsoft.ReactNative {
14
15
  // Properties
15
16
  Microsoft.UI.Windowing.AppWindow AppWindow {get;};
16
17
 
18
+ ReactNativeWindow ReactNativeWindow {get;};
19
+
17
20
  ReactNativeHost ReactNativeHost {get;};
18
21
 
19
22
  ReactViewOptions ReactViewOptions {get;};
@@ -54,7 +54,29 @@ std::string GetBundleFromEmbeddedResource(const winrt::Windows::Foundation::Uri
54
54
  return std::string(start, start + size);
55
55
  }
56
56
 
57
- std::future<std::string> LocalBundleReader::LoadBundleAsync(const std::wstring bundleUri) {
57
+ namespace {
58
+
59
+ std::string BufferToString(const winrt::Windows::Storage::Streams::IBuffer &buffer) {
60
+ std::string result(buffer.Length(), '\0');
61
+ if (!result.empty()) {
62
+ auto reader = winrt::Windows::Storage::Streams::DataReader::FromBuffer(buffer);
63
+ reader.ReadBytes(winrt::array_view<uint8_t>{
64
+ reinterpret_cast<uint8_t *>(&result[0]), reinterpret_cast<uint8_t *>(&result[result.length()])});
65
+ }
66
+ return result;
67
+ }
68
+
69
+ winrt::Windows::Storage::Streams::IBuffer BytesToBuffer(const void *data, uint32_t size) {
70
+ winrt::Windows::Storage::Streams::DataWriter writer;
71
+ auto bytes = static_cast<const uint8_t *>(data);
72
+ writer.WriteBytes(winrt::array_view<const uint8_t>(bytes, bytes + size));
73
+ return writer.DetachBuffer();
74
+ }
75
+
76
+ } // namespace
77
+
78
+ winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::Streams::IBuffer>
79
+ LocalBundleReader::LoadBundleAsync(const std::wstring bundleUri) {
58
80
  try {
59
81
  co_await winrt::resume_background();
60
82
 
@@ -66,41 +88,26 @@ std::future<std::string> LocalBundleReader::LoadBundleAsync(const std::wstring b
66
88
  file = co_await winrt::Windows::Storage::StorageFile::GetFileFromApplicationUriAsync(uri);
67
89
  } else if (bundleUri.starts_with(L"resource://")) {
68
90
  winrt::Windows::Foundation::Uri uri(bundleUri);
69
- co_return GetBundleFromEmbeddedResource(uri);
91
+ auto bytes = GetBundleFromEmbeddedResource(uri);
92
+ co_return BytesToBuffer(bytes.data(), static_cast<uint32_t>(bytes.size()));
70
93
  } else {
71
94
  file = co_await winrt::Windows::Storage::StorageFile::GetFileFromPathAsync(bundleUri);
72
95
  }
73
96
 
74
- // Read the buffer manually to avoid a Utf8 -> Utf16 -> Utf8 encoding
75
- // roundtrip.
76
- auto fileBuffer{co_await winrt::Windows::Storage::FileIO::ReadBufferAsync(file)};
77
- auto dataReader{winrt::Windows::Storage::Streams::DataReader::FromBuffer(fileBuffer)};
78
-
79
- // No need to use length + 1, STL guarantees that string storage is null-terminated.
80
- std::string script(fileBuffer.Length(), '\0');
81
-
82
- // Construct the array_view to slice into the first fileBuffer.Length bytes.
83
- // DataReader.ReadBytes will read as many bytes as are present in the
84
- // array_view. The backing string has fileBuffer.Length() + 1 bytes, without
85
- // an explicit end it will read 1 byte to many and throw.
86
- dataReader.ReadBytes(winrt::array_view<uint8_t>{
87
- reinterpret_cast<uint8_t *>(&script[0]), reinterpret_cast<uint8_t *>(&script[script.length()])});
88
- dataReader.Close();
89
-
90
- co_return script;
97
+ co_return co_await winrt::Windows::Storage::FileIO::ReadBufferAsync(file);
91
98
  }
92
99
  // RuntimeScheduler only handles std::exception or jsi::JSError
93
- catch (winrt::hresult_error const &e) {
94
- throw std::exception(winrt::to_string(e.message()).c_str());
100
+ catch (winrt::hresult_error const &) {
101
+ throw;
95
102
  }
96
103
  }
97
104
 
98
105
  std::string LocalBundleReader::LoadBundle(const std::wstring &bundlePath) {
99
- return LoadBundleAsync(bundlePath).get();
106
+ return BufferToString(LoadBundleAsync(bundlePath).get());
100
107
  }
101
108
 
102
109
  StorageFileBigString::StorageFileBigString(const std::wstring &path) {
103
- m_futureBuffer = LocalBundleReader::LoadBundleAsync(path);
110
+ m_pendingLoad = LocalBundleReader::LoadBundleAsync(path);
104
111
  }
105
112
 
106
113
  bool StorageFileBigString::isAscii() const {
@@ -118,8 +125,9 @@ size_t StorageFileBigString::size() const {
118
125
  }
119
126
 
120
127
  void StorageFileBigString::ensure() const {
121
- if (m_string.empty()) {
122
- m_string = m_futureBuffer.get();
128
+ if (m_pendingLoad) {
129
+ m_string = BufferToString(m_pendingLoad.get());
130
+ m_pendingLoad = nullptr;
123
131
  }
124
132
  }
125
133
 
@@ -3,14 +3,16 @@
3
3
 
4
4
  #pragma once
5
5
  #include <cxxreact/JSBigString.h>
6
- #include <future>
6
+ #include <winrt/Windows.Foundation.h>
7
+ #include <winrt/Windows.Storage.Streams.h>
7
8
  #include <string>
8
9
 
9
10
  namespace Microsoft::ReactNative {
10
11
 
11
12
  class LocalBundleReader {
12
13
  public:
13
- static std::future<std::string> LoadBundleAsync(const std::wstring bundlePath);
14
+ static winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::Streams::IBuffer> LoadBundleAsync(
15
+ const std::wstring bundlePath);
14
16
  static std::string LoadBundle(const std::wstring &bundlePath);
15
17
  };
16
18
 
@@ -24,7 +26,7 @@ class StorageFileBigString : public facebook::react::JSBigString {
24
26
  void ensure() const;
25
27
 
26
28
  private:
27
- mutable std::future<std::string> m_futureBuffer;
29
+ mutable winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::Streams::IBuffer> m_pendingLoad;
28
30
  mutable std::string m_string;
29
31
  };
30
32
 
@@ -4,7 +4,6 @@
4
4
  #include <winrt/Windows.Foundation.h>
5
5
  #include <winrt/Windows.Storage.FileProperties.h>
6
6
  #include <winrt/Windows.Storage.h>
7
- #include <future>
8
7
  #include "Unicode.h"
9
8
 
10
9
  namespace winrt {
@@ -43,7 +42,8 @@ facebook::jsi::ScriptVersion_t UwpScriptStore::getScriptVersion(const std::strin
43
42
  return version;
44
43
  }
45
44
 
46
- std::future<facebook::jsi::ScriptVersion_t> UwpScriptStore::getScriptVersionAsync(const std::string &bundleUri) {
45
+ winrt::Windows::Foundation::IAsyncOperation<facebook::jsi::ScriptVersion_t> UwpScriptStore::getScriptVersionAsync(
46
+ const std::string &bundleUri) {
47
47
  co_await winrt::resume_background();
48
48
 
49
49
  const winrt::hstring fileUrl(Microsoft::Common::Unicode::Utf8ToUtf16("ms-appx:///Bundle/" + bundleUri + ".bundle"));
@@ -1,6 +1,6 @@
1
1
  #pragma once
2
2
  #include <JSI/ScriptStore.h>
3
- #include <future>
3
+ #include <winrt/Windows.Foundation.h>
4
4
 
5
5
  namespace Microsoft::ReactNative {
6
6
 
@@ -16,7 +16,8 @@ class UwpScriptStore : public facebook::jsi::ScriptStore {
16
16
  static facebook::jsi::ScriptVersion_t GetFileVersion(const std::wstring &filePath);
17
17
 
18
18
  private:
19
- std::future<facebook::jsi::ScriptVersion_t> getScriptVersionAsync(const std::string &bundleUri);
19
+ winrt::Windows::Foundation::IAsyncOperation<facebook::jsi::ScriptVersion_t> getScriptVersionAsync(
20
+ const std::string &bundleUri);
20
21
  };
21
22
 
22
23
  } // namespace Microsoft::ReactNative
@@ -158,6 +158,22 @@
158
158
  </ClCompile>
159
159
  <ClCompile Include="$(NodeApiJsiSrcDir)NodeApiJsiRuntime.cpp">
160
160
  <PrecompiledHeader>NotUsing</PrecompiledHeader>
161
+ <!--
162
+ Workaround for a Visual Studio 2026 (v145) C++ optimizer bug. With
163
+ optimizations on, this translation unit is miscompiled such that the
164
+ pointer-value-scope teardown in NodeApiJsiRuntime hands Hermes a stale
165
+ napi_value, crashing in hermes!JSProxy::defineOwnProperty (via
166
+ napi_create_reference) during rapid UI updates - e.g. the
167
+ e2e-test-app-fabric visitAllPages test. Building this file without
168
+ optimization (verified equivalent to `#pragma optimize("", off)`)
169
+ avoids it. We must also opt out of /GL here so the disabled
170
+ optimization survives link-time code generation. NodeApiJsiRuntime.cpp
171
+ is externally provided, so the workaround lives here rather than in the
172
+ source. Scoped to v145+ (the bug does not reproduce on v143); remove
173
+ when the compiler bug is fixed.
174
+ -->
175
+ <Optimization Condition="$(PlatformToolsetVersion)&gt;=145">Disabled</Optimization>
176
+ <WholeProgramOptimization Condition="$(PlatformToolsetVersion)&gt;=145">false</WholeProgramOptimization>
161
177
  </ClCompile>
162
178
  </ItemGroup>
163
179
  <ItemGroup Condition="'$(BuildMSRNCxxNodeApiJsiLoader)' != 'false'">
@@ -15,7 +15,7 @@
15
15
  <TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
16
16
  <TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.22621.0</TargetPlatformVersion>
17
17
  <TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
18
- <MinimumVisualStudioVersion>17.0</MinimumVisualStudioVersion>
18
+ <MinimumVisualStudioVersion>18.0</MinimumVisualStudioVersion>
19
19
  <FileAlignment>512</FileAlignment>
20
20
  <ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
21
21
  <DocumentationFile>bin\$(Platform)\$(Configuration)\Microsoft.ReactNative.Managed.XML</DocumentationFile>
@@ -150,8 +150,8 @@
150
150
  </ItemGroup>
151
151
  </When>
152
152
  </Choose>
153
- <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '17.0' ">
154
- <VisualStudioVersion>17.0</VisualStudioVersion>
153
+ <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '18.0' ">
154
+ <VisualStudioVersion>18.0</VisualStudioVersion>
155
155
  </PropertyGroup>
156
156
  <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
157
157
  <Target Name="Deploy" />
@@ -3,7 +3,7 @@
3
3
  <PropertyGroup>
4
4
  <OutputType>Exe</OutputType>
5
5
 
6
- <TargetFramework>net8.0</TargetFramework>
6
+ <TargetFramework>net10.0</TargetFramework>
7
7
  <Platforms>x64;x86;ARM64</Platforms>
8
8
  <RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
9
9
 
@@ -31,8 +31,8 @@
31
31
  <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.3.1" />
32
32
  <PackageReference Include="RuntimeContracts" Version="0.3.0" />
33
33
 
34
- <!--
35
- NuGet decides to pull in packages with issues. There is no seeming way to diagnose why NuGet is pulling in those versions.
34
+ <!--
35
+ NuGet decides to pull in packages with issues. There is no seeming way to diagnose why NuGet is pulling in those versions.
36
36
  Running restore with -Verbosity Detailed and environment variables:
37
37
  * NUGET_RESTORE_MSBUILD_ARGS=/bl:c:\temp\nuget.binlog
38
38
  * NUGET_RESTORE_MSBUILD_VERBOSITY=diag
@@ -42,7 +42,7 @@
42
42
  <PackageReference Include="System.Private.Uri" Version="4.3.2" />
43
43
  </ItemGroup>
44
44
 
45
- <!--
45
+ <!--
46
46
  This target is used to ensure the tool is deployed and can be used from source.
47
47
  It will return all deployed files so the caller can implement incrementality properly
48
48
  -->
@@ -53,7 +53,7 @@
53
53
  </ItemGroup>
54
54
  </Target>
55
55
 
56
- <!--
56
+ <!--
57
57
  This target returns the location of the deployed executable.
58
58
  -->
59
59
  <Target Name="GetPublishedToolPath" DependsOnTargets="PublishTool" Returns="@(_PublishedToolExecutable)">
@@ -62,13 +62,13 @@
62
62
  </ItemGroup>
63
63
  </Target>
64
64
 
65
- <!--
65
+ <!--
66
66
  This is used during the PR build to ensure we have the artifacts published during the build.
67
67
  -->
68
- <Target
69
- Name="PublishToolDuringBuild"
70
- DependsOnTargets="Publish"
71
- AfterTargets="Build"
68
+ <Target
69
+ Name="PublishToolDuringBuild"
70
+ DependsOnTargets="Publish"
71
+ AfterTargets="Build"
72
72
  Condition="'$(PublishToolDuringBuild)' == 'true'">
73
73
  </Target>
74
74
 
@@ -6,7 +6,7 @@
6
6
  <PublishProtocol>FileSystem</PublishProtocol>
7
7
  <Configuration>Debug</Configuration>
8
8
  <Platform>x64</Platform>
9
- <TargetFramework>net8.0</TargetFramework>
9
+ <TargetFramework>net10.0</TargetFramework>
10
10
  <PublishDir>$(OutDir)publish</PublishDir>
11
11
  <RuntimeIdentifier>win-x64</RuntimeIdentifier>
12
12
  <SelfContained>true</SelfContained>
@@ -6,7 +6,7 @@
6
6
  <PublishProtocol>FileSystem</PublishProtocol>
7
7
  <Configuration>Release</Configuration>
8
8
  <Platform>x64</Platform>
9
- <TargetFramework>net8.0</TargetFramework>
9
+ <TargetFramework>net10.0</TargetFramework>
10
10
  <PublishDir>$(OutDir)publish</PublishDir>
11
11
  <RuntimeIdentifier>win-x64</RuntimeIdentifier>
12
12
  <SelfContained>true</SelfContained>
@@ -10,11 +10,11 @@
10
10
  -->
11
11
  <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
12
12
  <PropertyGroup>
13
- <ReactNativeWindowsVersion>0.83.0</ReactNativeWindowsVersion>
13
+ <ReactNativeWindowsVersion>0.83.2</ReactNativeWindowsVersion>
14
14
  <ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
15
15
  <ReactNativeWindowsMinor>83</ReactNativeWindowsMinor>
16
- <ReactNativeWindowsPatch>0</ReactNativeWindowsPatch>
16
+ <ReactNativeWindowsPatch>2</ReactNativeWindowsPatch>
17
17
  <ReactNativeWindowsCanary>false</ReactNativeWindowsCanary>
18
- <ReactNativeWindowsCommitId>0fc74b3bd7d368b133e5633b387a79b4df844a96</ReactNativeWindowsCommitId>
18
+ <ReactNativeWindowsCommitId>83f78a8cf0b1226d7a9b78a1b18538e91cfd82c2</ReactNativeWindowsCommitId>
19
19
  </PropertyGroup>
20
20
  </Project>
@@ -43,8 +43,8 @@
43
43
 
44
44
  <PropertyGroup Label="ExternalDependencies">
45
45
  <!-- Google Test Adapter -->
46
- <!-- Property sheets in the adapter's NuGet doesn't consider PlatformToolset=v143 -->
47
- <Force-Enable-Microsoft-googletest-v140-windesktop-msvcstl-static-rt-dyn>false</Force-Enable-Microsoft-googletest-v140-windesktop-msvcstl-static-rt-dyn>
46
+ <!-- If ApplicationType is set, adapter include paths won't be set for MSVC 14.0 (v140) or later -->
47
+ <Force-Enable-Microsoft-googletest-v140-windesktop-msvcstl-static-rt-dyn>true</Force-Enable-Microsoft-googletest-v140-windesktop-msvcstl-static-rt-dyn>
48
48
  </PropertyGroup>
49
49
 
50
50
  <!--
@@ -136,7 +136,8 @@
136
136
  <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
137
137
  <RuntimeTypeInfo>true</RuntimeTypeInfo>
138
138
  <ShowIncludes Condition="'$(ShowIncludes)'=='true'">true</ShowIncludes>
139
- <AdditionalOptions>/utf-8 %(AdditionalOptions) /await</AdditionalOptions>
139
+ <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
140
+ <AdditionalOptions Condition="$(PlatformToolsetVersion)&lt;145">%(AdditionalOptions) /await</AdditionalOptions>
140
141
  <ControlFlowGuard>Guard</ControlFlowGuard>
141
142
  <SpectreMitigation>Spectre</SpectreMitigation>
142
143
 
@@ -2,7 +2,7 @@
2
2
  <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3
3
  <PropertyGroup Label="WinUI3 versioning">
4
4
 
5
- <!--
5
+ <!--
6
6
  Internal versions are typically only located at: https://microsoft.visualstudio.com/DefaultCollection/ProjectReunion/_artifacts/feed/Project.Reunion.nuget.internal/NuGet/Microsoft.WindowsAppSDK/versions
7
7
  For local testing of internal versions, modify WinUI3ExperimentalVersion, and comment out the additional nuget source in NuGet.Config
8
8
  When this version is updated, be sure to update the default for the enableInternalFeed parameter of /.ado/templates/enable-experimental-winui3.yml
@@ -10,7 +10,7 @@
10
10
  <WinUI3ExperimentalVersion Condition="'$(WinUI3ExperimentalVersion)'==''">2.0.0-experimental3</WinUI3ExperimentalVersion>
11
11
  <!-- This value is also used by the CLI, see /packages/@react-native-windows/cli/.../autolinkWindows.ts -->
12
12
  <WinUI3Version Condition="'$(WinUI3Version)'=='' AND '$(UseExperimentalWinUI3)'=='true'">$(WinUI3ExperimentalVersion)</WinUI3Version>
13
- <WinUI3Version Condition="'$(WinUI3Version)'==''">1.8.260209005</WinUI3Version>
13
+ <WinUI3Version Condition="'$(WinUI3Version)'==''">1.8.260508005</WinUI3Version>
14
14
  <!-- This is needed to prevent build errors with WinAppSDK >= 1.7 trying to double build WindowsAppRuntimeAutoInitializer.cpp -->
15
15
  <WindowsAppSdkAutoInitialize Condition="'$(WindowsAppSdkAutoInitialize)'=='' And $([MSBuild]::VersionGreaterThan('$(WinUI3Version)', '1.7.0'))">false</WindowsAppSdkAutoInitialize>
16
16
  </PropertyGroup>
@@ -1,4 +1,4 @@
1
- # This script enables or disables VS 2022's JustMyXaml feature
1
+ # This script enables or disables VS 2026's JustMyXaml feature
2
2
  [CmdletBinding()]
3
3
  param([bool]$Enable)
4
4
 
@@ -7,14 +7,14 @@ if (!([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups
7
7
  }
8
8
 
9
9
  $instanceId = & "$(${env:ProgramFiles(x86)})\Microsoft Visual Studio\Installer\vswhere.exe" -property instanceId
10
- $hiveFile = "$($env:LocalAppData)\Microsoft\VisualStudio\17.0_$instanceId\privateregistry.bin"
11
- & reg.exe load HKLM\VS2022_HIVE $hiveFile | Out-Null
12
- New-PSDrive -Name VS2022 -PSProvider Registry -Root HKLM\VS2022_HIVE -ErrorAction Stop | Out-Null
13
- $currentValue = (Get-ItemProperty VS2022:\Software\Microsoft\VisualStudio\17.0_$instanceId\Debugger -Name EnableXamlVisualDiagnosticsJustMyXaml).EnableXamlVisualDiagnosticsJustMyXaml
10
+ $hiveFile = "$($env:LocalAppData)\Microsoft\VisualStudio\18.0_$instanceId\privateregistry.bin"
11
+ & reg.exe load HKLM\VS2026_HIVE $hiveFile | Out-Null
12
+ New-PSDrive -Name VS2026 -PSProvider Registry -Root HKLM\VS2026_HIVE -ErrorAction Stop | Out-Null
13
+ $currentValue = (Get-ItemProperty VS2026:\Software\Microsoft\VisualStudio\18.0_$instanceId\Debugger -Name EnableXamlVisualDiagnosticsJustMyXaml).EnableXamlVisualDiagnosticsJustMyXaml
14
14
  if ($currentValue -eq 0) { $currentValue = $false; } else { $currentValue = $true; }
15
15
  Write-Host "Current value: $currentValue"
16
16
  if ($Enable) { $newValue = 1; } else { $newValue = 0; }
17
- Set-ItemProperty VS2022:\Software\Microsoft\VisualStudio\17.0_$instanceId\Debugger -Name EnableXamlVisualDiagnosticsJustMyXaml -Value $newValue -Type DWord
17
+ Set-ItemProperty VS2026:\Software\Microsoft\VisualStudio\18.0_$instanceId\Debugger -Name EnableXamlVisualDiagnosticsJustMyXaml -Value $newValue -Type DWord
18
18
  Write-Host "New value: $Enable"
19
- Remove-PSDrive -Name VS2022
20
- & reg.exe unload HKLM\VS2022_HIVE | Out-Null
19
+ Remove-PSDrive -Name VS2026
20
+ & reg.exe unload HKLM\VS2026_HIVE | Out-Null
@@ -23,7 +23,9 @@ param (
23
23
  "ReactCommon.UnitTests\ReactCommon.UnitTests.exe")
24
24
  ),
25
25
 
26
- [System.IO.FileInfo] $VsTest = "${env:ProgramFiles}\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe"
26
+ [System.IO.FileInfo] $VsTest =
27
+ "$(& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath)\" +
28
+ "Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe"
27
29
  )
28
30
 
29
31
  if ($Include.Count) {
@@ -103,7 +103,7 @@ if "%R_VERSION%"=="" (
103
103
  for /f "delims=" %%a in ('npm show react-native-windows@%RNW_VERSION% devDependencies.react') do @set R_VERSION=%%a
104
104
  )
105
105
 
106
- @echo creaternwapp.cmd Determining concrete versions for react@%R_VERSION%, react-native@%RN_VERSION%, @react-native-community/cli@%RNCLI_VERSION%, and react-native-windows@%RNW_VERSION%
106
+ @echo creaternwapp.cmd Determining concrete versions for react@%R_VERSION%, react-native@%RN_VERSION%, @react-native-community/cli@%RNCLI_VERSION%, and react-native-windows@%RNW_VERSION%
107
107
  for /f "delims=" %%a in ('npm show react-native-windows@%RNW_VERSION% version') do @set RNW_VERSION=%%a
108
108
  for /f "delims=" %%a in ('npm show react-native@%RN_VERSION% version') do @set RN_VERSION=%%a
109
109
  for /f "delims=" %%a in ('npm show @react-native-community/cli@%RNCLI_VERSION% version') do @set RNCLI_VERSION=%%a
@@ -178,10 +178,20 @@ call git commit -m "add rnw dependency"
178
178
  @echo creaternwapp.cmd Running init-windows with: npx --yes @react-native-community/cli@%RNCLI_VERSION% init-windows --template %RNW_TEMPLATE_TYPE% --overwrite --logging
179
179
  call npx --yes @react-native-community/cli@%RNCLI_VERSION% init-windows --template %RNW_TEMPLATE_TYPE% --overwrite --logging
180
180
 
181
+ if %ERRORLEVEL% neq 0 (
182
+ @echo creaternwapp.cmd init-windows command not available from react-native CLI, falling back to react-native-windows-init
183
+ call npx --yes react-native-windows-init@%RNW_VERSION% --template %RNW_TEMPLATE_TYPE% --overwrite --logging
184
+ )
185
+
186
+ if %ERRORLEVEL% neq 0 (
187
+ @echo creaternwapp.cmd: Unable to initialize Windows project
188
+ exit /b %ERRORLEVEL%
189
+ )
190
+
181
191
  @echo creaternwapp.cmd Done, see new %RNW_TEMPLATE_TYPE% project in %CD% with react@%R_VERSION%, react-native@%RN_VERSION%, and react-native-windows@%RNW_VERSION%
182
192
 
183
193
  popd
184
194
 
185
195
  endlocal
186
196
 
187
- exit /b %ERRORLEVEL%
197
+ exit /b %ERRORLEVEL%
@@ -108,7 +108,7 @@ if "%R_VERSION%"=="" (
108
108
  for /f "delims=" %%a in ('npm show react-native-windows@%RNW_VERSION% devDependencies.react') do @set R_VERSION=%%a
109
109
  )
110
110
 
111
- @echo creaternwlib.cmd Determining concrete versions for react@%R_VERSION%, react-native@%RN_VERSION%, and react-native-windows@%RNW_VERSION%
111
+ @echo creaternwlib.cmd Determining concrete versions for react@%R_VERSION%, react-native@%RN_VERSION%, and react-native-windows@%RNW_VERSION%
112
112
  for /f "delims=" %%a in ('npm show react-native-windows@%RNW_VERSION% version') do @set RNW_VERSION=%%a
113
113
  for /f "delims=" %%a in ('npm show react-native@%RN_VERSION% version') do @set RN_VERSION=%%a
114
114
  for /f "delims=" %%a in ('npm show @react-native-community/cli@%RNCLI_VERSION% version') do @set RNCLI_VERSION=%%a
@@ -167,10 +167,20 @@ call git commit -m "chore: add rnw dependency"
167
167
  @echo creaternwlib.cmd Running init-windows with: yarn react-native init-windows --template %RNW_TEMPLATE_TYPE% --overwrite --logging
168
168
  call yarn react-native init-windows --template %RNW_TEMPLATE_TYPE% --overwrite --logging
169
169
 
170
+ if %ERRORLEVEL% neq 0 (
171
+ @echo creaternwlib.cmd init-windows command not available from react-native CLI, falling back to react-native-windows-init
172
+ call npx --yes react-native-windows-init@%RNW_VERSION% --template %RNW_TEMPLATE_TYPE% --overwrite --logging
173
+ )
174
+
175
+ if %ERRORLEVEL% neq 0 (
176
+ @echo creaternwlib.cmd: Unable to initialize Windows project
177
+ exit /b %ERRORLEVEL%
178
+ )
179
+
170
180
  @echo creaternwlib.cmd Done, see new %RNW_TEMPLATE_TYPE% project in %CD% with react@%R_VERSION%, react-native@%RN_VERSION%, and react-native-windows@%RNW_VERSION%
171
181
 
172
182
  popd
173
183
 
174
184
  endlocal
175
185
 
176
- exit /b %ERRORLEVEL%
186
+ exit /b %ERRORLEVEL%
@@ -8,7 +8,7 @@ param(
8
8
  [string]$Check = [CheckId]::All,
9
9
 
10
10
  [Parameter(ValueFromRemainingArguments)]
11
- [ValidateSet('appDev', 'rnwDev', 'buildLab', 'vs2022', 'clone')]
11
+ [ValidateSet('appDev', 'rnwDev', 'buildLab', 'vs2026', 'clone')]
12
12
  [String[]]$Tags = @('appDev'),
13
13
  [switch]$Enterprise = $false
14
14
  )
@@ -94,7 +94,6 @@ $vsComponents = @('Microsoft.Component.MSBuild',
94
94
  $vcToolsComponent,
95
95
  'Microsoft.VisualStudio.ComponentGroup.UWP.Support',
96
96
  'Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core',
97
- 'Microsoft.VisualStudio.Component.Windows10SDK.19041',
98
97
  'Microsoft.VisualStudio.Component.Windows11SDK.22621');
99
98
 
100
99
  # UWP.VC is not needed to build the projects with msbuild, but the VS IDE requires it.
@@ -113,12 +112,12 @@ $wingetver = "1.7.11261";
113
112
 
114
113
  # The minimum VS version to check for
115
114
  # Note: For install to work, whatever min version you specify here must be met by the current package available on winget.
116
- $vsver = "17.11.0";
115
+ $vsver = "18.6.1";
117
116
 
118
117
  # The exact .NET SDK version to check for
119
- $dotnetver = "8.0";
118
+ $dotnetver = "10.0";
120
119
  # Version name of the winget package
121
- $wingetDotNetVer = "8";
120
+ $wingetDotNetVer = "10";
122
121
 
123
122
  $v = [System.Environment]::OSVersion.Version;
124
123
  if ($env:Agent_BuildDirectory) {
@@ -242,9 +241,9 @@ function InstallVS {
242
241
 
243
242
  if ($Enterprise) {
244
243
  # The CI machines need the enterprise version of VS as that is what is hardcoded in all the scripts
245
- WinGetInstall Microsoft.VisualStudio.2022.Enterprise
244
+ WinGetInstall Microsoft.VisualStudio.Enterprise
246
245
  } else {
247
- WinGetInstall Microsoft.VisualStudio.2022.Community
246
+ WinGetInstall Microsoft.VisualStudio.Community
248
247
  }
249
248
 
250
249
  $vsWhere = Get-VSWhere;
@@ -458,8 +457,8 @@ $requirements = @(
458
457
  },
459
458
  @{
460
459
  Id=[CheckId]::VSUWP;
461
- Name = "Visual Studio 2022 (>= $vsver) & req. components";
462
- Tags = @('appDev', 'vs2022');
460
+ Name = "Visual Studio 2026 (>= $vsver) & req. components";
461
+ Tags = @('appDev', 'vs2026');
463
462
  Valid = { CheckVS; }
464
463
  Install = { InstallVS };
465
464
  HasVerboseOutput = $true;
@@ -491,7 +490,7 @@ $requirements = @(
491
490
  $downloadPath = "$env:TEMP\WindowsApplicationDriver.msi"
492
491
  Write-Verbose "Downloading WinAppDriver from $url";
493
492
  Invoke-WebRequest -UseBasicParsing $url -OutFile $downloadPath
494
-
493
+
495
494
  # SDL Compliance: Verify signature (Work Item 58386093)
496
495
  $signature = Get-AuthenticodeSignature $downloadPath
497
496
  if ($signature.Status -ne "Valid") {
@@ -499,10 +498,10 @@ $requirements = @(
499
498
  throw "WinAppDriver signature verification failed"
500
499
  }
501
500
  if ($signature.SignerCertificate.Subject -notlike "*Microsoft*") {
502
- Remove-Item $downloadPath -ErrorAction SilentlyContinue
501
+ Remove-Item $downloadPath -ErrorAction SilentlyContinue
503
502
  throw "WinAppDriver not signed by Microsoft"
504
503
  }
505
-
504
+
506
505
  & $downloadPath /q
507
506
  Remove-Item $downloadPath -ErrorAction SilentlyContinue
508
507
  };
@@ -600,7 +599,7 @@ function WinGetInstall {
600
599
  Write-Verbose "Executing `winget install `"$wingetPackage`"";
601
600
  & winget install "$wingetPackage" --accept-source-agreements --accept-package-agreements
602
601
  }
603
-
602
+
604
603
  # Refresh PATH environment variable to pick up newly installed tools
605
604
  $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
606
605
  }
@@ -693,12 +692,12 @@ foreach ($req in $filteredRequirements)
693
692
  try {
694
693
  $validAfterInstall = Invoke-Command $req.Valid;
695
694
  } catch { }
696
-
695
+
697
696
  if ($validAfterInstall) {
698
697
  $Installed++;
699
698
  continue; # go to the next item
700
699
  }
701
-
700
+
702
701
  if ($LASTEXITCODE -ne 0) {
703
702
  throw "Last exit code was non-zero: $LASTEXITCODE - $outputFromInstall";
704
703
  }
@@ -737,4 +736,4 @@ if ($NeedsRerun -ne 0) {
737
736
  $Tags | Out-File $MarkerFile;
738
737
  if (!$ShellInvocation) { Read-Host 'Press Enter to exit' }
739
738
  exit 0;
740
- }
739
+ }
@@ -33,7 +33,6 @@
33
33
  #include <cxxreact/MessageQueueThread.h>
34
34
  #pragma warning(pop)
35
35
 
36
- #include <future>
37
36
  #include <mutex>
38
37
 
39
38
  #include <AppModel.h>
@@ -47,61 +46,59 @@ using namespace facebook::react;
47
46
 
48
47
  namespace Microsoft::ReactNative {
49
48
 
50
- std::future<std::pair<std::string, bool>> GetJavaScriptFromServerAsync(const std::string &url) {
51
- winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter filter;
52
- filter.CacheControl().ReadBehavior(winrt::Windows::Web::Http::Filters::HttpCacheReadBehavior::NoCache);
53
- winrt::Windows::Web::Http::HttpClient httpClient(filter);
54
- winrt::Windows::Foundation::Uri uri(Microsoft::Common::Unicode::Utf8ToUtf16(url));
49
+ winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::Streams::IBuffer> GetJavaScriptFromServerAsync(
50
+ const std::string &url) {
51
+ try {
52
+ winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter filter;
53
+ filter.CacheControl().ReadBehavior(winrt::Windows::Web::Http::Filters::HttpCacheReadBehavior::NoCache);
54
+ winrt::Windows::Web::Http::HttpClient httpClient(filter);
55
+ winrt::Windows::Foundation::Uri uri(Microsoft::Common::Unicode::Utf8ToUtf16(url));
55
56
 
56
- co_await winrt::resume_background();
57
+ co_await winrt::resume_background();
57
58
 
58
- winrt::Windows::Web::Http::HttpRequestMessage request(winrt::Windows::Web::Http::HttpMethod::Get(), uri);
59
- auto asyncRequest = httpClient.SendRequestAsync(request);
59
+ winrt::Windows::Web::Http::HttpRequestMessage request(winrt::Windows::Web::Http::HttpMethod::Get(), uri);
60
+ auto asyncRequest = httpClient.SendRequestAsync(request);
60
61
  #ifdef DEFAULT_CPPWINRT_EXCEPTIONS
61
- try {
62
62
  winrt::Windows::Web::Http::HttpResponseMessage response = co_await asyncRequest;
63
- } catch (winrt::hresult_error const &e) {
64
- co_return std::make_pair(
65
- Microsoft::Common::Unicode::Utf16ToUtf8(e.message().c_str(), e.message().size()).c_str(), false);
66
- }
67
63
  #else
68
- co_await lessthrow_await_adapter<winrt::Windows::Foundation::IAsyncOperationWithProgress<
69
- winrt::Windows::Web::Http::HttpResponseMessage,
70
- winrt::Windows::Web::Http::HttpProgress>>{asyncRequest};
71
-
72
- HRESULT hr = asyncRequest.ErrorCode();
73
- if (FAILED(hr)) {
74
- std::string error;
75
- if (hr == WININET_E_CANNOT_CONNECT) {
76
- error = fmt::format("A connection with the server {} could not be established.\n\nIs the packager running?", url);
77
- } else {
78
- error = fmt::format("Error 0x{:x} downloading {}.", static_cast<int>(asyncRequest.ErrorCode()), url);
64
+ co_await lessthrow_await_adapter<winrt::Windows::Foundation::IAsyncOperationWithProgress<
65
+ winrt::Windows::Web::Http::HttpResponseMessage,
66
+ winrt::Windows::Web::Http::HttpProgress>>{asyncRequest};
67
+
68
+ HRESULT hr = asyncRequest.ErrorCode();
69
+ if (FAILED(hr)) {
70
+ std::string error;
71
+ if (hr == WININET_E_CANNOT_CONNECT) {
72
+ error =
73
+ fmt::format("A connection with the server {} could not be established.\n\nIs the packager running?", url);
74
+ } else {
75
+ error = fmt::format("Error 0x{:x} downloading {}.", static_cast<int>(asyncRequest.ErrorCode()), url);
76
+ }
77
+ throw winrt::hresult_error(E_FAIL, winrt::to_hstring(error));
79
78
  }
80
- co_return std::make_pair(error, false);
81
- }
82
79
 
83
- winrt::Windows::Web::Http::HttpResponseMessage response = asyncRequest.GetResults();
80
+ winrt::Windows::Web::Http::HttpResponseMessage response = asyncRequest.GetResults();
84
81
  #endif
85
82
 
86
- winrt::Windows::Storage::Streams::IBuffer buffer = co_await response.Content().ReadAsBufferAsync();
87
- auto reader = winrt::Windows::Storage::Streams::DataReader::FromBuffer(buffer);
88
-
89
- reader.UnicodeEncoding(winrt::Windows::Storage::Streams::UnicodeEncoding::Utf8);
90
- uint32_t len = reader.UnconsumedBufferLength();
91
- std::string result;
92
- if (len > 0 || response.IsSuccessStatusCode()) {
93
- std::string data;
94
- data.resize(len);
95
- auto buf = reinterpret_cast<uint8_t *>(data.data());
96
- static_assert(
97
- sizeof(buf[0]) == sizeof(data[0]), "perf optimization relies on uint8_t and char being the same size");
98
- reader.ReadBytes(winrt::array_view(buf, buf + len));
99
- result = std::move(data);
100
- } else {
101
- result = fmt::format("HTTP Error {} downloading {}.", static_cast<int>(response.StatusCode()), url);
102
- }
83
+ winrt::Windows::Storage::Streams::IBuffer buffer = co_await response.Content().ReadAsBufferAsync();
84
+
85
+ if (!response.IsSuccessStatusCode()) {
86
+ std::string error;
87
+ if (buffer.Length() > 0) {
88
+ auto reader = winrt::Windows::Storage::Streams::DataReader::FromBuffer(buffer);
89
+ error.resize(buffer.Length());
90
+ auto buf = reinterpret_cast<uint8_t *>(error.data());
91
+ reader.ReadBytes(winrt::array_view(buf, buf + buffer.Length()));
92
+ } else {
93
+ error = fmt::format("HTTP Error {} downloading {}.", static_cast<int>(response.StatusCode()), url);
94
+ }
95
+ throw winrt::hresult_error(E_FAIL, winrt::to_hstring(error));
96
+ }
103
97
 
104
- co_return std::make_pair(std::move(result), response.IsSuccessStatusCode());
98
+ co_return buffer;
99
+ } catch (winrt::hresult_error const &) {
100
+ throw;
101
+ }
105
102
  }
106
103
 
107
104
  void LaunchDevTools(const facebook::react::DevSettings &settings) {
@@ -185,7 +182,8 @@ std::string GetPackageName(const std::string &bundleAppId) {
185
182
  return packageName;
186
183
  }
187
184
 
188
- std::future<winrt::Windows::Web::Http::HttpStatusCode> PollForLiveReload(const std::string &url) {
185
+ winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Web::Http::HttpStatusCode> PollForLiveReload(
186
+ const std::string &url) {
189
187
  winrt::Windows::Web::Http::HttpClient httpClient;
190
188
  winrt::Windows::Foundation::Uri uri(Microsoft::Common::Unicode::Utf8ToUtf16(url));
191
189
  httpClient.DefaultRequestHeaders().Connection().TryParseAdd(L"keep-alive");
@@ -299,7 +297,16 @@ std::pair<std::string, bool> GetJavaScriptFromServer(
299
297
  inlineSourceMap,
300
298
  hermesBytecodeVersion);
301
299
  try {
302
- return GetJavaScriptFromServerAsync(bundleUrl).get();
300
+ auto buffer = GetJavaScriptFromServerAsync(bundleUrl).get();
301
+ std::string result(buffer.Length(), '\0');
302
+ if (!result.empty()) {
303
+ auto reader = winrt::Windows::Storage::Streams::DataReader::FromBuffer(buffer);
304
+ reader.ReadBytes(winrt::array_view<uint8_t>{
305
+ reinterpret_cast<uint8_t *>(&result[0]), reinterpret_cast<uint8_t *>(&result[result.length()])});
306
+ }
307
+ return std::make_pair(std::move(result), true);
308
+ } catch (std::exception const &e) {
309
+ return std::make_pair(std::string{"Error: "} + e.what(), false);
303
310
  } catch (winrt::hresult_error const &e) {
304
311
  return std::make_pair(
305
312
  "Error: " + Microsoft::Common::Unicode::Utf16ToUtf8(e.message().c_str(), e.message().size()), false);
@@ -10,7 +10,6 @@
10
10
  #include <winrt/Windows.Networking.Sockets.h>
11
11
  #include <atomic>
12
12
  #include <functional>
13
- #include <future>
14
13
  #include <memory>
15
14
  #include <string>
16
15
 
@@ -18,11 +18,26 @@ namespace Microsoft::React {
18
18
  struct IWebSocketModuleContentHandler {
19
19
  virtual ~IWebSocketModuleContentHandler() noexcept {}
20
20
 
21
+ /// Returns true if this handler should process messages for the given socket.
22
+ virtual bool CanHandleSocket(int64_t socketId) noexcept = 0;
23
+
21
24
  virtual void ProcessMessage(std::string &&message, winrt::Microsoft::ReactNative::JSValueObject &params) noexcept = 0;
22
25
 
23
26
  virtual void ProcessMessage(
24
27
  std::vector<uint8_t> &&message,
25
28
  winrt::Microsoft::ReactNative::JSValueObject &params) noexcept = 0;
29
+
30
+ /// Check CanHandleSocket() then ProcessMessage() in one call.
31
+ /// Returns true if the message was handled.
32
+ virtual bool TryProcessMessage(
33
+ int64_t socketId,
34
+ std::string &&message,
35
+ winrt::Microsoft::ReactNative::JSValueObject &params) noexcept = 0;
36
+
37
+ virtual bool TryProcessMessage(
38
+ int64_t socketId,
39
+ std::vector<uint8_t> &&message,
40
+ winrt::Microsoft::ReactNative::JSValueObject &params) noexcept = 0;
26
41
  };
27
42
 
28
43
  } // namespace Microsoft::React
@@ -84,6 +84,7 @@ shared_ptr<IWebSocketResource> WebSocketTurboModule::CreateResource(int64_t id,
84
84
  if (auto prop = propBag.Get(BlobModuleContentHandlerPropertyId()))
85
85
  contentHandler = prop.Value().lock();
86
86
 
87
+ bool handled = false;
87
88
  if (contentHandler) {
88
89
  if (isBinary) {
89
90
  auto buffer = CryptographicBuffer::DecodeFromBase64String(winrt::to_hstring(message));
@@ -91,11 +92,15 @@ shared_ptr<IWebSocketResource> WebSocketTurboModule::CreateResource(int64_t id,
91
92
  CryptographicBuffer::CopyToByteArray(buffer, arr);
92
93
  auto data = vector<uint8_t>(arr.begin(), arr.end());
93
94
 
94
- contentHandler->ProcessMessage(std::move(data), args);
95
+ handled = contentHandler->TryProcessMessage(id, std::move(data), args);
95
96
  } else {
96
- contentHandler->ProcessMessage(string{message}, args);
97
+ handled = contentHandler->TryProcessMessage(id, string{message}, args);
97
98
  }
98
- } else {
99
+ }
100
+ // When the content handler processes the message, it takes ownership of the
101
+ // payload and populates args itself (e.g. as a blob reference), so we only
102
+ // fall back to setting args["data"] when no handler claimed the message.
103
+ if (!handled) {
99
104
  args["data"] = message;
100
105
  }
101
106
 
@@ -221,6 +221,11 @@ BlobWebSocketModuleContentHandler::BlobWebSocketModuleContentHandler(shared_ptr<
221
221
 
222
222
  #pragma region IWebSocketModuleContentHandler
223
223
 
224
+ bool BlobWebSocketModuleContentHandler::CanHandleSocket(int64_t socketId) noexcept /*override*/ {
225
+ scoped_lock lock{m_mutex};
226
+ return m_socketIds.find(socketId) != m_socketIds.end();
227
+ }
228
+
224
229
  void BlobWebSocketModuleContentHandler::ProcessMessage(
225
230
  string &&message,
226
231
  msrn::JSValueObject &params) noexcept /*override*/
@@ -241,6 +246,38 @@ void BlobWebSocketModuleContentHandler::ProcessMessage(
241
246
  params[blobKeys.Type] = blobKeys.Blob;
242
247
  }
243
248
 
249
+ bool BlobWebSocketModuleContentHandler::TryProcessMessage(
250
+ int64_t socketId,
251
+ string &&message,
252
+ msrn::JSValueObject &params) noexcept /*override*/
253
+ {
254
+ scoped_lock lock{m_mutex};
255
+ if (m_socketIds.find(socketId) == m_socketIds.end())
256
+ return false;
257
+
258
+ params[blobKeys.Data] = std::move(message);
259
+ return true;
260
+ }
261
+
262
+ bool BlobWebSocketModuleContentHandler::TryProcessMessage(
263
+ int64_t socketId,
264
+ vector<uint8_t> &&message,
265
+ msrn::JSValueObject &params) noexcept /*override*/
266
+ {
267
+ scoped_lock lock{m_mutex};
268
+ if (m_socketIds.find(socketId) == m_socketIds.end())
269
+ return false;
270
+
271
+ auto blob = msrn::JSValueObject{
272
+ {blobKeys.Offset, 0},
273
+ {blobKeys.Size, message.size()},
274
+ {blobKeys.BlobId, m_blobPersistor->StoreMessage(std::move(message))}};
275
+
276
+ params[blobKeys.Data] = std::move(blob);
277
+ params[blobKeys.Type] = blobKeys.Blob;
278
+ return true;
279
+ }
280
+
244
281
  #pragma endregion IWebSocketModuleContentHandler
245
282
 
246
283
  void BlobWebSocketModuleContentHandler::Register(int64_t socketID) noexcept {
@@ -51,11 +51,23 @@ class BlobWebSocketModuleContentHandler final : public IWebSocketModuleContentHa
51
51
 
52
52
  #pragma region IWebSocketModuleContentHandler
53
53
 
54
+ bool CanHandleSocket(int64_t socketId) noexcept override;
55
+
54
56
  void ProcessMessage(std::string &&message, winrt::Microsoft::ReactNative::JSValueObject &params) noexcept override;
55
57
 
56
58
  void ProcessMessage(std::vector<uint8_t> &&message, winrt::Microsoft::ReactNative::JSValueObject &params) noexcept
57
59
  override;
58
60
 
61
+ bool TryProcessMessage(
62
+ int64_t socketId,
63
+ std::string &&message,
64
+ winrt::Microsoft::ReactNative::JSValueObject &params) noexcept override;
65
+
66
+ bool TryProcessMessage(
67
+ int64_t socketId,
68
+ std::vector<uint8_t> &&message,
69
+ winrt::Microsoft::ReactNative::JSValueObject &params) noexcept override;
70
+
59
71
  #pragma endregion IWebSocketModuleContentHandler
60
72
 
61
73
  void Register(int64_t socketID) noexcept;
@@ -27,8 +27,12 @@ class WinRTWebSocketResource2 : public IWebSocketResource,
27
27
  void operator=(const TaskSequencer &) = delete;
28
28
 
29
29
  private:
30
+ // `experimental` is deprecated starting Visual Studio 2026
31
+ #if _MSC_VER >= 1951
32
+ using CoroHandle = std::coroutine_handle<>;
33
+ #else
30
34
  using CoroHandle = std::experimental::coroutine_handle<>;
31
-
35
+ #endif
32
36
  struct Suspender {
33
37
  CoroHandle m_handle;
34
38
 
package/just-task.js CHANGED
@@ -25,6 +25,7 @@ const fs = require('fs');
25
25
  const {
26
26
  registerNuGetRestoreTask,
27
27
  } = require('@rnw-scripts/just-task/nuget-restore-task');
28
+ const {findPowerShell} = require('@react-native-windows/find-dotnet-tools');
28
29
 
29
30
  option('production');
30
31
  option('clean');
@@ -46,9 +47,9 @@ function codegen(test) {
46
47
 
47
48
  function layoutMSRNCxx() {
48
49
  if (require('os').platform() === 'win32') {
49
- const powershell = `${process.env.SystemRoot}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
50
+ const powershell = findPowerShell();
50
51
  execSync(
51
- `${powershell} -NoProfile .\\Scripts\\Tfs\\Layout-MSRN-Headers.ps1 -GenerateLocalCxx`,
52
+ `"${powershell}" -NoProfile .\\Scripts\\Tfs\\Layout-MSRN-Headers.ps1 -GenerateLocalCxx`,
52
53
  {
53
54
  env: process.env,
54
55
  },
@@ -84,12 +85,22 @@ registerNuGetRestoreTask({
84
85
  scriptArguments: ['-SkipLockDeletion'],
85
86
  });
86
87
 
88
+ function installDotnetToolsTask() {
89
+ execSync(
90
+ `dotnet tool restore --tool-manifest ${path.resolve(__dirname, 'dotnet-tools.json')}`,
91
+ {env: process.env},
92
+ );
93
+ }
94
+
95
+ task('installDotnetTools', installDotnetToolsTask);
96
+
87
97
  task(
88
98
  'build',
89
99
  series(
90
100
  condition('clean', () => argv().clean),
91
101
  'copyRNLibraries',
92
102
  'copyReadmeAndLicenseFromRoot',
103
+ condition('installDotnetTools', () => !process.env.TF_BUILD),
93
104
  'layoutMSRNCxx',
94
105
  'compileTsPlatformOverrides',
95
106
  'restoreNuGetPackages',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-windows",
3
- "version": "0.83.0",
3
+ "version": "0.83.2",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,7 +26,7 @@
26
26
  "@react-native-community/cli": "20.0.0",
27
27
  "@react-native-community/cli-platform-android": "20.0.0",
28
28
  "@react-native-community/cli-platform-ios": "20.0.0",
29
- "@react-native-windows/cli": "0.83.0",
29
+ "@react-native-windows/cli": "0.83.2",
30
30
  "@react-native/assets": "1.0.0",
31
31
  "@react-native/assets-registry": "0.83.4",
32
32
  "@react-native/codegen": "0.83.4",
@@ -69,7 +69,7 @@
69
69
  "yargs": "^17.6.2"
70
70
  },
71
71
  "devDependencies": {
72
- "@react-native-windows/codegen": "0.83.0",
72
+ "@react-native-windows/codegen": "0.83.1",
73
73
  "@react-native/metro-config": "0.83.4",
74
74
  "@rnw-scripts/babel-react-native-config": "0.0.0",
75
75
  "@rnw-scripts/eslint-config": "1.2.38",
@@ -86,7 +86,7 @@
86
86
  "prettier": "2.8.8",
87
87
  "react": "19.2.0",
88
88
  "react-native": "0.83.4",
89
- "react-native-platform-override": "0.83.0",
89
+ "react-native-platform-override": "0.83.1",
90
90
  "react-refresh": "^0.14.0",
91
91
  "typescript": "5.0.4"
92
92
  },
@@ -96,7 +96,7 @@
96
96
  "react-native": "^0.83.0"
97
97
  },
98
98
  "beachball": {
99
- "defaultNpmTag": "latest",
99
+ "defaultNpmTag": "v0.83-stable",
100
100
  "disallowedChangeTypes": [
101
101
  "major",
102
102
  "minor",
@@ -50,7 +50,7 @@
50
50
  <PropertyGroup Label="Configuration">
51
51
  <ConfigurationType>Application</ConfigurationType>
52
52
  <CharacterSet>Unicode</CharacterSet>
53
- <PlatformToolset>v143</PlatformToolset>
53
+ <PlatformToolset>v145</PlatformToolset>
54
54
  </PropertyGroup>
55
55
  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
56
56
  <UseDebugLibraries>true</UseDebugLibraries>
@@ -49,7 +49,7 @@
49
49
  <PropertyGroup Label="Configuration">
50
50
  <ConfigurationType>DynamicLibrary</ConfigurationType>
51
51
  <CharacterSet>Unicode</CharacterSet>
52
- <PlatformToolset>v143</PlatformToolset>
52
+ <PlatformToolset>v145</PlatformToolset>
53
53
  <GenerateManifest>false</GenerateManifest>
54
54
  </PropertyGroup>
55
55
  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">