Skip to content

Commit 268aaf7

Browse files
committed
Add HostTarget to CDP registry
Wires up the HostTarget in ReactNativeHost for react-native-windows. This code will only run if InspectorFlags::getEnableModernCDPRegistry() returns true.
1 parent 8f380f8 commit 268aaf7

File tree

6 files changed

+150
-0
lines changed

6 files changed

+150
-0
lines changed

vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@
281281
<SubType>Code</SubType>
282282
</ClInclude>
283283
<ClInclude Include="ReactHost\AsyncActionQueue.h" />
284+
<ClInclude Include="ReactHost\DebuggerNotifications.h" />
284285
<ClInclude Include="ReactHost\InstanceFactory.h" />
285286
<ClInclude Include="ReactHost\IReactInstanceInternal.h" />
286287
<ClInclude Include="ReactHost\JSBundle.h" />

vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@
313313
<ClInclude Include="ReactHost\AsyncActionQueue.h">
314314
<Filter>ReactHost</Filter>
315315
</ClInclude>
316+
<ClInclude Include="ReactHost\DebuggerNotifications.h">
317+
<Filter>ReactHost</Filter>
318+
</ClInclude>
316319
<ClInclude Include="ReactHost\InstanceFactory.h">
317320
<Filter>ReactHost</Filter>
318321
</ClInclude>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
#pragma once
5+
6+
#include <winrt/Microsoft.ReactNative.h>
7+
8+
namespace Microsoft::ReactNative {
9+
10+
struct DebuggerNotifications {
11+
static winrt::Microsoft::ReactNative::IReactPropertyName ShowDebuggerPausedOverlayEventName() noexcept {
12+
static winrt::Microsoft::ReactNative::IReactPropertyName propertyName{
13+
winrt::Microsoft::ReactNative::ReactPropertyBagHelper::GetName(
14+
winrt::Microsoft::ReactNative::ReactPropertyBagHelper::GetNamespace(L"ReactNative.Debugger"),
15+
L"ShowDebuggerPausedOverlay")};
16+
return propertyName;
17+
}
18+
19+
static void OnShowDebuggerPausedOverlay(
20+
winrt::Microsoft::ReactNative::IReactNotificationService const &service,
21+
std::string message,
22+
std::function<void()> onResume) {
23+
const winrt::Microsoft::ReactNative::ReactNonAbiValue<std::tuple<std::string, std::function<void()>>> nonAbiValue{
24+
std::in_place, std::tie(message, onResume)};
25+
service.SendNotification(ShowDebuggerPausedOverlayEventName(), nullptr, nonAbiValue);
26+
}
27+
28+
static void OnHideDebuggerPausedOverlay(winrt::Microsoft::ReactNative::IReactNotificationService const &service) {
29+
service.SendNotification(ShowDebuggerPausedOverlayEventName(), nullptr, nullptr);
30+
}
31+
32+
static winrt::Microsoft::ReactNative::IReactNotificationSubscription SubscribeShowDebuggerPausedOverlay(
33+
winrt::Microsoft::ReactNative::IReactNotificationService const &service,
34+
winrt::Microsoft::ReactNative::IReactDispatcher const &dispatcher,
35+
std::function<void(std::string, std::function<void()>)> showCallback,
36+
std::function<void()> hideCallback) {
37+
return service.Subscribe(
38+
ShowDebuggerPausedOverlayEventName(),
39+
dispatcher,
40+
[showCallback, hideCallback](auto &&, winrt::Microsoft::ReactNative::IReactNotificationArgs const &args) {
41+
if (args.Data()) {
42+
const auto [message, onResume] = args.Data()
43+
.as<winrt::Microsoft::ReactNative::ReactNonAbiValue<
44+
std::tuple<std::string, std::function<void()>>>>()
45+
.Value();
46+
showCallback(message, onResume);
47+
} else {
48+
hideCallback();
49+
}
50+
});
51+
}
52+
};
53+
54+
} // namespace Microsoft::ReactNative

vnext/Microsoft.ReactNative/ReactNativeHost.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
#include "TurboModulesProvider.h"
1111

1212
#include <future/futureWinRT.h>
13+
#include <jsinspector-modern/InspectorFlags.h>
1314
#include <winrt/Windows.Foundation.Collections.h>
1415
#include "IReactContext.h"
16+
#include "ReactHost/DebuggerNotifications.h"
1517
#include "ReactInstanceSettings.h"
1618

1719
#ifdef USE_FABRIC
@@ -30,13 +32,86 @@ using namespace xaml::Controls;
3032

