react-native-windows 0.76.7 → 0.76.9

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 (136) hide show
  1. package/Libraries/Components/Button.windows.js +9 -0
  2. package/Libraries/Components/Pressable/Pressable.windows.js +9 -0
  3. package/Libraries/Components/TextInput/TextInput.windows.js +11 -1
  4. package/Libraries/Components/Touchable/TouchableBounce.windows.js +229 -0
  5. package/Libraries/Components/Touchable/TouchableNativeFeedback.windows.js +373 -0
  6. package/Libraries/Components/Touchable/TouchableOpacity.windows.js +7 -0
  7. package/Libraries/Components/Touchable/TouchableWithoutFeedback.windows.js +8 -0
  8. package/Libraries/Components/View/View.windows.js +11 -1
  9. package/Libraries/Components/View/ViewAccessibility.d.ts +15 -0
  10. package/Libraries/Components/View/ViewAccessibility.windows.js +3 -0
  11. package/Libraries/Components/View/ViewPropTypes.windows.js +3 -0
  12. package/Libraries/Core/ReactNativeVersion.js +1 -1
  13. package/Libraries/Image/Image.windows.js +7 -0
  14. package/Libraries/Modal/Modal.windows.js +4 -1
  15. package/Libraries/Text/Text.windows.js +14 -1
  16. package/Libraries/Text/TextProps.windows.js +3 -0
  17. package/Microsoft.ReactNative/CompositionComponentView.idl +13 -1
  18. package/Microsoft.ReactNative/Fabric/AbiPortalShadowNode.cpp +97 -0
  19. package/Microsoft.ReactNative/Fabric/AbiPortalShadowNode.h +53 -0
  20. package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.h +160 -17
  21. package/Microsoft.ReactNative/Fabric/AbiViewProps.cpp +8 -10
  22. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +4 -2
  23. package/Microsoft.ReactNative/Fabric/Composition/ComponentViewRegistry.cpp +0 -5
  24. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +428 -39
  25. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +39 -1
  26. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +55 -33
  27. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +5 -3
  28. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp +43 -5
  29. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.h +2 -1
  30. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.cpp +115 -0
  31. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.h +41 -0
  32. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp +298 -0
  33. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.h +59 -0
  34. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +106 -56
  35. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +2 -0
  36. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +163 -10
  37. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +17 -1
  38. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.cpp +4 -2
  39. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.h +9 -1
  40. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +348 -316
  41. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +3 -61
  42. package/Microsoft.ReactNative/Fabric/Composition/PortalComponentView.cpp +78 -0
  43. package/Microsoft.ReactNative/Fabric/Composition/PortalComponentView.h +52 -0
  44. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp +22 -0
  45. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +7 -5
  46. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +99 -37
  47. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +12 -6
  48. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +81 -22
  49. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +21 -2
  50. package/Microsoft.ReactNative/Fabric/Composition/Theme.cpp +6 -1
  51. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.cpp +41 -37
  52. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +76 -33
  53. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +8 -2
  54. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +1 -6
  55. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h +0 -3
  56. package/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp +0 -2
  57. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/HostPlatformColor.h +5 -8
  58. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorParser.h +1 -2
  59. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorUtils.cpp +1 -1
  60. package/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl +15 -1
  61. package/Microsoft.ReactNative/IReactContext.cpp +2 -2
  62. package/Microsoft.ReactNative/IReactContext.h +1 -1
  63. package/Microsoft.ReactNative/IReactContext.idl +2 -2
  64. package/Microsoft.ReactNative/IReactPackageBuilder.idl +3 -3
  65. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +97 -87
  66. package/Microsoft.ReactNative/Modules/AccessibilityInfoModule.cpp +4 -0
  67. package/Microsoft.ReactNative/Modules/AlertModule.cpp +9 -4
  68. package/Microsoft.ReactNative/Modules/Animated/NativeAnimatedNodeManager.cpp +1 -1
  69. package/Microsoft.ReactNative/Modules/Animated/PropsAnimatedNode.cpp +32 -35
  70. package/Microsoft.ReactNative/Modules/Animated/PropsAnimatedNode.h +7 -4
  71. package/Microsoft.ReactNative/Modules/AppStateModule.cpp +1 -1
  72. package/Microsoft.ReactNative/Modules/AppThemeModuleUwp.cpp +2 -2
  73. package/Microsoft.ReactNative/Modules/AppearanceModule.cpp +2 -2
  74. package/Microsoft.ReactNative/Modules/ClipboardModule.cpp +1 -1
  75. package/Microsoft.ReactNative/Modules/ClipboardModule.h +1 -1
  76. package/Microsoft.ReactNative/Modules/DeviceInfoModule.cpp +3 -3
  77. package/Microsoft.ReactNative/Modules/I18nManagerModule.cpp +1 -1
  78. package/Microsoft.ReactNative/Modules/LogBoxModule.cpp +7 -5
  79. package/Microsoft.ReactNative/Modules/LogBoxModule.h +2 -1
  80. package/Microsoft.ReactNative/Modules/Timing.cpp +2 -2
  81. package/Microsoft.ReactNative/ReactHost/IReactInstance.h +5 -0
  82. package/Microsoft.ReactNative/ReactHost/React.h +0 -3
  83. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +36 -12
  84. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +1 -1
  85. package/Microsoft.ReactNative/ReactNativeHost.cpp +9 -4
  86. package/Microsoft.ReactNative/ReactNativeIsland.idl +5 -1
  87. package/Microsoft.ReactNative/ReactPackageBuilder.cpp +3 -3
  88. package/Microsoft.ReactNative/ReactPackageBuilder.h +4 -4
  89. package/Microsoft.ReactNative/Utils/Helpers.cpp +0 -2
  90. package/Microsoft.ReactNative/Views/DevMenu.cpp +6 -6
  91. package/Microsoft.ReactNative/Views/DevMenu.h +1 -1
  92. package/Microsoft.ReactNative/XamlUIService.cpp +13 -7
  93. package/Microsoft.ReactNative/XamlUIService.h +4 -1
  94. package/Microsoft.ReactNative/XamlUIService.idl +2 -0
  95. package/Microsoft.ReactNative.Cxx/JSI/JsiAbiApi.h +6 -2
  96. package/Microsoft.ReactNative.Cxx/NativeModules.h +29 -0
  97. package/Microsoft.ReactNative.Cxx/ReactContext.h +1 -1
  98. package/Microsoft.ReactNative.Cxx/XamlUtils.h +12 -0
  99. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  100. package/PropertySheets/React.Cpp.props +3 -0
  101. package/PropertySheets/WebView2.props +1 -1
  102. package/PropertySheets/WinUI.props +5 -4
  103. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/AccessibilityPrimitives.h +253 -0
  104. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/accessibilityPropsConversions.h +799 -0
  105. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/ReactInstance.cpp +39 -35
  106. package/Shared/InspectorPackagerConnection.cpp +2 -5
  107. package/Shared/InspectorPackagerConnection.h +2 -2
  108. package/Shared/Networking/WinRTWebSocketResource.cpp +369 -7
  109. package/Shared/Networking/WinRTWebSocketResource.h +118 -0
  110. package/Shared/Shared.vcxitems +12 -5
  111. package/Shared/Shared.vcxitems.filters +11 -4
  112. package/codegen/NativeReactNativeFeatureFlagsSpec.g.h +91 -97
  113. package/codegen/react/components/rnwcore/ActivityIndicatorView.g.h +212 -0
  114. package/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h +295 -0
  115. package/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h +200 -0
  116. package/codegen/react/components/rnwcore/AndroidProgressBar.g.h +224 -0
  117. package/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h +250 -0
  118. package/codegen/react/components/rnwcore/AndroidSwitch.g.h +267 -0
  119. package/codegen/react/components/rnwcore/DebuggingOverlay.g.h +234 -0
  120. package/codegen/react/components/rnwcore/InputAccessory.g.h +200 -0
  121. package/codegen/react/components/rnwcore/ModalHostView.g.h +279 -0
  122. package/codegen/react/components/rnwcore/PullToRefreshView.g.h +246 -0
  123. package/codegen/react/components/rnwcore/SafeAreaView.g.h +197 -0
  124. package/codegen/react/components/rnwcore/Switch.g.h +263 -0
  125. package/codegen/react/components/rnwcore/UnimplementedNativeView.g.h +200 -0
  126. package/codegen/rnwcoreJSI-generated.cpp +0 -6
  127. package/codegen/rnwcoreJSI.h +0 -9
  128. package/jest/setup.js +5 -1
  129. package/just-task.js +1 -1
  130. package/package.json +11 -11
  131. package/src/private/featureflags/ReactNativeFeatureFlags.js +1 -6
  132. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +1 -2
  133. package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.cpp +0 -191
  134. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentDescriptor.h +0 -39
  135. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewShadowNode.cpp +0 -18
  136. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewShadowNode.h +0 -39
