react-native-windows 0.80.1 → 0.80.6

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 (74) hide show
  1. package/Directory.Build.props +1 -1
  2. package/Microsoft.ReactNative/Fabric/Composition/DebuggerUIIsland.cpp +169 -0
  3. package/Microsoft.ReactNative/Fabric/Composition/DebuggerUIIsland.h +42 -0
  4. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.cpp +1 -1
  5. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +60 -33
  6. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +68 -1
  7. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +9 -0
  8. package/Microsoft.ReactNative/Fabric/Composition/UriImageManager.cpp +5 -3
  9. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +6 -1
  10. package/Microsoft.ReactNative/Fabric/WindowsImageManager.cpp +14 -1
  11. package/Microsoft.ReactNative/Fabric/platform/react/threading/TaskDispatchThread.cpp +75 -24
  12. package/Microsoft.ReactNative/Fabric/platform/react/threading/TaskDispatchThread.h +4 -25
  13. package/Microsoft.ReactNative/JsiApi.cpp +1 -1
  14. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +1 -0
  15. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters +3 -0
  16. package/Microsoft.ReactNative/ReactHost/DebuggerNotifications.h +54 -0
  17. package/Microsoft.ReactNative/ReactHost/React.h +11 -4
  18. package/Microsoft.ReactNative/ReactHost/ReactHost.cpp +195 -29
  19. package/Microsoft.ReactNative/ReactHost/ReactHost.h +22 -4
  20. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +24 -5
  21. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +1 -1
  22. package/Microsoft.ReactNative/ReactRootView.cpp +108 -0
  23. package/Microsoft.ReactNative/ReactRootView.h +6 -0
  24. package/Microsoft.ReactNative/Views/DevMenu.cpp +1 -1
  25. package/Microsoft.ReactNative.Cxx/JSI/decorator.h +41 -0
  26. package/Microsoft.ReactNative.Cxx/JSI/jsi-inl.h +16 -0
  27. package/Microsoft.ReactNative.Cxx/JSI/jsi.cpp +125 -0
  28. package/Microsoft.ReactNative.Cxx/JSI/jsi.h +167 -1
  29. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +1 -1
  30. package/Microsoft.ReactNative.Cxx/NodeApiJsiRuntime.cpp +110 -38
  31. package/Microsoft.ReactNative.Cxx/node-api/js_native_api.h +44 -31
  32. package/Microsoft.ReactNative.Cxx/node-api/js_native_api_types.h +13 -14
  33. package/Microsoft.ReactNative.Cxx/node-api/js_runtime_api.h +19 -4
  34. package/Microsoft.ReactNative.Cxx/node-api/node_api.h +270 -0
  35. package/Microsoft.ReactNative.Cxx/node-api/node_api_types.h +52 -0
  36. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  37. package/PropertySheets/JSEngine.props +1 -1
  38. package/PropertySheets/React.Cpp.props +2 -2
  39. package/ReactCommon/ReactCommon.vcxproj +18 -1
  40. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/NativeToJsBridge.cpp +1 -1
  41. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsi/jsi/test/testlib.cpp +4 -4
  42. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsinspector-modern/NetworkIOAgent.cpp +23 -9
  43. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsinspector-modern/NetworkIOAgent.h +16 -0
  44. package/ReactCommon/cgmanifest.json +1 -1
  45. package/Scripts/Tfs/Layout-MSRN-Headers.ps1 +2 -0
  46. package/Shared/DevServerHelper.h +13 -3
  47. package/Shared/DevSettings.h +7 -0
  48. package/Shared/DevSupportManager.cpp +79 -20
  49. package/Shared/DevSupportManager.h +7 -19
  50. package/Shared/Hermes/HermesRuntimeAgentDelegate.cpp +99 -0
  51. package/Shared/Hermes/HermesRuntimeAgentDelegate.h +81 -0
  52. package/Shared/Hermes/HermesRuntimeTargetDelegate.cpp +263 -0
  53. package/Shared/Hermes/HermesRuntimeTargetDelegate.h +77 -0
  54. package/Shared/HermesRuntimeHolder.cpp +29 -111
  55. package/Shared/HermesRuntimeHolder.h +214 -32
  56. package/Shared/IDevSupportManager.h +5 -2
  57. package/Shared/Inspector/ReactInspectorPackagerConnectionDelegate.cpp +108 -0
  58. package/Shared/Inspector/ReactInspectorPackagerConnectionDelegate.h +19 -0
  59. package/Shared/Inspector/ReactInspectorThread.h +18 -0
  60. package/Shared/JSI/RuntimeHolder.h +5 -2
  61. package/Shared/OInstance.cpp +44 -27
  62. package/Shared/Shared.vcxitems +27 -17
  63. package/Shared/Shared.vcxitems.filters +33 -15
  64. package/package.json +5 -5
  65. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.cpp +0 -78
  66. package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.h +0 -196
  67. package/ReactCommon/TEMP_UntilReactCommonUpdate/jserrorhandler/JsErrorHandler.cpp +0 -429
  68. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsitooling/react/runtime/JSRuntimeFactory.cpp +0 -45
  69. package/ReactCommon/TEMP_UntilReactCommonUpdate/jsitooling/react/runtime/JSRuntimeFactory.h +0 -91
  70. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/ReactInstance.cpp +0 -670
  71. package/Shared/InspectorPackagerConnection.cpp +0 -232
  72. package/Shared/InspectorPackagerConnection.h +0 -61
  73. /package/Shared/{HermesSamplingProfiler.cpp → Hermes/HermesSamplingProfiler.cpp} +0 -0
  74. /package/Shared/{HermesSamplingProfiler.h → Hermes/HermesSamplingProfiler.h} +0 -0
