react-native-windows 0.83.0-preview.4 → 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 (37) 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/Composition/TooltipService.cpp +80 -0
  6. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.h +17 -0
  7. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/WindowsTextLayoutManager.cpp +1 -1
  8. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +3 -2
  9. package/Microsoft.ReactNative/ReactNativeAppBuilder.idl +3 -0
  10. package/Microsoft.ReactNative/Utils/LocalBundleReader.cpp +33 -25
  11. package/Microsoft.ReactNative/Utils/LocalBundleReader.h +5 -3
  12. package/Microsoft.ReactNative/Utils/UwpScriptStore.cpp +2 -2
  13. package/Microsoft.ReactNative/Utils/UwpScriptStore.h +3 -2
  14. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +16 -0
  15. package/Microsoft.ReactNative.Managed/Microsoft.ReactNative.Managed.csproj +3 -3
  16. package/Microsoft.ReactNative.Managed.CodeGen/Microsoft.ReactNative.Managed.CodeGen.csproj +10 -10
  17. package/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Debug.pubxml +1 -1
  18. package/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Release.pubxml +1 -1
  19. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  20. package/PropertySheets/React.Cpp.props +4 -3
  21. package/PropertySheets/WinUI.props +2 -2
  22. package/Scripts/JustMyXaml.ps1 +8 -8
  23. package/Scripts/UnitTest.ps1 +3 -1
  24. package/Scripts/creaternwapp.cmd +12 -2
  25. package/Scripts/creaternwlib.cmd +12 -2
  26. package/Scripts/rnw-dependencies.ps1 +15 -16
  27. package/Shared/DevSupportManager.cpp +55 -48
  28. package/Shared/DevSupportManager.h +0 -1
  29. package/Shared/Modules/IWebSocketModuleContentHandler.h +15 -0
  30. package/Shared/Modules/WebSocketModule.cpp +8 -3
  31. package/Shared/Networking/DefaultBlobResource.cpp +37 -0
  32. package/Shared/Networking/DefaultBlobResource.h +12 -0
  33. package/Shared/Networking/WinRTWebSocketResource.h +5 -1
  34. package/just-task.js +13 -2
  35. package/package.json +6 -6
  36. package/templates/cpp-app/windows/MyApp/MyApp.vcxproj +1 -1
  37. 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) ||
@@ -169,12 +169,22 @@ TooltipTracker::TooltipTracker(
169
169
  view.PointerEntered({this, &TooltipTracker::OnPointerEntered});
170
170
  view.PointerExited({this, &TooltipTracker::OnPointerExited});
171
171
  view.PointerMoved({this, &TooltipTracker::OnPointerMoved});
172
+ view.GotFocus({this, &TooltipTracker::OnGotFocus});
173
+ view.LostFocus({this, &TooltipTracker::OnLostFocus});
172
174
  view.Unmounted({this, &TooltipTracker::OnUnmounted});
173
175
  }
174
176
 
175
177
  TooltipTracker::~TooltipTracker() {
176
178
  DestroyTimer();
177
179
  DestroyTooltip();
180
+ m_outer->NotifyDismiss(this);
181
+ }
182
+
183
+ void TooltipTracker::DismissForExternalRequest() noexcept {
184
+ // Service is already updating its active slot; do not call back into it.
185
+ m_focusTooltip = false;
186
+ DestroyTimer();
187
+ DestroyTooltip();
178
188
  }
179
189
 