@@ -204,47 +204,51 @@ std::string simpleBasename(const std::string& path) {
204
204
  */
205
205
  void ReactInstance::loadScript(
206
206
  std::unique_ptr<const JSBigString> script,
207
- const std::string& sourceURL) {
207
+ const std::string& sourceURL,
208
+ std::function<void(jsi::Runtime& runtime)>&& completion) {
208
209
  auto buffer = std::make_shared<BigStringBuffer>(std::move(script));
209
210
  std::string scriptName = simpleBasename(sourceURL);
210
211
 
211
- runtimeScheduler_->scheduleWork(
212
- [this,
213
- scriptName,
214
- sourceURL,
215
- buffer = std::move(buffer),
216
- weakBufferedRuntimeExecuter = std::weak_ptr<BufferedRuntimeExecutor>(
217
- bufferedRuntimeExecutor_)](jsi::Runtime& runtime) {
218
- SystraceSection s("ReactInstance::loadScript");
219
- bool hasLogger(ReactMarker::logTaggedMarkerBridgelessImpl);
220
- if (hasLogger) {
221
- ReactMarker::logTaggedMarkerBridgeless(
222
- ReactMarker::RUN_JS_BUNDLE_START, scriptName.c_str());
223
- }
212
+ runtimeScheduler_->scheduleWork([this,
213
+ scriptName,
214
+ sourceURL,
215
+ buffer = std::move(buffer),
216
+ weakBufferedRuntimeExecuter =
217
+ std::weak_ptr<BufferedRuntimeExecutor>(
218
+ bufferedRuntimeExecutor_),
219
+ completion](jsi::Runtime& runtime) {
220
+ SystraceSection s("ReactInstance::loadScript");
221
+ bool hasLogger(ReactMarker::logTaggedMarkerBridgelessImpl);
222
+ if (hasLogger) {
223
+ ReactMarker::logTaggedMarkerBridgeless(
224
+ ReactMarker::RUN_JS_BUNDLE_START, scriptName.c_str());
225
+ }
224
226
 
225
- runtime.evaluateJavaScript(buffer, sourceURL);
227
+ runtime.evaluateJavaScript(buffer, sourceURL);
226
228
 
227
- /**
228
- * TODO(T183610671): We need a safe/reliable way to enable the js
229
- * pipeline from javascript. Remove this after we figure that out, or
230
- * after we just remove the js pipeline.
231
- */
232
- if (!jsErrorHandler_->hasHandledFatalError()) {
233
- jsErrorHandler_->setRuntimeReady();
234
- }
229
+ /**
230
+ * TODO(T183610671): We need a safe/reliable way to enable the js
231
+ * pipeline from javascript. Remove this after we figure that out, or
232
+ * after we just remove the js pipeline.
233
+ */
234
+ if (!jsErrorHandler_->hasHandledFatalError()) {
235
+ jsErrorHandler_->setRuntimeReady();
236
+ }
235
237
 
236
- if (hasLogger) {
237
- ReactMarker::logTaggedMarkerBridgeless(
238
- ReactMarker::RUN_JS_BUNDLE_STOP, scriptName.c_str());
239
- ReactMarker::logMarkerBridgeless(
240
- ReactMarker::INIT_REACT_RUNTIME_STOP);
241
- ReactMarker::logMarkerBridgeless(ReactMarker::APP_STARTUP_STOP);
242
- }
243
- if (auto strongBufferedRuntimeExecuter =
244
- weakBufferedRuntimeExecuter.lock()) {
245
- strongBufferedRuntimeExecuter->flush();
246
- }
247
- });
238
+ if (hasLogger) {
239
+ ReactMarker::logTaggedMarkerBridgeless(
240
+ ReactMarker::RUN_JS_BUNDLE_STOP, scriptName.c_str());
241
+ ReactMarker::logMarkerBridgeless(ReactMarker::INIT_REACT_RUNTIME_STOP);
242
+ ReactMarker::logMarkerBridgeless(ReactMarker::APP_STARTUP_STOP);
243
+ }
244
+ if (auto strongBufferedRuntimeExecuter =
245
+ weakBufferedRuntimeExecuter.lock()) {
246
+ strongBufferedRuntimeExecuter->flush();
247
+ }
248
+ if (completion) {
249
+ completion(runtime);
250
+ }
251
+ });
248
252
  }
249
253
 
250
254
  /*
@@ -148,17 +148,14 @@ InspectorPackagerConnection::InspectorPackagerConnection(
148
148
  winrt::fire_and_forget InspectorPackagerConnection::disconnectAsync() {
149
149
  co_await winrt::resume_background();
150
150
  std::string reason("Explicit close");
151
- m_packagerWebSocketConnection->Close(
152
- Microsoft::React::Networking::WinRTWebSocketResource::CloseCode::GoingAway, reason);
151
+ m_packagerWebSocketConnection->Close(Microsoft::React::Networking::IWebSocketResource::CloseCode::GoingAway, reason);
153
152
  co_return;
154
153
  }
155
154
 
156
155
  winrt::fire_and_forget InspectorPackagerConnection::connectAsync() {
157
156
  co_await winrt::resume_background();
158
157
 
159
- std::vector<winrt::Windows::Security::Cryptography::Certificates::ChainValidationResult> certExceptions;
160
- m_packagerWebSocketConnection =
161
- std::make_shared<Microsoft::React::Networking::WinRTWebSocketResource>(std::move(certExceptions));
158
+ m_packagerWebSocketConnection = Microsoft::React::Networking::IWebSocketResource::Make();
162
159
 
163
160
  m_packagerWebSocketConnection->SetOnError([](const Microsoft::React::Networking::IWebSocketResource::Error &err) {
164
161
  facebook::react::tracing::error(err.Message.c_str());
@@ -3,7 +3,7 @@
3
3
 
4
4
  #pragma once
5
5
 
6
- #include <Networking/WinRTWebSocketResource.h>
6
+ #include <Networking/IWebSocketResource.h>
7
7
  #include <jsinspector-modern/InspectorInterfaces.h>
8
8
 
9
9
  namespace Microsoft::ReactNative {
@@ -42,7 +42,7 @@ class InspectorPackagerConnection final : public std::enable_shared_from_this<In
42
42
  private:
43
43
  std::unordered_map<int32_t, std::unique_ptr<facebook::react::jsinspector_modern::ILocalConnection>>
44
44
  m_localConnections;
45
- std::shared_ptr<Microsoft::React::Networking::WinRTWebSocketResource> m_packagerWebSocketConnection;
45
+ std::shared_ptr<Microsoft::React::Networking::IWebSocketResource> m_packagerWebSocketConnection;
46
46
  std::shared_ptr<IBundleStatusProvider> m_bundleStatusProvider;
47
47
  std::string m_url;
48
48
  };
@@ -21,16 +21,18 @@
21
21
 
22
22
  using Microsoft::Common::Utilities::CheckedReinterpretCast;
23
23
 
24
+ using Mso::DispatchQueue;
25
+
24
26
  using std::function;
25
27
  using std::lock_guard;
26
28
  using std::mutex;
27
- using std::size_t;
28
29
  using std::string;
29
30
  using std::vector;
30
31
 
31
32
  using winrt::fire_and_forget;
32
33
  using winrt::hresult;
33
34
  using winrt::hresult_error;
35
+ using winrt::hstring;
34
36
  using winrt::resume_background;
35
37
  using winrt::resume_on_signal;
36
38
  using winrt::Windows::Foundation::IAsyncAction;
@@ -38,6 +40,7 @@ using winrt::Windows::Foundation::Uri;
38
40
  using winrt::Windows::Networking::Sockets::IMessageWebSocket;
39
41
  using winrt::Windows::Networking::Sockets::IMessageWebSocketMessageReceivedEventArgs;
40
42
  using winrt::Windows::Networking::Sockets::IWebSocket;
43
+ using winrt::Windows::Networking::Sockets::IWebSocketClosedEventArgs;
41
44
  using winrt::Windows::Networking::Sockets::MessageWebSocket;
42
45
  using winrt::Windows::Networking::Sockets::SocketMessageType;
43
46
  using winrt::Windows::Networking::Sockets::WebSocketClosedEventArgs;
@@ -54,9 +57,9 @@ namespace {
54
57
  ///
55
58
  /// Implements an awaiter for Mso::DispatchQueue
56
59
  ///
57
- auto resume_in_queue(const Mso::DispatchQueue &queue) noexcept {
60
+ auto resume_in_queue(const DispatchQueue &queue) noexcept {
58
61
  struct awaitable {
59
- awaitable(const Mso::DispatchQueue &queue) noexcept : m_queue{queue} {}
62
+ awaitable(const DispatchQueue &queue) noexcept : m_queue{queue} {}
60
63
 
61
64
  bool await_ready() const noexcept {
62
65
  return false;
@@ -79,10 +82,367 @@ auto resume_in_queue(const Mso::DispatchQueue &queue) noexcept {
79
82
  return awaitable{queue};
80
83
  } // resume_in_queue
81
84
 
85
+ DispatchQueue GetCurrentOrSerialQueue() noexcept {
86
+ auto queue = DispatchQueue::CurrentQueue();
87
+ if (!queue)
88
+ queue = DispatchQueue::MakeSerialQueue();
89
+
90
+ return queue;
91
+ }
92
+
82
93
  } // namespace
83
94
 
84
95
  namespace Microsoft::React::Networking {
85
96
 
97
+ #pragma region WinRTWebSocketResource2
98
+
99
+ WinRTWebSocketResource2::WinRTWebSocketResource2(
100
+ IMessageWebSocket &&socket,
101
+ IDataWriter &&writer,
102
+ vector<ChainValidationResult> &&certExceptions,
103
+ DispatchQueue callingQueue)
104
+ : m_socket{std::move(socket)},
105
+ m_writer(std::move(writer)),
106
+ m_readyState{ReadyState::Connecting},
107
+ m_connectPerformed{CreateEvent(/*attributes*/ nullptr, /*manual reset*/ true, /*state*/ false, /*name*/ nullptr)},
108
+ m_callingQueue{callingQueue} {
109
+ for (const auto &certException : certExceptions) {
110
+ m_socket.Control().IgnorableServerCertificateErrors().Append(certException);
111
+ }
112
+ }
113
+
114
+ // private
115
+ WinRTWebSocketResource2::WinRTWebSocketResource2(
116
+ IMessageWebSocket &&socket,
117
+ vector<ChainValidationResult> &&certExceptions)
118
+ : WinRTWebSocketResource2(
119
+ std::move(socket),
120
+ DataWriter{socket.OutputStream()},
121
+ std::move(certExceptions),
122
+ GetCurrentOrSerialQueue()) {}
123
+
124
+ WinRTWebSocketResource2::WinRTWebSocketResource2(vector<ChainValidationResult> &&certExceptions)
125
+ : WinRTWebSocketResource2(MessageWebSocket{}, std::move(certExceptions)) {}
126
+
127
+ WinRTWebSocketResource2::~WinRTWebSocketResource2() noexcept /*override*/
128
+ {}
129
+
130
+ void WinRTWebSocketResource2::Fail(string &&message, ErrorType type) noexcept {
131
+ auto self = shared_from_this();
132
+
133
+ self->m_backgroundQueue.Post([self, message = std::move(message), type]() {
134
+ self->m_readyState = ReadyState::Closed;
135
+ self->m_callingQueue.Post([self, message = std::move(message), type]() {
136
+ if (self->m_errorHandler) {
137
+ self->m_errorHandler({std::move(message), type});
138
+ }
139
+ });
140
+ });
141
+ }
142
+
143
+ void WinRTWebSocketResource2::Fail(hresult &&error, ErrorType type) noexcept {
144
+ Fail(Utilities::HResultToString(std::move(error)), type);
145
+ }
146
+
147
+ void WinRTWebSocketResource2::Fail(hresult_error const &error, ErrorType type) noexcept {
148
+ Fail(Utilities::HResultToString(error), type);
149
+ }
150
+
151
+ void WinRTWebSocketResource2::OnMessageReceived(
152
+ IMessageWebSocket const &,
153
+ IMessageWebSocketMessageReceivedEventArgs const &args) {
154
+ auto self = shared_from_this();
155
+ string response;
156
+
157
+ IDataReader reader{nullptr};
158
+ // Use WinRT ABI to avoid throwing exceptions on expected code paths
159
+ HRESULT hr =
160
+ reinterpret_cast<ABI::Windows::Networking::Sockets::IMessageWebSocketMessageReceivedEventArgs *>(
161
+ winrt::get_abi(args))
162
+ ->GetDataReader(reinterpret_cast<ABI::Windows::Storage::Streams::IDataReader **>(winrt::put_abi(reader)));
163
+
164
+ if (FAILED(hr)) {
165
+ string errorMessage;
166
+ ErrorType errorType;
167
+ // See
168
+ // https://docs.microsoft.com/uwp/api/windows.networking.sockets.messagewebsocketmessagereceivedeventargs.getdatareader?view=winrt-22621#remarks
169
+ if (hr == WININET_E_CONNECTION_ABORTED) {
170
+ errorMessage = "[0x80072EFE] Underlying TCP connection suddenly terminated";
171
+ errorType = ErrorType::Connection;
172
+ // Note: It is not clear whether all read-related errors should close the socket.
173
+ Close(CloseCode::BadPayload, std::move(errorMessage));
174
+ } else {
175
+ errorMessage = Utilities::HResultToString(hr);
176
+ errorType = ErrorType::Receive;
177
+ }
178
+
179
+ self->Fail(std::move(errorMessage), errorType);
180
+
181
+ return;
182
+ }
183
+
184
+ try {
185
+ auto len = reader.UnconsumedBufferLength();
186
+ if (args.MessageType() == SocketMessageType::Utf8) {
187
+ reader.UnicodeEncoding(UnicodeEncoding::Utf8);
188
+ vector<uint8_t> data(len);
189
+ reader.ReadBytes(data);
190
+
191
+ response = string(CheckedReinterpretCast<char *>(data.data()), data.size());
192
+ } else {
193
+ auto buffer = reader.ReadBuffer(len);
194
+ auto data = CryptographicBuffer::EncodeToBase64String(buffer);
195
+
196
+ response = winrt::to_string(std::wstring_view(data));
197
+ }
198
+ } catch (hresult_error const &e) {
199
+ return self->Fail(e, ErrorType::Receive);
200
+ }
201
+
202
+ // Posting inside try-catch block causes errors.
203
+ self->m_callingQueue.Post([self, response = std::move(response), messageType = args.MessageType()]() {
204
+ if (self->m_readHandler) {
205
+ self->m_readHandler(response.length(), response, messageType == SocketMessageType::Binary);
206
+ }
207
+ });
208
+ }
209
+
210
+ void WinRTWebSocketResource2::OnClosed(IWebSocket const &sender, IWebSocketClosedEventArgs const &args) {
211
+ auto self = shared_from_this();
212
+
213
+ self->m_backgroundQueue.Post([self]() { self->m_readyState = ReadyState::Closed; });
214
+
215
+ self->m_callingQueue.Post([self]() {
216
+ if (self->m_closeHandler) {
217
+ self->m_closeHandler(self->m_closeCode, self->m_closeReason);
218
+ }
219
+ });
220
+ }
221
+
222
+ fire_and_forget WinRTWebSocketResource2::PerformConnect(Uri &&uri) noexcept {
223
+ auto self = shared_from_this();
224
+ auto coUri = std::move(uri);
225
+
226
+ co_await resume_in_queue(self->m_backgroundQueue);
227
+
228
+ auto async = self->m_socket.ConnectAsync(coUri);
229
+ co_await lessthrow_await_adapter<IAsyncAction>{async};
230
+
231
+ co_await resume_in_queue(self->m_callingQueue);
232
+
233
+ auto result = async.ErrorCode();
234
+
235
+ try {
236
+ if (result >= 0) { // Non-failing HRESULT
237
+ co_await resume_in_queue(self->m_backgroundQueue);
238
+ self->m_readyState = ReadyState::Open;
239
+
240
+ co_await resume_in_queue(self->m_callingQueue);
241
+ if (self->m_connectHandler) {
242
+ self->m_connectHandler();
243
+ }
244
+ } else {
245
+ self->Fail(std::move(result), ErrorType::Connection);
246
+ }
247
+ } catch (hresult_error const &e) {
248
+ self->Fail(e, ErrorType::Connection);
249
+ } catch (std::exception const &e) {
250
+ self->Fail(e.what(), ErrorType::Connection);
251
+ }
252
+
253
+ SetEvent(self->m_connectPerformed.get());
254
+ }
255
+
256
+ fire_and_forget WinRTWebSocketResource2::PerformClose() noexcept {
257
+ auto self = shared_from_this();
258
+
259
+ co_await resume_on_signal(self->m_connectPerformed.get());
260
+
261
+ co_await resume_in_queue(self->m_backgroundQueue);
262
+
263
+ // See https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close
264
+ co_await self->SendPendingMessages();
265
+
266
+ try {
267
+ self->m_socket.Close(static_cast<uint16_t>(m_closeCode), winrt::to_hstring(m_closeReason));
268
+ self->m_readyState = ReadyState::Closing;
269
+ } catch (winrt::hresult_invalid_argument const &e) {
270
+ Fail(e, ErrorType::Close);
271
+ } catch (hresult_error const &e) {
272
+ Fail(e, ErrorType::Close);
273
+ } catch (const std::exception &e) {
274
+ Fail(e.what(), ErrorType::Close);
275
+ }
276
+ }
277
+
278
+ fire_and_forget WinRTWebSocketResource2::PerformWrite(string &&message, bool isBinary) noexcept {
279
+ auto self = shared_from_this();
280
+ string coMessage = std::move(message);
281
+
282
+ co_await resume_in_queue(self->m_backgroundQueue); // Ensure writes happen sequentially
283
+ self->m_outgoingMessages.emplace(std::move(coMessage), isBinary);
284
+
285
+ co_await resume_on_signal(self->m_connectPerformed.get());
286
+
287
+ co_await resume_in_queue(self->m_backgroundQueue);
288
+
289
+ co_await self->SendPendingMessages();
290
+ }
291
+
292
+ IAsyncAction WinRTWebSocketResource2::SendPendingMessages() noexcept {
293
+ auto self = shared_from_this();
294
+
295
+ while (!self->m_outgoingMessages.empty()) {
296
+ if (self->m_readyState != ReadyState::Open) {
297
+ co_return;
298
+ }
299
+
300
+ size_t length = 0;
301
+ string messageLocal;
302
+ bool isBinaryLocal;
303
+ try {
304
+ std::tie(messageLocal, isBinaryLocal) = self->m_outgoingMessages.front();
305
+ self->m_outgoingMessages.pop();
306
+ if (isBinaryLocal) {
307
+ self->m_socket.Control().MessageType(SocketMessageType::Binary);
308
+
309
+ auto buffer = CryptographicBuffer::DecodeFromBase64String(winrt::to_hstring(messageLocal));
310
+ if (buffer) {
311
+ length = buffer.Length();
312
+ self->m_writer.WriteBuffer(buffer);
313
+ }
314
+ } else {
315
+ self->m_socket.Control().MessageType(SocketMessageType::Utf8);
316
+
317
+ length = messageLocal.size();
318
+ winrt::array_view<const uint8_t> view(
319
+ CheckedReinterpretCast<const uint8_t *>(messageLocal.c_str()),
320
+ CheckedReinterpretCast<const uint8_t *>(messageLocal.c_str()) + messageLocal.length());
321
+ self->m_writer.WriteBytes(view);
322
+ }
323
+ } catch (hresult_error const &e) { // TODO: Remove after fixing unit tests exceptions.
324
+ self->Fail(e, ErrorType::Send);
325
+ co_return;
326
+ } catch (const std::exception &e) {
327
+ self->Fail(e.what(), ErrorType::Send);
328
+ co_return;
329
+ }
330
+
331
+ auto async = self->m_writer.StoreAsync();
332
+ co_await lessthrow_await_adapter<DataWriterStoreOperation>{async};
333
+
334
+ auto result = async.ErrorCode();
335
+ if (result < 0) {
336
+ Fail(std::move(result), ErrorType::Send);
337
+ }
338
+ }
339
+ }
340
+
341
+ #pragma region IWebSocketResource
342
+
343
+ void WinRTWebSocketResource2::Connect(string &&url, const Protocols &protocols, const Options &options) noexcept {
344
+ // Register MessageReceived BEFORE calling Connect
345
+ // https://learn.microsoft.com/en-us/uwp/api/windows.networking.sockets.messagewebsocket.messagereceived?view=winrt-22621
346
+ m_socket.MessageReceived([self = shared_from_this()](
347
+ IMessageWebSocket const &sender, IMessageWebSocketMessageReceivedEventArgs const &args) {
348
+ self->OnMessageReceived(sender, args);
349
+ });
350
+
351
+ m_socket.Closed([self = shared_from_this()](IWebSocket const &sender, IWebSocketClosedEventArgs const &args) {
352
+ self->OnClosed(sender, args);
353
+ });
354
+
355
+ auto supportedProtocols = m_socket.Control().SupportedProtocols();
356
+ for (const auto &protocol : protocols) {
357
+ supportedProtocols.Append(winrt::to_hstring(protocol));
358
+ }
359
+
360
+ Uri uri{nullptr};
361
+ bool hasOriginHeader{false};
362
+ try {
363
+ uri = Uri{winrt::to_hstring(url)};
364
+
365
+ for (const auto &header : options) {
366
+ m_socket.SetRequestHeader(header.first, winrt::to_hstring(header.second));
367
+ if (boost::iequals(header.first, L"Origin")) {
368
+ hasOriginHeader = true;
369
+ }
370
+ }
371
+
372
+ // #12626 - If Origin header is not provided, set to connect endpoint.
373
+ if (!hasOriginHeader) {
374
+ auto scheme = uri.SchemeName();
375
+ auto host = uri.Host();
376
+ auto port = uri.Port();
377
+
378
+ if (scheme == L"ws") {
379
+ scheme = L"http";
380
+ } else if (scheme == L"wss") {
381
+ scheme = L"https";
382
+ }
383
+
384
+ // Only add a port if a port is defined.
385
+ hstring originPort = port != 0 ? L":" + winrt::to_hstring(port) : L"";
386
+ auto origin = hstring{scheme + L"://" + host + originPort};
387
+
388
+ m_socket.SetRequestHeader(L"Origin", std::move(origin));
389
+ }
390
+ } catch (hresult_error const &e) {
391
+ Fail(e, ErrorType::Connection);
392
+
393
+ SetEvent(m_connectPerformed.get());
394
+
395
+ return;
396
+ }
397
+
398
+ PerformConnect(std::move(uri));
399
+ }
400
+
401
+ void WinRTWebSocketResource2::Ping() noexcept {}
402
+
403
+ void WinRTWebSocketResource2::Send(string &&message) noexcept {
404
+ PerformWrite(std::move(message), false);
405
+ }
406
+
407
+ void WinRTWebSocketResource2::SendBinary(string &&base64String) noexcept {
408
+ PerformWrite(std::move(base64String), true);
409
+ }
410
+
411
+ void WinRTWebSocketResource2::Close(CloseCode code, const string &reason) noexcept {
412
+ m_closeCode = code;
413
+ m_closeReason = reason;
414
+ PerformClose();
415
+ }
416
+
417
+ IWebSocketResource::ReadyState WinRTWebSocketResource2::GetReadyState() const noexcept {
418
+ return m_readyState;
419
+ }
420
+
421
+ void WinRTWebSocketResource2::SetOnConnect(function<void()> &&handler) noexcept {
422
+ m_connectHandler = std::move(handler);
423
+ }
424
+
425
+ void WinRTWebSocketResource2::SetOnPing(function<void()> && /*handler*/) noexcept {}
426
+
427
+ void WinRTWebSocketResource2::SetOnSend(function<void(size_t)> && /*handler*/) noexcept {}
428
+
429
+ void WinRTWebSocketResource2::SetOnMessage(function<void(size_t, const string &, bool isBinary)> &&handler) noexcept {
430
+ m_readHandler = std::move(handler);
431
+ }
432
+
433
+ void WinRTWebSocketResource2::SetOnClose(function<void(CloseCode, const string &)> &&handler) noexcept {
434
+ m_closeHandler = std::move(handler);
435
+ }
436
+
437
+ void WinRTWebSocketResource2::SetOnError(function<void(Error &&)> &&handler) noexcept {
438
+ m_errorHandler = std::move(handler);
439
+ }
440
+
441
+ #pragma endregion IWebSocketResource
442
+
443
+ #pragma endregion WinRTWebSocketResource2
444
+
445
+ #pragma region Legacy resource
86
446
  // private