@@ -3,6 +3,7 @@
3
3
 
4
4
  #pragma once
5
5
 
6
+ #include <jsinspector-modern/HostTarget.h>
6
7
  #include <mutex>
7
8
  #include <unordered_map>
8
9
  #include "AsyncActionQueue.h"
@@ -15,6 +16,7 @@
15
16
 
16
17
  namespace Mso::React {
17
18
 
19
+ class ReactInspectorHostTargetDelegate;
18
20
  class ReactViewHost;
19
21
 
20
22
  //! ReactHost manages lifetime of ReactNative instance.
@@ -52,9 +54,6 @@ class ReactHost final : public Mso::ActiveObject<IReactHost> {
52
54
 
53
55
  Mso::CntPtr<AsyncActionQueue> ActionQueue() const noexcept;
54
56
 
55
- Mso::Future<void> LoadInQueue(ReactOptions &&options) noexcept;
56
- Mso::Future<void> UnloadInQueue(size_t unloadActionId) noexcept;
57
-
58
57
  void Close() noexcept;
59
58
  bool IsClosed() const noexcept;
60
59
 
@@ -64,6 +63,12 @@ class ReactHost final : public Mso::ActiveObject<IReactHost> {
64
63
  template <class TCallback>
65
64
  Mso::Future<void> PostInQueue(TCallback &&callback) noexcept;
66
65
 
66
+ private:
67
+ enum class UnloadReason {
68
+ Unload,
69
+ CloseHost,
70
+ };
71
+
67
72
  private:
68
73
  friend MakePolicy;
69
74
  ReactHost(Mso::DispatchQueue const &queue) noexcept;
@@ -75,9 +80,18 @@ class ReactHost final : public Mso::ActiveObject<IReactHost> {
75
80
  void ForEachViewHost(const Mso::FunctorRef<void(ReactViewHost &)> &action) noexcept;
76
81
 
77
82
  AsyncAction MakeLoadInstanceAction(ReactOptions &&options) noexcept;
78
- AsyncAction MakeUnloadInstanceAction() noexcept;
83
+ AsyncAction MakeUnloadInstanceAction(UnloadReason reason) noexcept;
84
+
85
+ Mso::Future<void> LoadInQueue(ReactOptions &&options) noexcept;
86
+ Mso::Future<void> UnloadInQueue(UnloadReason reason, size_t unloadActionId) noexcept;
87
+
88
+ void OnDebuggerResume() noexcept;
89
+ bool IsInspectable() noexcept;
90
+ void AddInspectorPage() noexcept;
91
+ void RemoveInspectorPage() noexcept;
79
92
 
80
93
  private:
94
+ friend class ReactInspectorHostTargetDelegate;
81
95
  mutable std::mutex m_mutex;
82
96
  const Mso::InvokeElsePostExecutor m_executor{Queue()};
83
97
  const Mso::ActiveReadableField<Mso::CntPtr<AsyncActionQueue>> m_actionQueue{
@@ -92,6 +106,10 @@ class ReactHost final : public Mso::ActiveObject<IReactHost> {
92
106
  size_t m_pendingUnloadActionId{0};
93
107
  size_t m_nextUnloadActionId{0};
94
108
  const Mso::ActiveField<bool> m_isInstanceUnloading{false, Queue()};
109
+
110
+ const std::shared_ptr<facebook::react::jsinspector_modern::HostTargetDelegate> m_inspectorHostTargetDelegate;
111
+ const std::shared_ptr<facebook::react::jsinspector_modern::HostTarget> m_inspectorHostTarget;
112
+ const Mso::ActiveField<std::optional<int32_t>> m_inspectorPageId{Queue()};
95
113
  };
96
114
 
97
115
  //! Implements a cross-platform host for a React view
@@ -66,6 +66,7 @@
66
66
  #include <react/runtime/PlatformTimerRegistry.h>
67
67
  #include <react/runtime/TimerManager.h>
68
68
  #include <react/threading/MessageQueueThreadImpl.h>
69
+ #include "Inspector/ReactInspectorThread.h"
69
70
  #endif
70
71
 
71
72
  #if !defined(CORE_ABI) && !defined(USE_FABRIC)
@@ -553,6 +554,8 @@ std::shared_ptr<facebook::react::DevSettings> ReactInstanceWin::CreateDevSetting
553
554
 
554
555
  devSettings->useRuntimeScheduler = useRuntimeScheduler;
555
556
 
557
+ devSettings->inspectorHostTarget = m_options.InspectorHostTarget;
558
+
556
559
  return devSettings;
557
560
  }
558
561
 
@@ -664,16 +667,21 @@ void ReactInstanceWin::InitializeBridgeless() noexcept {
664
667
  };
665
668
 
666
669
  if (devSettings->useDirectDebugger) {
667
- ::Microsoft::ReactNative::GetSharedDevManager()->EnsureHermesInspector(
668
- devSettings->sourceBundleHost, devSettings->sourceBundlePort);
670
+ ::Microsoft::ReactNative::GetSharedDevManager()->EnsureInspectorPackagerConnection(
671
+ devSettings->sourceBundleHost, devSettings->sourceBundlePort, devSettings->bundleAppId);
669
672
  }
670
673
 
671
674
  m_jsiRuntimeHolder = std::make_shared<Microsoft::ReactNative::HermesRuntimeHolder>(
672
675
  devSettings, jsMessageThread, CreatePreparedScriptStore());
673
676
  auto jsRuntime = std::make_unique<Microsoft::ReactNative::HermesJSRuntime>(m_jsiRuntimeHolder);
674
677
  jsRuntime->getRuntime();
675
- m_bridgelessReactInstance = std::make_unique<facebook::react::ReactInstance>(
676
- std::move(jsRuntime), jsMessageThread, timerManager, jsErrorHandlingFunc);
678
+
679
+ m_bridgelessReactInstance = std::make_shared<facebook::react::ReactInstance>(
680
+ std::move(jsRuntime),
681
+ jsMessageThread,
682
+ timerManager,
683
+ jsErrorHandlingFunc,
684
+ m_options.InspectorHostTarget);
677
685
 
678
686
  auto bufferedRuntimeExecutor = m_bridgelessReactInstance->getBufferedRuntimeExecutor();
679
687
  timerManager->setRuntimeExecutor(bufferedRuntimeExecutor);
@@ -695,6 +703,7 @@ void ReactInstanceWin::InitializeBridgeless() noexcept {
695
703
  winrt::make<implementation::ReactContext>(Mso::Copy(m_reactContext)));
696
704
 
697
705
  facebook::react::ReactInstance::JSRuntimeFlags options;
706
+
698
707
  m_bridgelessReactInstance->initializeRuntime(
699
708
  options,
700
709
  [=, onCreated = m_options.OnInstanceCreated, reactContext = m_reactContext](
@@ -748,7 +757,6 @@ void ReactInstanceWin::InitializeBridgeless() noexcept {
748
757
 
749
758
  LoadJSBundlesBridgeless(devSettings);
750
759
  SetupHMRClient();
751
-
752
760
  } catch (std::exception &e) {
753
761
  OnErrorWithMessage(e.what());
754
762
  OnErrorWithMessage("ReactInstanceWin: Failed to create React Instance.");
@@ -1092,6 +1100,17 @@ Mso::Future<void> ReactInstanceWin::Destroy() noexcept {
1092
1100
  if (m_bridgelessReactInstance) {
1093
1101
  if (auto jsMessageThread = m_jsMessageThread.Exchange(nullptr)) {
1094
1102
  jsMessageThread->runOnQueueSync([&]() noexcept {
1103
+ // Unregister from inspector BEFORE shutting down JS thread
1104
+ if (m_bridgelessReactInstance && m_options.InspectorHostTarget) {
1105
+ Mso::React::MessageDispatchQueue messageDispatchQueue{
1106
+ ::Microsoft::ReactNative::ReactInspectorThread::Instance(), nullptr};
1107
+ messageDispatchQueue.runOnQueueSync(
1108
+ [weakBridgelessReactInstance = std::weak_ptr(m_bridgelessReactInstance)]() {
1109
+ if (auto bridgelessReactInstance = weakBridgelessReactInstance.lock()) {
1110
+ bridgelessReactInstance->unregisterFromInspector();
1111
+ }
1112
+ });
1113
+ }
1095
1114
  {
1096
1115
  // Release the JSI runtime
1097
1116
  std::scoped_lock lock{m_mutex};
@@ -205,7 +205,7 @@ class ReactInstanceWin final : public Mso::ActiveObject<IReactInstanceInternal>
205
205
 
206
206
  #ifdef USE_FABRIC
207
207
  // Bridgeless
208
- std::unique_ptr<facebook::react::ReactInstance> m_bridgelessReactInstance;
208
+ std::shared_ptr<facebook::react::ReactInstance> m_bridgelessReactInstance;
209
209
  #endif
210
210
 
211
211
  std::atomic<ReactInstanceState> m_state{ReactInstanceState::Loading};
@@ -5,14 +5,19 @@
5
5
  #include "ReactRootView.g.cpp"
6
6
 
7
7
  #include <QuirkSettings.h>
8
+ #include <ReactHost/DebuggerNotifications.h>
8
9
  #include <ReactHost/MsoUtils.h>
10
+ #include <UI.Text.h>
11
+ #include <UI.Xaml.Controls.Primitives.h>
9
12
  #include <UI.Xaml.Input.h>
10
13
  #include <UI.Xaml.Media.Media3D.h>
11
14
  #include <Utils/Helpers.h>
12
15
  #include <dispatchQueue/dispatchQueue.h>
13
16
  #include <winrt/Windows.UI.Core.h>
17
+ #include "InstanceManager.h"
14
18
  #include "ReactNativeHost.h"
15
19
  #include "ReactViewInstance.h"
20
+ #include "Utils/KeyboardUtils.h"
16
21
  #include "XamlUtils.h"
17
22
 
18
23
  #include <winrt/Microsoft.UI.Xaml.Controls.h>
@@ -34,6 +39,7 @@ ReactRootView::ReactRootView() noexcept : m_uiQueue(Mso::DispatchQueue::GetCurre
34
39
  UpdatePerspective();
35
40
  Loaded([this](auto &&, auto &&) {
36
41
  ::Microsoft::ReactNative::SetCompositor(::Microsoft::ReactNative::GetCompositor(*this));
42
+ SetupDevToolsShortcut();
37
43
  });
38
44
  }
39
45
 
@@ -45,6 +51,20 @@ void ReactRootView::ReactNativeHost(ReactNative::ReactNativeHost const &value) n
45
51
  if (m_reactNativeHost != value) {
46
52
  ReactViewHost(nullptr);
47
53
  m_reactNativeHost = value;
54
+ const auto weakThis = this->get_weak();
55
+ ::Microsoft::ReactNative::DebuggerNotifications::SubscribeShowDebuggerPausedOverlay(
56
+ m_reactNativeHost.InstanceSettings().Notifications(),
57
+ m_reactNativeHost.InstanceSettings().UIDispatcher(),
58
+ [weakThis](std::string message, std::function<void()> onResume) {
59
+ if (auto strongThis = weakThis.get()) {
60
+ strongThis->ShowDebuggerPausedOverlay(message, onResume);
61
+ }
62
+ },
63
+ [weakThis]() {
64
+ if (auto strongThis = weakThis.get()) {
65
+ strongThis->HideDebuggerPausedOverlay();
66
+ }
67
+ });
48
68
  ReloadView();
49
69
  }
50
70
  }
@@ -283,6 +303,65 @@ void ReactRootView::EnsureLoadingUI() noexcept {
283
303
  }
284
304
  }
285
305
 
306
+ void ReactRootView::HideDebuggerPausedOverlay() noexcept {
307
+ m_isDebuggerPausedOverlayOpen = false;
308
+ if (m_debuggerPausedFlyout) {
309
+ m_debuggerPausedFlyout.Hide();
310
+ m_debuggerPausedFlyout = nullptr;
311
+ }
312
+ }
313
+
314
+ void ReactRootView::ShowDebuggerPausedOverlay(
315
+ const std::string &message,
316
+ const std::function<void()> &onResume) noexcept {
317
+ // Initialize content
318
+ const xaml::Controls::Grid contentGrid;
319
+ xaml::Controls::ColumnDefinition messageColumnDefinition;
320
+ xaml::Controls::ColumnDefinition buttonColumnDefinition;
321
+ messageColumnDefinition.MinWidth(60);
322
+ buttonColumnDefinition.MinWidth(36);
323
+ contentGrid.ColumnDefinitions().Append(messageColumnDefinition);
324
+ contentGrid.ColumnDefinitions().Append(buttonColumnDefinition);
325
+ xaml::Controls::TextBlock messageBlock;
326
+ messageBlock.Text(winrt::to_hstring(message));
327
+ messageBlock.FontWeight(winrt::Windows::UI::Text::FontWeights::SemiBold());
328
+ xaml::Controls::FontIcon resumeGlyph;
329
+ resumeGlyph.FontFamily(xaml::Media::FontFamily(L"Segoe MDL2 Assets"));
330
+ resumeGlyph.Foreground(xaml::Media::SolidColorBrush(winrt::Colors::Green()));
331
+ resumeGlyph.Glyph(L"\uF5B0");
332
+ resumeGlyph.HorizontalAlignment(xaml::HorizontalAlignment::Right);
333
+ resumeGlyph.PointerReleased([onResume](auto &&...) { onResume(); });
334
+ xaml::Controls::Grid::SetColumn(resumeGlyph, 1);
335
+ contentGrid.Children().Append(messageBlock);
336
+ contentGrid.Children().Append(resumeGlyph);
337
+
338
+ // Configure flyout
339
+ m_isDebuggerPausedOverlayOpen = true;
340
+ xaml::Style flyoutStyle(
341
+ {XAML_NAMESPACE_STR L".Controls.FlyoutPresenter", winrt::Windows::UI::Xaml::Interop::TypeKind::Metadata});
342
+ flyoutStyle.Setters().Append(winrt::Setter(
343
+ xaml::Controls::Control::CornerRadiusProperty(), winrt::box_value(xaml::CornerRadius{12, 12, 12, 12})));
344
+ flyoutStyle.Setters().Append(winrt::Setter(
345
+ xaml::Controls::Control::BackgroundProperty(),
346
+ winrt::box_value(xaml::Media::SolidColorBrush{FromArgb(255, 255, 255, 193)})));
347
+ flyoutStyle.Setters().Append(
348
+ winrt::Setter(xaml::FrameworkElement::MarginProperty(), winrt::box_value(xaml::Thickness{0, 12, 0, 0})));
349
+ m_debuggerPausedFlyout = xaml::Controls::Flyout{};
350
+ m_debuggerPausedFlyout.FlyoutPresenterStyle(flyoutStyle);
351
+ m_debuggerPausedFlyout.LightDismissOverlayMode(xaml::Controls::LightDismissOverlayMode::On);
352
+ m_debuggerPausedFlyout.Content(contentGrid);
353
+
354
+ // Disable light dismiss
355
+ m_debuggerPausedFlyout.Closing([weakThis = this->get_weak()](auto &&, const auto &args) {
356
+ if (auto strongThis = weakThis.get()) {
357
+ args.Cancel(strongThis->m_isDebuggerPausedOverlayOpen);
358
+ }
359
+ });
360
+
361
+ // Show flyout
362
+ m_debuggerPausedFlyout.ShowAt(*this);
363
+ }
364
+
286
365
  void ReactRootView::ShowInstanceLoaded() noexcept {
287
366
  if (m_xamlRootView) {
288
367
  ClearLoadingUI();
@@ -481,4 +560,33 @@ void ReactRootView::RemoveChildAt(uint32_t index) {
481
560
  Children().RemoveAt(RNIndexToXamlIndex(index));
482
561
  }
483
562
 
563
+ bool IsCtrlShiftI(winrt::Windows::System::VirtualKey key) noexcept {
564
+ return (
565
+ key == winrt::Windows::System::VirtualKey::I &&
566
+ ::Microsoft::ReactNative::IsModifiedKeyPressed(
567
+ winrt::CoreWindow::GetForCurrentThread(), winrt::Windows::System::VirtualKey::Shift) &&
568
+ ::Microsoft::ReactNative::IsModifiedKeyPressed(
569
+ winrt::CoreWindow::GetForCurrentThread(), winrt::Windows::System::VirtualKey::Control));
570
+ }
571
+
572
+ void ReactRootView::SetupDevToolsShortcut() noexcept {
573
+ if (auto xamlRoot = XamlRoot()) {
574
+ if (std::find(m_subscribedDebuggerRoots.begin(), m_subscribedDebuggerRoots.end(), xamlRoot) ==
575
+ m_subscribedDebuggerRoots.end()) {
576
+ if (auto rootContent = xamlRoot.Content()) {
577
+ m_subscribedDebuggerRoots.push_back(xamlRoot);
578
+ rootContent.KeyDown(
579
+ [weakThis = this->get_weak()](const auto & /*sender*/, const xaml::Input::KeyRoutedEventArgs &args) {
580
+ if (const auto strongThis = weakThis.get()) {
581
+ if (IsCtrlShiftI(args.Key())) {
582
+ ::Microsoft::ReactNative::GetSharedDevManager()->OpenDevTools(
583
+ winrt::to_string(strongThis->m_reactNativeHost.InstanceSettings().BundleAppId()));
584
+ }
585
+ };
586
+ });
587
+ }
588
+ }
589
+ }
590
+ }
591
+
484
592
  } // namespace winrt::Microsoft::ReactNative::implementation
@@ -72,6 +72,7 @@ struct ReactRootView : ReactRootViewT<ReactRootView>, ::Microsoft::ReactNative::
72
72
  bool m_isPerspectiveEnabled{true};
73
73
  bool m_isInitialized{false};
74
74
  bool m_isJSViewAttached{false};
75
+ bool m_isDebuggerPausedOverlayOpen{false};
75
76
  Mso::DispatchQueue m_uiQueue;
76
77
  int64_t m_rootTag{-1};
77
78
  std::unique_ptr<Mso::React::ReactOptions> m_reactOptions;
@@ -84,9 +85,11 @@ struct ReactRootView : ReactRootViewT<ReactRootView>, ::Microsoft::ReactNative::
84
85
  std::shared_ptr<::Microsoft::ReactNative::PreviewKeyboardEventHandlerOnRoot> m_previewKeyboardEventHandlerOnRoot;
85
86
  xaml::Controls::ContentControl m_focusSafeHarbor{nullptr};
86
87
  xaml::Controls::ContentControl::LosingFocus_revoker m_focusSafeHarborLosingFocusRevoker{};
88
+ xaml::Controls::Flyout m_debuggerPausedFlyout{nullptr};
87
89
  winrt::Grid m_greenBoxGrid{nullptr};
88
90
  winrt::TextBlock m_waitingTextBlock{nullptr};
89
91
  winrt::SystemNavigationManager::BackRequested_revoker m_backRequestedRevoker{};
92
+ std::vector<xaml::XamlRoot> m_subscribedDebuggerRoots{};
90
93
 
91
94
  // Visual tree to support safe harbor
92
95
  // this
@@ -102,6 +105,8 @@ struct ReactRootView : ReactRootViewT<ReactRootView>, ::Microsoft::ReactNative::
102
105
  void UpdateRootViewInternal() noexcept;
103
106
  void ClearLoadingUI() noexcept;
104
107
  void EnsureLoadingUI() noexcept;
108
+ void HideDebuggerPausedOverlay() noexcept;
109
+ void ShowDebuggerPausedOverlay(const std::string &message, const std::function<void()> &onResume) noexcept;
105
110
  void ShowInstanceLoaded() noexcept;
106
111
  void ShowInstanceError() noexcept;
107
112
  void ShowInstanceWaiting() noexcept;
@@ -112,6 +117,7 @@ struct ReactRootView : ReactRootViewT<ReactRootView>, ::Microsoft::ReactNative::
112
117
  bool OnBackRequested() noexcept;
113
118
  Mso::React::IReactViewHost *ReactViewHost() noexcept;
114
119
  void ReactViewHost(Mso::React::IReactViewHost *viewHost) noexcept;
120
+ void SetupDevToolsShortcut() noexcept;
115
121
  };
116
122
 
117
123
  } // namespace winrt::Microsoft::ReactNative::implementation
@@ -6,7 +6,7 @@
6
6
  #include "DevMenu.h"
7
7
 
8
8
  #include <winrt/Windows.ApplicationModel.DataTransfer.h>
9
- #include "HermesSamplingProfiler.h"
9
+ #include "Hermes/HermesSamplingProfiler.h"
10
10
  #include "IReactDispatcher.h"
11
11
  #include "Modules/DevSettingsModule.h"
12
12
 
@@ -112,6 +112,12 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
112
112
  return plain_;
113
113
  }
114
114
 
115
+ #if JSI_VERSION >= 20
116
+ ICast* castInterface(const UUID& interfaceUUID) override {
117
+ return plain().castInterface(interfaceUUID);
118
+ }
119
+ #endif
120
+
115
121
  Value evaluateJavaScript(
116
122
  const std::shared_ptr<const Buffer>& buffer,
117
123
  const std::string& sourceURL) override {
@@ -423,6 +429,19 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation {
423
429
  return plain_.callAsConstructor(f, args, count);
424
430
  };
425
431
 
432
+ #if JSI_VERSION >= 20
433
+ void setRuntimeDataImpl(
434
+ const UUID& uuid,
435
+ const void* data,
436
+ void (*deleter)(const void* data)) override {
437
+ return plain_.setRuntimeDataImpl(uuid, data, deleter);
438
+ }
439
+
440
+ const void* getRuntimeDataImpl(const UUID& uuid) override {
441
+ return plain_.getRuntimeDataImpl(uuid);
442
+ }
443
+ #endif
444
+
426
445
  // Private data for managing scopes.
427
446
  Runtime::ScopeState* pushScope() override {
428
447
  return plain_.pushScope();
@@ -620,6 +639,13 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
620
639
  // the derived class.
621
640
  WithRuntimeDecorator(Plain& plain, With& with) : RD(plain), with_(with) {}
622
641
 
642
+ #if JSI_VERSION >= 20
643
+ ICast* castInterface(const UUID& interfaceUUID) override {
644
+ Around around{with_};
645
+ return RD::castInterface(interfaceUUID);
646
+ }
647
+ #endif
648
+
623
649
  Value evaluateJavaScript(
624
650
  const std::shared_ptr<const Buffer>& buffer,
625
651
  const std::string& sourceURL) override {
@@ -1034,6 +1060,21 @@ class WithRuntimeDecorator : public RuntimeDecorator<Plain, Base> {
1034
1060
  };
1035
1061
  #endif
1036
1062
 
1063
+ #if JSI_VERSION >= 20
1064
+ void setRuntimeDataImpl(
1065
+ const UUID& uuid,
1066
+ const void* data,
1067
+ void (*deleter)(const void* data)) override {
1068
+ Around around{with_};
1069
+ RD::setRuntimeDataImpl(uuid, data, deleter);
1070
+ }
1071
+
1072
+ const void* getRuntimeDataImpl(const UUID& uuid) override {
1073
+ Around around{with_};
1074
+ return RD::getRuntimeDataImpl(uuid);
1075
+ }
1076
+ #endif
1077
+
1037
1078
  private:
1038
1079
  // Wrap an RAII type around With& to guarantee after always happens.
1039
1080
  struct Around {
@@ -86,6 +86,22 @@ inline const Runtime::PointerValue* Runtime::getPointerValue(
86
86
  return value.data_.pointer.ptr_;
87
87
  }
88
88
 
89
+ #if JSI_VERSION >= 20
90
+ inline void Runtime::setRuntimeData(
91
+ const UUID& uuid,
92
+ const std::shared_ptr<void>& data) {
93
+ auto* dataPtr = new std::shared_ptr<void>(data);
94
+ setRuntimeDataImpl(uuid, dataPtr, [](const void* data) {
95
+ delete (const std::shared_ptr<void>*)data;
96
+ });
97
+ }
98
+
99
+ inline std::shared_ptr<void> Runtime::getRuntimeData(const UUID& uuid) {
100
+ auto* data = (const std::shared_ptr<void>*)getRuntimeDataImpl(uuid);
101
+ return data ? *data : nullptr;
102
+ }
103
+ #endif
104
+
89
105
  #if JSI_VERSION >= 17
90
106
  Value Object::getPrototype(Runtime& runtime) const {
91
107
  return runtime.getPrototypeOf(*this);
@@ -8,6 +8,8 @@
8
8
  #include <cassert>
9
9
  #include <cmath>
10
10
  #include <cstdlib>
11
+ #include <map>
12
+ #include <mutex>
11
13
  #include <stdexcept>
12
14
 
13
15
  #include <jsi/instrumentation.h>
@@ -18,6 +20,65 @@ namespace jsi {
18
20
 
19
21
  namespace {
20
22
 
23
+ #if JSI_VERSION >= 20
24
+ /// A global map used to store custom runtime data for VMs that do not provide
25
+ /// their own default implementation of setRuntimeData and getRuntimeData.
26
+ struct RuntimeDataGlobal {
27
+ /// Mutex protecting the Runtime data map
28
+ std::mutex mutex_{};
29
+ /// Maps a runtime pointer to a map of its custom data. At destruction of the
30
+ /// runtime, its entry will be removed from the global map.
31
+ std::unordered_map<
32
+ Runtime*,
33
+ std::unordered_map<
34
+ UUID,
35
+ std::pair<const void*, void (*)(const void* data)>,
36
+ UUID::Hash>>
37
+ dataMap_;
38
+ };
39
+
40
+ RuntimeDataGlobal& getRuntimeDataGlobal() {
41
+ static RuntimeDataGlobal runtimeData{};
42
+ return runtimeData;
43
+ }
44
+
45
+ /// A host object that, when destructed, will remove the runtime's custom data
46
+ /// entry from the global map of custom data.
47
+ class RemoveRuntimeDataHostObject : public jsi::HostObject {
48
+ public:
49
+ explicit RemoveRuntimeDataHostObject(Runtime* runtime) : runtime_(runtime) {}
50
+
51
+ RemoveRuntimeDataHostObject(const RemoveRuntimeDataHostObject&) = default;
52
+ RemoveRuntimeDataHostObject(RemoveRuntimeDataHostObject&&) = default;
53
+ RemoveRuntimeDataHostObject& operator=(const RemoveRuntimeDataHostObject&) =
54
+ default;
55
+ RemoveRuntimeDataHostObject& operator=(RemoveRuntimeDataHostObject&&) =
56
+ default;
57
+
58
+ ~RemoveRuntimeDataHostObject() override {
59
+ auto& runtimeDataGlobal = getRuntimeDataGlobal();
60
+ std::lock_guard<std::mutex> lock(runtimeDataGlobal.mutex_);
61
+ auto runtimeMapIt = runtimeDataGlobal.dataMap_.find(runtime_);
62
+ // We install the RemoveRuntimeDataHostObject only when the first custom
63
+ // data for the runtime is added, and only this object is responsible for
64
+ // clearing runtime data. Thus, we should always be able to find the data
65
+ // entry.
66
+ assert(
67
+ runtimeMapIt != runtimeDataGlobal.dataMap_.end() &&
68
+ "Custom runtime data not found for this runtime");
69
+
70
+ for (auto [_, entry] : runtimeMapIt->second) {
71
+ auto* deleter = entry.second;
72
+ deleter(entry.first);
73
+ }
74
+ runtimeDataGlobal.dataMap_.erase(runtime_);
75
+ }
76
+
77
+ private:
78
+ Runtime* runtime_;
79
+ };
80
+ #endif
81
+
21
82
  // This is used for generating short exception strings.
22
83
  std::string kindToString(const Value& v, Runtime* rt = nullptr) {
23
84
  if (v.isUndefined()) {
@@ -237,6 +298,12 @@ NativeState::~NativeState() {}
237
298
 
238
299
  Runtime::~Runtime() {}
239
300
 
301
+ #if JSI_VERSION >= 20
302
+ ICast* Runtime::castInterface(const UUID& /*interfaceUUID*/) {
303
+ return nullptr;
304
+ }
305
+ #endif
306
+
240
307
  Instrumentation& Runtime::instrumentation() {
241
308
  class NoInstrumentation : public Instrumentation {
242
309
  std::string getRecordedGCStats() override {
@@ -398,6 +465,64 @@ Object Runtime::createObjectWithPrototype(const Value& prototype) {
398
465
  }
399
466
  #endif
400
467
 
468
+ #if JSI_VERSION >= 20
469
+ void Runtime::setRuntimeDataImpl(
470
+ const UUID& uuid,
471
+ const void* data,
472
+ void (*deleter)(const void* data)) {
473
+ auto& runtimeDataGlobal = getRuntimeDataGlobal();
474
+ std::lock_guard<std::mutex> lock(runtimeDataGlobal.mutex_);
475
+ if (auto it = runtimeDataGlobal.dataMap_.find(this);
476
+ it != runtimeDataGlobal.dataMap_.end()) {
477
+ auto& map = it->second;
478
+ if (auto entryIt = map.find(uuid); entryIt != map.end()) {
479
+ // Free the old data
480
+ auto oldData = entryIt->second.first;
481
+ auto oldDataDeleter = entryIt->second.second;
482
+ oldDataDeleter(oldData);
483
+ }
484
+ map[uuid] = {data, deleter};
485
+ return;
486
+ }
487
+ // No custom data entry exist for this runtime in the global map, so create
488
+ // one.
489
+ runtimeDataGlobal.dataMap_[this][uuid] = {data, deleter};
490
+
491
+ // The first time data is added for this runtime is added to the map, install
492
+ // a host object on the global object of the runtime. This host object is used
493
+ // to release the runtime's entry from the global custom data map when the
494
+ // runtime is destroyed.
495
+ // Also, try to protect the host object by making it non-configurable,
496
+ // non-enumerable, and non-writable. These JSI operations are purposely
497
+ // performed after runtime-specific data map is added and the host object is
498
+ // created to prevent data leaks if any operations fail.
499
+ Object ho = Object::createFromHostObject(
500
+ *this, std::make_shared<RemoveRuntimeDataHostObject>(this));
501
+ global().setProperty(*this, "_jsiRuntimeDataCleanUp", ho);
502
+ auto definePropertyFn = global()
503
+ .getPropertyAsObject(*this, "Object")
504
+ .getPropertyAsFunction(*this, "defineProperty");
505
+ auto desc = Object(*this);
506
+ desc.setProperty(*this, "configurable", Value(false));
507
+ desc.setProperty(*this, "enumerable", Value(false));
508
+ desc.setProperty(*this, "writable", Value(false));
509
+ definePropertyFn.call(*this, global(), "_jsiRuntimeDataCleanUp", desc);
510
+ }
511
+
512
+ const void* Runtime::getRuntimeDataImpl(const UUID& uuid) {
513
+ auto& runtimeDataGlobal = getRuntimeDataGlobal();
514
+ std::lock_guard<std::mutex> lock(runtimeDataGlobal.mutex_);
515
+ if (auto runtimeMapIt = runtimeDataGlobal.dataMap_.find(this);
516
+ runtimeMapIt != runtimeDataGlobal.dataMap_.end()) {
517
+ if (auto customDataIt = runtimeMapIt->second.find(uuid);
518
+ customDataIt != runtimeMapIt->second.end()) {
519
+ return customDataIt->second.first;
520
+ }
521
+ }
522
+ return nullptr;
523
+ }
524
+ #endif
525
+
401
526
  Pointer& Pointer::operator=(Pointer&& other) JSI_NOEXCEPT_15 {
402
527
  if (ptr_) {
403
528
  ptr_->invalidate();