180
190
  facebook::react::Tag TooltipTracker::Tag() const noexcept {
@@ -192,6 +202,9 @@ void TooltipTracker::OnPointerEntered(
192
202
  auto pp = args.GetCurrentPoint(-1);
193
203
  m_pos = pp.Position();
194
204
 
205
+ // Claim the single tooltip slot, dismissing any other tracker's pending or visible tooltip.
206
+ m_outer->NotifyShow(this);
207
+
195
208
  m_timer = winrt::Microsoft::ReactNative::Timer::Create(m_properties.Handle());
196
209
  m_timer.Interval(std::chrono::milliseconds(toolTipTimeToShowMs));
197
210
  m_timer.Tick({this, &TooltipTracker::OnTick});
@@ -225,6 +238,56 @@ void TooltipTracker::OnPointerExited(
225
238
  return;
226
239
  DestroyTimer();
227
240
  DestroyTooltip();
241
+ m_outer->NotifyDismiss(this);
242
+ }
243
+
244
+ void TooltipTracker::OnGotFocus(
245
+ const winrt::Windows::Foundation::IInspectable & /*sender*/,
246
+ const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs & /*args*/) noexcept {
247
+ // Skip if a mouse-driven tooltip or its dwell timer is already in flight on this view.
248
+ if (m_hwndTip || m_timer) {
249
+ return;
250
+ }
251
+
252
+ auto view = m_view.view();
253
+ if (!view) {
254
+ return;
255
+ }
256
+
257
+ auto viewCompView = view.try_as<winrt::Microsoft::ReactNative::Composition::ViewComponentView>();
258
+ if (!viewCompView) {
259
+ return;
260
+ }
261
+ auto selfView =
262
+ winrt::get_self<winrt::Microsoft::ReactNative::Composition::implementation::ViewComponentView>(viewCompView);
263
+ RECT rc = selfView->getClientRect();
264
+ auto scaleFactor = view.LayoutMetrics().PointScaleFactor;
265
+ if (scaleFactor <= 0) {
266
+ return;
267
+ }
268
+
269
+ // Anchor in DIPs at the horizontal center of the view's top edge; ShowTooltip re-applies scaleFactor.
270
+ m_pos = {static_cast<float>(rc.left + rc.right) / 2.0f / scaleFactor, static_cast<float>(rc.top) / scaleFactor};
271
+
272
+ m_focusTooltip = true;
273
+ // Claim the single tooltip slot, dismissing any other tracker's pending or visible tooltip.
274
+ m_outer->NotifyShow(this);
275
+ m_timer = winrt::Microsoft::ReactNative::Timer::Create(m_properties.Handle());
276
+ m_timer.Interval(std::chrono::milliseconds(toolTipTimeToShowMs));
277
+ m_timer.Tick({this, &TooltipTracker::OnTick});
278
+ m_timer.Start();
279
+ }
280
+
281
+ void TooltipTracker::OnLostFocus(
282
+ const winrt::Windows::Foundation::IInspectable & /*sender*/,
283
+ const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs & /*args*/) noexcept {
284
+ if (!m_focusTooltip) {
285
+ return;
286
+ }
287
+ m_focusTooltip = false;
288
+ DestroyTimer();
289
+ DestroyTooltip();
290
+ m_outer->NotifyDismiss(this);
228
291
  }
229
292
 
230
293
  void TooltipTracker::OnUnmounted(
@@ -232,6 +295,7 @@ void TooltipTracker::OnUnmounted(
232
295
  const winrt::Microsoft::ReactNative::ComponentView &) noexcept {
233
296
  DestroyTimer();
234
297
  DestroyTooltip();
298
+ m_outer->NotifyDismiss(this);
235
299
  }
236
300
 
237
301
  void TooltipTracker::ShowTooltip(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
@@ -326,6 +390,22 @@ void TooltipService::StopTracking(const winrt::Microsoft::ReactNative::Component
326
390
  }
327
391
  }
328
392
 
393
+ void TooltipService::NotifyShow(TooltipTracker *tracker) noexcept {
394
+ if (m_activeTracker == tracker) {
395
+ return;
396
+ }
397
+ if (m_activeTracker) {
398
+ m_activeTracker->DismissForExternalRequest();
399
+ }
400
+ m_activeTracker = tracker;
401
+ }
402
+
403
+ void TooltipService::NotifyDismiss(TooltipTracker *tracker) noexcept {
404
+ if (m_activeTracker == tracker) {
405
+ m_activeTracker = nullptr;
406
+ }
407
+ }
408
+
329
409
  static const ReactPropertyId<winrt::Microsoft::ReactNative::ReactNonAbiValue<std::shared_ptr<TooltipService>>>
330
410
  &TooltipServicePropertyId() noexcept {
331
411
  static const ReactPropertyId<winrt::Microsoft::ReactNative::ReactNonAbiValue<std::shared_ptr<TooltipService>>> prop{
@@ -27,6 +27,12 @@ struct TooltipTracker {
27
27
  void OnPointerExited(
28
28
  const winrt::Windows::Foundation::IInspectable &sender,
29
29
  const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept;
30
+ void OnGotFocus(
31
+ const winrt::Windows::Foundation::IInspectable &sender,
32
+ const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept;
33
+ void OnLostFocus(
34
+ const winrt::Windows::Foundation::IInspectable &sender,
35
+ const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept;
30
36
  void OnTick(
31
37
  const winrt::Windows::Foundation::IInspectable &,
32
38
  const winrt::Windows::Foundation::IInspectable &) noexcept;
@@ -36,6 +42,10 @@ struct TooltipTracker {
36
42
 
37
43
  facebook::react::Tag Tag() const noexcept;
38
44
 
45
+ // Cancel pending dwell timer and close any visible tooltip popup; used by the service when another tracker takes
46
+ // over.
47
+ void DismissForExternalRequest() noexcept;
48
+
39
49
  private:
40
50
  void ShowTooltip(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept;
41
51
  void DestroyTimer() noexcept;
@@ -46,6 +56,7 @@ struct TooltipTracker {
46
56
  ::Microsoft::ReactNative::ReactTaggedView m_view;
47
57
  winrt::Microsoft::ReactNative::ITimer m_timer;
48
58
  HWND m_hwndTip{nullptr};
59
+ bool m_focusTooltip{false};
49
60
  winrt::Microsoft::ReactNative::ReactPropertyBag m_properties;
50
61
  };
51
62
 
@@ -54,12 +65,18 @@ struct TooltipService {
54
65
  void StartTracking(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept;
55
66
  void StopTracking(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept;
56
67
 
68
+ // Enforce "only one tooltip visible at a time": dismisses the previously active tracker, if any.
69
+ void NotifyShow(TooltipTracker *tracker) noexcept;
70
+ // Clears the active-tracker slot if it still points at `tracker`.
71
+ void NotifyDismiss(TooltipTracker *tracker) noexcept;
72
+
57
73
  static std::shared_ptr<TooltipService> GetCurrent(
58
74
  const winrt::Microsoft::ReactNative::ReactPropertyBag &properties) noexcept;
59
75
 
60
76
  private:
61
77
  std::vector<std::shared_ptr<TooltipTracker>> m_enteredTrackers;
62
78
  std::vector<std::shared_ptr<TooltipTracker>> m_trackers;
79
+ TooltipTracker *m_activeTracker{nullptr};
63
80
  winrt::Microsoft::ReactNative::ReactPropertyBag m_properties;
64
81
  };
65
82
 
@@ -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-preview.4</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>0ec67ebb53a96bd08e313d3bc17f438ff0f0dc42</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>