87
447
  WinRTWebSocketResource::WinRTWebSocketResource(
88
448
  IMessageWebSocket &&socket,
@@ -331,7 +691,7 @@ void WinRTWebSocketResource::Connect(string &&url, const Protocols &protocols, c
331
691
  response = string(CheckedReinterpretCast<char *>(data.data()), data.size());
332
692
  } else {
333
693
  auto buffer = reader.ReadBuffer(len);
334
- winrt::hstring data = CryptographicBuffer::EncodeToBase64String(buffer);
694
+ hstring data = CryptographicBuffer::EncodeToBase64String(buffer);
335
695
 
336
696
  response = winrt::to_string(std::wstring_view(data));
337
697
  }
@@ -360,7 +720,7 @@ void WinRTWebSocketResource::Connect(string &&url, const Protocols &protocols, c
360
720
  }
361
721
  }
362
722
 
363
- winrt::Windows::Foundation::Collections::IVector<winrt::hstring> supportedProtocols =
723
+ winrt::Windows::Foundation::Collections::IVector<hstring> supportedProtocols =
364
724
  m_socket.Control().SupportedProtocols();
365
725
  for (const auto &protocol : protocols) {
366
726
  supportedProtocols.Append(winrt::to_hstring(protocol));
@@ -383,8 +743,8 @@ void WinRTWebSocketResource::Connect(string &&url, const Protocols &protocols, c
383
743
  }
384
744
 
385
745
  // Only add a port if a port is defined
386
- winrt::hstring originPort = port != 0 ? L":" + winrt::to_hstring(port) : L"";
387
- auto origin = winrt::hstring{scheme + L"://" + host + originPort};
746
+ hstring originPort = port != 0 ? L":" + winrt::to_hstring(port) : L"";
747
+ auto origin = hstring{scheme + L"://" + host + originPort};
388
748
 
389
749
  m_socket.SetRequestHeader(L"Origin", std::move(origin));
390
750
  }
@@ -461,4 +821,6 @@ void WinRTWebSocketResource::SetOnError(function<void(Error &&)> &&handler) noex
461
821
 
462
822
  #pragma endregion IWebSocketResource
463
823
 
824
+ #pragma endregion Legacy resource
825
+
464
826
  } // namespace Microsoft::React::Networking