3133
namespace winrt::Microsoft::ReactNative::implementation {
3234

35+
class FuseboxHostTargetDelegate : public facebook::react::jsinspector_modern::HostTargetDelegate,
36+
public std::enable_shared_from_this<FuseboxHostTargetDelegate> {
37+
public:
38+
FuseboxHostTargetDelegate(ReactNativeHost *reactNativeHost) : m_reactNativeHost(reactNativeHost) {}
39+
40+
void onReload(facebook::react::jsinspector_modern::HostTargetDelegate::PageReloadRequest const &request) override {
41+
m_reactNativeHost->ReloadInstance();
42+
}
43+
44+
#ifdef HAS_FUSEBOX_PAUSED_OVERLAY // Remove after syncing past https://github.com/facebook/react-native/pull/44078
45+
void onSetPausedInDebuggerMessage(
46+
facebook::react::jsinspector_modern::HostTargetDelegate::OverlaySetPausedInDebuggerMessageRequest const &request)
47+
override {
48+
const auto instanceSettings = m_reactNativeHost->InstanceSettings();
49+
if (instanceSettings) {
50+
if (request.message.has_value()) {
51+
::Microsoft::ReactNative::DebuggerNotifications::OnShowDebuggerPausedOverlay(
52+
instanceSettings.Notifications(), request.message.value(), [weakThis = weak_from_this()]() {
53+
if (auto strongThis = weakThis.lock()) {
54+
strongThis->m_reactNativeHost->OnDebuggerResume();
55+
}
56+
});
57+
} else {
58+
::Microsoft::ReactNative::DebuggerNotifications::OnHideDebuggerPausedOverlay(instanceSettings.Notifications());
59+
}
60+
}
61+
}
62+
#endif
63+
64+
private:
65+
ReactNativeHost *m_reactNativeHost;
66+
};
67+
3368
ReactNativeHost::ReactNativeHost() noexcept : m_reactHost{Mso::React::MakeReactHost()} {
3469
#if _DEBUG
3570
facebook::react::InitializeLogging([](facebook::react::RCTLogLevel /*logLevel*/, const char *message) {
3671
std::string str = std::string("ReactNative:") + message;
3772
OutputDebugStringA(str.c_str());
3873
});
3974
#endif
75+
76+
auto &inspectorFlags = facebook::react::jsinspector_modern::InspectorFlags::getInstance();
77+
if (inspectorFlags.getEnableModernCDPRegistry() && !m_inspectorPageId.has_value()) {
78+
m_inspectorThread = std::make_shared<Mso::DispatchQueue>(Mso::DispatchQueue::MakeLooperQueue());
79+
m_inspectorHostDelegate = std::make_shared<FuseboxHostTargetDelegate>(this);
80+
m_inspectorTarget = facebook::react::jsinspector_modern::HostTarget::create(
81+
*m_inspectorHostDelegate, [inspectorThread = m_inspectorThread](std::function<void()> &&callback) {
82+
inspectorThread->InvokeElsePost([callback]() { callback(); });
83+
});
84+
85+
std::weak_ptr<facebook::react::jsinspector_modern::HostTarget> weakInspectorTarget = m_inspectorTarget;
86+
facebook::react::jsinspector_modern::InspectorTargetCapabilities capabilities;
87+
#ifdef HAS_FUSEBOX_CAPABILITIES // Remove after syncing past https://github.com/facebook/react-native/pull/43689
88+
capabilities.nativePageReloads = true;
89+
capabilities.prefersFuseboxFrontend = true;
90+
#endif
91+
m_inspectorPageId = facebook::react::jsinspector_modern::getInspectorInstance().addPage(
92+
"React Native Windows (Experimental)",
93+
/* vm */ "",
94+
[weakInspectorTarget](std::unique_ptr<facebook::react::jsinspector_modern::IRemoteConnection> remote)
95+
-> std::unique_ptr<facebook::react::jsinspector_modern::ILocalConnection> {
96+
if (const auto inspectorTarget = weakInspectorTarget.lock()) {
97+
facebook::react::jsinspector_modern::HostTarget::SessionMetadata sessionMetadata;
98+
sessionMetadata.integrationName = "React Native Windows (Host)";
99+
return inspectorTarget->connect(std::move(remote), sessionMetadata);
100+
}
101+
102+
// This can happen if we're about to be dealloc'd. Reject the connection.
103+
return nullptr;
104+
},
105+
capabilities);
106+
}
107+
}
108+
109+
ReactNativeHost::~ReactNativeHost() noexcept {
110+
if (m_inspectorPageId.has_value()) {
111+
facebook::react::jsinspector_modern::getInspectorInstance().removePage(*m_inspectorPageId);
112+
m_inspectorPageId.reset();
113+
m_inspectorTarget.reset();
114+
}
40115
}
41116

42117
/*static*/ ReactNative::ReactNativeHost ReactNativeHost::FromContext(
@@ -197,4 +272,10 @@ Mso::React::IReactHost *ReactNativeHost::ReactHost() noexcept {
197272
return m_reactHost.Get();
198273
}
199274

275+
#ifdef HAS_FUSEBOX_PAUSED_OVERLAY // Remove after syncing past https://github.com/facebook/react-native/pull/44078
276+
void ReactNativeHost::OnDebuggerResume() noexcept {
277+
m_inspectorTarget->sendCommand(facebook::react::jsinspector_modern::HostCommand::DebuggerResume);
278+
}
279+
#endif
280+
200281
} // namespace winrt::Microsoft::ReactNative::implementation

vnext/Microsoft.ReactNative/ReactNativeHost.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
#include "ReactNativeHost.g.h"
77

8+
#include <dispatchQueue/dispatchQueue.h>
9+
#include <jsinspector-modern/HostTarget.h>
810
#include "NativeModulesProvider.h"
911
#include "ReactHost/React.h"
1012
#include "ReactInstanceSettings.h"
@@ -16,6 +18,7 @@ namespace winrt::Microsoft::ReactNative::implementation {
1618
struct ReactNativeHost : ReactNativeHostT<ReactNativeHost> {
1719
public: // ReactNativeHost ABI API
1820
ReactNativeHost() noexcept;
21+
~ReactNativeHost() noexcept;
1922

2023
static ReactNative::ReactNativeHost FromContext(ReactNative::IReactContext const &reactContext) noexcept;
2124

@@ -25,6 +28,7 @@ struct ReactNativeHost : ReactNativeHostT<ReactNativeHost> {
2528
// property InstanceSettings
2629
ReactNative::ReactInstanceSettings InstanceSettings() noexcept;
2730
void InstanceSettings(ReactNative::ReactInstanceSettings const &value) noexcept;
31+
void OnDebuggerResume() noexcept;
2832

2933
winrt::Windows::Foundation::IAsyncAction LoadInstance() noexcept;
3034
winrt::Windows::Foundation::IAsyncAction ReloadInstance() noexcept;
@@ -39,6 +43,11 @@ struct ReactNativeHost : ReactNativeHostT<ReactNativeHost> {
3943

4044
ReactNative::ReactInstanceSettings m_instanceSettings{nullptr};
4145
ReactNative::IReactPackageBuilder m_packageBuilder;
46+
47+
std::shared_ptr<Mso::DispatchQueue> m_inspectorThread{nullptr};
48+
std::shared_ptr<facebook::react::jsinspector_modern::HostTargetDelegate> m_inspectorHostDelegate{nullptr};
49+
std::shared_ptr<facebook::react::jsinspector_modern::HostTarget> m_inspectorTarget{nullptr};
50+
std::optional<int32_t> m_inspectorPageId{std::nullopt};
4251
};
4352

4453
} // namespace winrt::Microsoft::ReactNative::implementation

vnext/ReactCommon/ReactCommon.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
<ClInclude Include="$(ReactNativeDir)\ReactCommon\cxxreact\SystraceSection.h" />
110110
<ClInclude Include="$(ReactNativeDir)\ReactCommon\jsiexecutor\jsireact\JSIExecutor.h" />
111111
<ClInclude Include="$(ReactNativeDir)\ReactCommon\jsiexecutor\jsireact\JSINativeModules.h" />
112+
<ClInclude Include="$(ReactNativeDir)\ReactCommon\jsinspector-modern\InspectorFlags.h" />
112113
<ClInclude Include="$(ReactNativeDir)\ReactCommon\jsinspector-modern\InspectorInterfaces.h" />
113114
<ClInclude Include="$(ReactNativeDir)\ReactCommon\logger\react_native_log.h" />
114115
<ClInclude Include="$(YogaDir)\yoga\YGEnums.h" />
@@ -131,6 +132,7 @@
131132
<ClCompile Include="$(ReactNativeDir)\ReactCommon\jsi\jsi\JSIDynamic.cpp" />
132133
<ClCompile Include="$(ReactNativeDir)\ReactCommon\jsiexecutor\jsireact\JSIExecutor.cpp" />
133134
<ClCompile Include="$(ReactNativeDir)\ReactCommon\jsiexecutor\jsireact\JSINativeModules.cpp" />
135+
<ClCompile Include="$(ReactNativeDir)\ReactCommon\jsinspector-modern\InspectorFlags.cpp" />
134136
<ClCompile Include="$(ReactNativeDir)\ReactCommon\jsinspector-modern\InspectorInterfaces.cpp" />
135137
<ClCompile Include="$(ReactNativeDir)\ReactCommon\logger\react_native_log.cpp" />
136138
<CLCompile Include="$(ReactNativeDir)\ReactCommon\reactperflogger\reactperflogger\BridgeNativeModulePerfLogger.cpp" />

0 commit comments

Comments
 (0)